mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-02 12:53:33 +00:00
c59c3bf34d
Merge commit '368b06ce6b0135d6de13f7265f6dcbaeb791b3bb'
349 lines
9.9 KiB
Makefile
349 lines
9.9 KiB
Makefile
# SPDX-License-Identifier: BSD-2-Clause
|
|
#
|
|
# $Id: dpadd.mk,v 1.33 2024/02/17 17:26:57 sjg Exp $
|
|
#
|
|
# @(#) Copyright (c) 2004-2023, Simon J. Gerraty
|
|
#
|
|
# This file is provided in the hope that it will
|
|
# be of use. There is absolutely NO WARRANTY.
|
|
# Permission to copy, redistribute or otherwise
|
|
# use this file is hereby granted provided that
|
|
# the above copyright notice and this notice are
|
|
# left intact.
|
|
#
|
|
# Please send copies of changes and bug-fixes to:
|
|
# sjg@crufty.net
|
|
#
|
|
|
|
##
|
|
# DESCRIPTION:
|
|
# This makefile manages a number of variables that simplify
|
|
# dealing with libs in a build.
|
|
#
|
|
# Primary inputs are DPLIBS, DPADD and SRC_LIBS:
|
|
#
|
|
# DPLIBS
|
|
# List of LIB* that we will actually link with
|
|
# should be in correct link order.
|
|
# DPLIBS is a short-cut to ensure that DPADD and LDADD are
|
|
# kept in sync.
|
|
#
|
|
# DPADD List of LIB* that should already be built.
|
|
#
|
|
# SRC_LIBS
|
|
# List of LIB* that we want headers from, we do *not*
|
|
# require that such libs have been built.
|
|
#
|
|
# The above all get added to DPMAGIC_LIBS which is what we
|
|
# process.
|
|
#
|
|
# We expect LIB* to be set to absolute path of a library -
|
|
# suitable for putting in DPADD.
|
|
# eg.
|
|
#
|
|
# LIBC ?= ${OBJTOP}/lib/libc/libc.a
|
|
#
|
|
# From such a path we can derrive a number of other variables
|
|
# for which we can supply sensible default values.
|
|
# We name all these variables for the basename of the library
|
|
# (libc in our example above -- ${__lib:T:R} in below):
|
|
#
|
|
# LDADD_${__lib:T:R}:
|
|
# What should be added to LDADD (eg -lc)
|
|
#
|
|
# OBJ_${__lib:T:R}:
|
|
# This is trivial - just the dirname of the built library.
|
|
#
|
|
# SRC_${__lib:T:R}:
|
|
# Where the src for ${__lib} is, if LIB* is set as above
|
|
# we can simply substitute ${SRCTOP} for ${OBJTOP} in
|
|
# the dirname.
|
|
#
|
|
# INCLUDES_${__lib:T:R}:
|
|
# What should be added to CFLAGS
|
|
#
|
|
# If the directory ${SRC_${__lib:T:R}}/h exists we will
|
|
# only add -I${SRC_${__lib:T:R}}/h on the basis that
|
|
# this is where the public api is kept.
|
|
#
|
|
# Otherwise default will be -I${OBJ_${__lib:T:R}}
|
|
# -I${SRC_${__lib:T:R}}
|
|
#
|
|
# Note much of the above is skipped for staged libs
|
|
# eg.
|
|
# LIBC ?= ${STAGE_OBJTOP}/usr/lib/libc.a
|
|
#
|
|
# Since we can safely assume that -I${STAGE_OBJTOP}/usr/include
|
|
# and -L${STAGE_OBJTOP}/usr/lib are sufficient, and we should
|
|
# have no need of anything else.
|
|
#
|
|
# Sometimes things are more complicated so allow for
|
|
# DPLIBS to be qualified with each of the variables in
|
|
# DPLIBS_QUALIFIER_LIST (default is VAR_QUALIFIER_LIST same as
|
|
# init.mk)
|
|
|
|
.if !target(__${.PARSEFILE}__)
|
|
__${.PARSEFILE}__: .NOTMAIN
|
|
|
|
# sometimes we play games with .CURDIR etc
|
|
# _* hold the original values of .*
|
|
_OBJDIR?= ${.OBJDIR}
|
|
_CURDIR?= ${.CURDIR}
|
|
|
|
.if ${_CURDIR} == ${SRCTOP}
|
|
RELDIR=.
|
|
RELTOP=.
|
|
.else
|
|
RELDIR?= ${_CURDIR:S,${SRCTOP}/,,}
|
|
.if ${RELDIR} == ${_CURDIR}
|
|
RELDIR?= ${_OBJDIR:S,${OBJTOP}/,,}
|
|
.endif
|
|
RELTOP?= ${RELDIR:C,[^/]+,..,g}
|
|
.endif
|
|
RELOBJTOP?= ${OBJTOP}
|
|
RELSRCTOP?= ${SRCTOP}
|
|
|
|
# we get included just about everywhere so this is handy...
|
|
# C*DEBUG_XTRA are for defining on cmd line etc
|
|
# so do not use in makefiles.
|
|
.ifdef CFLAGS_DEBUG_XTRA
|
|
CFLAGS_LAST += ${CFLAGS_DEBUG_XTRA}
|
|
.endif
|
|
.ifdef CXXFLAGS_DEBUG_XTRA
|
|
CXXFLAGS_LAST += ${CXXFLAGS_DEBUG_XTRA}
|
|
.endif
|
|
|
|
.-include <local.dpadd.mk>
|
|
|
|
# DPLIBS helps us ensure we keep DPADD and LDADD in sync
|
|
DPLIBS_QUALIFIER_LIST ?= ${VAR_QUALIFIER_LIST}
|
|
DPLIBS += ${DPLIBS_QUALIFIER_LIST:u:@Q@${DPLIBS.$Q:U}@}
|
|
DPLIBS+= ${DPLIBS_LAST} ${DPLIBS_QUALIFIER_LIST:u:@Q@${DPLIBS_LAST.$Q:U}@}
|
|
DPADD+= ${DPLIBS:N-*}
|
|
.for __lib in ${DPLIBS}
|
|
.if "${__lib:M-*}" != ""
|
|
LDADD += ${__lib}
|
|
.else
|
|
LDADD += ${LDADD_${__lib:T:R}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}}
|
|
.endif
|
|
.endfor
|
|
|
|
# DPADD can contain things other than libs
|
|
__dpadd_libs := ${DPADD:M*/lib*}
|
|
|
|
.if defined(PROG) && ${MK_PROG_LDORDER_MK:Uno} != "no"
|
|
# some libs have dependencies...
|
|
# DPLIBS_* allows bsd.libnames.mk to flag libs which must be included
|
|
# in DPADD for a given library.
|
|
# Gather all such dependencies into __ldadd_all_xtras
|
|
# dups will be dealt with later.
|
|
# Note: libfoo_pic uses DPLIBS_libfoo
|
|
__ldadd_all_xtras=
|
|
.for __lib in ${__dpadd_libs:@d@${DPLIBS_${d:T:R:S,_pic,,}} ${DPLIBS_QUALIFIER_LIST:u:@Q@${DPLIBS_${d:T:R:S,_pic,,}.$Q:U}@}@}
|
|
__ldadd_all_xtras+= ${LDADD_${__lib}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}}
|
|
.if "${DPADD:M${__lib}}" == ""
|
|
DPADD+= ${__lib}
|
|
.endif
|
|
.endfor
|
|
.endif
|
|
# Last of all... for libc and libgcc
|
|
DPADD+= ${DPADD_LAST}
|
|
|
|
# de-dupuplicate __ldadd_all_xtras into __ldadd_xtras
|
|
# in reverse order so that libs end up listed after all that needed them.
|
|
__ldadd_xtras=
|
|
.for __lib in ${__ldadd_all_xtras:[-1..1]}
|
|
.if "${__ldadd_xtras:M${__lib}}" == "" || ${NEED_IMPLICIT_LDADD:tl:Uno} != "no"
|
|
__ldadd_xtras+= ${__lib}
|
|
.endif
|
|
.endfor
|
|
|
|
.if !empty(__ldadd_xtras)
|
|
# now back to the original order
|
|
__ldadd_xtras:= ${__ldadd_xtras:[-1..1]}
|
|
LDADD+= ${__ldadd_xtras}
|
|
.endif
|
|
|
|
# Convert DPADD into -I and -L options and add them to CPPFLAGS and LDADD
|
|
# For the -I's convert the path to a relative one. For separate objdirs
|
|
# the DPADD paths will be to the obj tree so we need to subst anyway.
|
|
|
|
# update this
|
|
__dpadd_libs := ${DPADD:M*/lib*}
|
|
|
|
# Order -L's to search ours first.
|
|
# Avoids picking up old versions already installed.
|
|
__dpadd_libdirs := ${__dpadd_libs:R:H:S/^/-L/g:O:u:N-L}
|
|
LDADD += ${__dpadd_libdirs:M-L${OBJTOP}/*}
|
|
LDADD += ${__dpadd_libdirs:N-L${OBJTOP}/*:N-L${HOST_LIBDIR:U/usr/lib}}
|
|
.if defined(HOST_LIBDIR) && ${HOST_LIBDIR} != "/usr/lib"
|
|
LDADD+= -L${HOST_LIBDIR}
|
|
.endif
|
|
|
|
.if !make(dpadd)
|
|
.ifdef LIB
|
|
# Each lib is its own src_lib, we want to include it in SRC_LIBS
|
|
# so that the correct INCLUDES_* will be picked up automatically.
|
|
SRC_LIBS+= ${_OBJDIR}/lib${LIB}.a
|
|
.endif
|
|
.endif
|
|
|
|
#
|
|
# This little bit of magic, assumes that SRC_libfoo will be
|
|
# set if it cannot be correctly derrived from ${LIBFOO}
|
|
# Note that SRC_libfoo and INCLUDES_libfoo should be named for the
|
|
# actual library name not the variable name that might refer to it.
|
|
# 99% of the time the two are the same, but the DPADD logic
|
|
# only has the library name available, so stick to that.
|
|
#
|
|
|
|
SRC_LIBS?=
|
|
# magic_libs includes those we want to link with
|
|
# as well as those we might look at
|
|
__dpadd_magic_libs += ${__dpadd_libs} ${SRC_LIBS}
|
|
DPMAGIC_LIBS += ${__dpadd_magic_libs} \
|
|
${__dpadd_magic_libs:@d@${DPMAGIC_LIBS_${d:T:R}}@}
|
|
|
|
# we skip this for staged libs
|
|
.for __lib in ${DPMAGIC_LIBS:O:u:N${STAGE_OBJTOP:Unot}*/lib/*}
|
|
#
|
|
# if SRC_libfoo is not set, then we assume that the srcdir corresponding
|
|
# to where we found the library is correct.
|
|
#
|
|
SRC_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELSRCTOP},}
|
|
#
|
|
# This is a no-brainer but just to be complete...
|
|
#
|
|
OBJ_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELOBJTOP},}
|
|
#
|
|
# If INCLUDES_libfoo is not set, then we'll use ${SRC_libfoo}/h if it exists,
|
|
# else just ${SRC_libfoo}.
|
|
#
|
|
.if !empty(SRC_${__lib:T:R})
|
|
INCLUDES_${__lib:T:R} ?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h:${SRC_${__lib:T:R}}}
|
|
.endif
|
|
.endfor
|
|
|
|
# even for staged libs we sometimes
|
|
# need to allow direct -I to avoid cicular dependencies
|
|
.for __lib in ${DPMAGIC_LIBS:O:u:T:R}
|
|
.if !empty(SRC_${__lib}) && empty(INCLUDES_${__lib})
|
|
# must be a staged lib
|
|
.if exists(${SRC_${__lib}}/h)
|
|
INCLUDES_${__lib} = -I${SRC_${__lib}}/h
|
|
.else
|
|
INCLUDES_${__lib} = -I${SRC_${__lib}}
|
|
.endif
|
|
.endif
|
|
.endfor
|
|
|
|
# when linking a shared lib, avoid non pic libs
|
|
SHLDADD+= ${LDADD:N-[lL]*}
|
|
.for __lib in ${__dpadd_libs:u}
|
|
.if defined(SHLIB_NAME) && ${LDADD:M-l${__lib:T:R:S,lib,,}} != ""
|
|
.if ${__lib:T:N*_pic.a:N*.so} == "" || exists(${__lib:R}.so)
|
|
SHLDADD+= -l${__lib:T:R:S,lib,,}
|
|
.elif exists(${__lib:R}_pic.a)
|
|
SHLDADD+= -l${__lib:T:R:S,lib,,}_pic
|
|
.else
|
|
.warning ${RELDIR}.${TARGET_SPEC} needs ${__lib:T:R}_pic.a
|
|
SHLDADD+= -l${__lib:T:R:S,lib,,}
|
|
.endif
|
|
SHLDADD+= -L${__lib:H}
|
|
.endif
|
|
.endfor
|
|
|
|
# Now for the bits we actually need
|
|
__dpadd_incs=
|
|
.for __lib in ${__dpadd_libs:u}
|
|
.if (make(${PROG:U}_p) || defined(NEED_GPROF)) && exists(${__lib:R}_p.a)
|
|
__ldadd=-l${__lib:T:R:S,lib,,}
|
|
LDADD := ${LDADD:S,^${__ldadd}$,${__ldadd}_p,g}
|
|
.endif
|
|
.endfor
|
|
|
|
#
|
|
# We take care of duplicate suppression later.
|
|
# don't apply :T:R too early
|
|
__dpadd_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_${x:T:R}}@}
|
|
__dpadd_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_${x:T:R}}@}
|
|
|
|
__dpadd_last_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_LAST_${x:T:R}}@}
|
|
__dpadd_last_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_LAST_${x:T:R}}@}
|
|
|
|
.if defined(HOSTPROG) || ${MACHINE:Nhost*} == ""
|
|
# we want any -I/usr/* last
|
|
__dpadd_last_incs := \
|
|
${__dpadd_last_incs:N-I/usr/*} \
|
|
${__dpadd_incs:M-I/usr/*} \
|
|
${__dpadd_last_incs:M-I/usr/*}
|
|
__dpadd_incs := ${__dpadd_incs:N-I/usr/*}
|
|
.endif
|
|
|
|
#
|
|
# eliminate any duplicates - but don't mess with the order
|
|
# force evaluation now - to avoid giving make a headache
|
|
#
|
|
.for t in CFLAGS CXXFLAGS
|
|
# avoid duplicates
|
|
__$t_incs:=${$t:M-I*:O:u}
|
|
.for i in ${__dpadd_incs}
|
|
.if "${__$t_incs:M$i}" == ""
|
|
$t+= $i
|
|
__$t_incs+= $i
|
|
.endif
|
|
.endfor
|
|
.endfor
|
|
|
|
.for t in CFLAGS_LAST CXXFLAGS_LAST
|
|
# avoid duplicates
|
|
__$t_incs:=${$t:M-I*:u}
|
|
.for i in ${__dpadd_last_incs}
|
|
.if "${__$t_incs:M$i}" == ""
|
|
$t+= $i
|
|
__$t_incs+= $i
|
|
.endif
|
|
.endfor
|
|
.endfor
|
|
|
|
# This target is used to gather a list of
|
|
# dir: ${DPADD}
|
|
# entries
|
|
.if make(*dpadd*)
|
|
.if !target(dpadd)
|
|
dpadd: .NOTMAIN
|
|
.if defined(DPADD) && ${DPADD} != ""
|
|
@echo "${RELDIR}: ${DPADD:S,${OBJTOP}/,,}"
|
|
.endif
|
|
.endif
|
|
.endif
|
|
|
|
.ifdef SRC_PATHADD
|
|
# We don't want to assume that we need to .PATH every element of
|
|
# SRC_LIBS, but the Makefile cannot do
|
|
# .PATH: ${SRC_libfoo}
|
|
# since the value of SRC_libfoo must be available at the time .PATH:
|
|
# is read - and we only just worked it out.
|
|
# Further, they can't wait until after include of {lib,prog}.mk as
|
|
# the .PATH is needed before then.
|
|
# So we let the Makefile do
|
|
# SRC_PATHADD+= ${SRC_libfoo}
|
|
# and we defer the .PATH: until now so that SRC_libfoo will be available.
|
|
.PATH: ${SRC_PATHADD}
|
|
.endif
|
|
|
|
# after all that, if doing -n we don't care
|
|
.if ${.MAKEFLAGS:Ux:M-n} != ""
|
|
DPADD =
|
|
.elif ${.MAKE.MODE:Mmeta*} != "" && exists(${.MAKE.DEPENDFILE})
|
|
DPADD_CLEAR_DPADD ?= yes
|
|
.if ${DPADD_CLEAR_DPADD} == "yes"
|
|
# save this
|
|
__dpadd_libs := ${__dpadd_libs}
|
|
# we have made what use of it we can of DPADD
|
|
DPADD =
|
|
.endif
|
|
.endif
|
|
|
|
.endif
|