xref: /freebsd/contrib/bmake/mk/dpadd.mk (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1# $Id: dpadd.mk,v 1.31 2023/11/25 01:07:49 sjg Exp $
2#
3#	@(#) Copyright (c) 2004-2023, Simon J. Gerraty
4#
5#	This file is provided in the hope that it will
6#	be of use.  There is absolutely NO WARRANTY.
7#	Permission to copy, redistribute or otherwise
8#	use this file is hereby granted provided that
9#	the above copyright notice and this notice are
10#	left intact.
11#
12#	Please send copies of changes and bug-fixes to:
13#	sjg@crufty.net
14#
15
16##
17# DESCRIPTION:
18#	This makefile manages a number of variables that simplify
19#	dealing with libs in a build.
20#
21#	Primary inputs are DPLIBS, DPADD and SRC_LIBS:
22#
23#	DPLIBS
24#		List of LIB* that we will actually link with
25#		should be in correct link order.
26#		DPLIBS is a short-cut to ensure that DPADD and LDADD are
27#		kept in sync.
28#
29#	DPADD	List of LIB* that should already be built.
30#
31#	SRC_LIBS
32#		List of LIB* that we want headers from, we do *not*
33#		require that such libs have been built.
34#
35#	The above all get added to DPMAGIC_LIBS which is what we
36#	process.
37#
38#	We expect LIB* to be set to absolute path of a library -
39#	suitable for putting in DPADD.
40#	eg.
41#
42#		LIBC ?= ${OBJTOP}/lib/libc/libc.a
43#
44#	From such a path we can derrive a number of other variables
45#	for which we can supply sensible default values.
46#	We name all these variables for the basename of the library
47#	(libc in our example above -- ${__lib:T:R} in below):
48#
49#	LDADD_${__lib:T:R}:
50#		What should be added to LDADD (eg -lc)
51#
52#	OBJ_${__lib:T:R}:
53#		This is trivial - just the dirname of the built library.
54#
55#	SRC_${__lib:T:R}:
56#		Where the src for ${__lib} is, if LIB* is set as above
57#		we can simply substitute ${SRCTOP} for ${OBJTOP} in
58#		the dirname.
59#
60#	INCLUDES_${__lib:T:R}:
61#		What should be added to CFLAGS
62#
63#		If the directory ${SRC_${__lib:T:R}}/h exists we will
64#		only add -I${SRC_${__lib:T:R}}/h on the basis that
65#		this is where the public api is kept.
66#
67#		Otherwise default will be -I${OBJ_${__lib:T:R}}
68#		-I${SRC_${__lib:T:R}}
69#
70#	Note much of the above is skipped for staged libs
71#	eg.
72#		LIBC ?= ${STAGE_OBJTOP}/usr/lib/libc.a
73#
74#	Since we can safely assume that -I${STAGE_OBJTOP}/usr/include
75#	and -L${STAGE_OBJTOP}/usr/lib are sufficient, and we should
76#	have no need of anything else.
77#
78#	Sometimes things are more complicated so allow for
79#	DPLIBS to be qualified with each of the variables in
80#	DPLIBS_QUALIFIER_LIST (default is VAR_QUALIFIER_LIST same as
81#	init.mk)
82
83.if !target(__${.PARSEFILE}__)
84__${.PARSEFILE}__: .NOTMAIN
85
86# sometimes we play games with .CURDIR etc
87# _* hold the original values of .*
88_OBJDIR?= ${.OBJDIR}
89_CURDIR?= ${.CURDIR}
90
91.if ${_CURDIR} == ${SRCTOP}
92RELDIR=.
93RELTOP=.
94.else
95RELDIR?= ${_CURDIR:S,${SRCTOP}/,,}
96.if ${RELDIR} == ${_CURDIR}
97RELDIR?= ${_OBJDIR:S,${OBJTOP}/,,}
98.endif
99RELTOP?= ${RELDIR:C,[^/]+,..,g}
100.endif
101RELOBJTOP?= ${OBJTOP}
102RELSRCTOP?= ${SRCTOP}
103
104# we get included just about everywhere so this is handy...
105# C*DEBUG_XTRA are for defining on cmd line etc
106# so do not use in makefiles.
107.ifdef CFLAGS_DEBUG_XTRA
108CFLAGS_LAST += ${CFLAGS_DEBUG_XTRA}
109.endif
110.ifdef CXXFLAGS_DEBUG_XTRA
111CXXFLAGS_LAST += ${CXXFLAGS_DEBUG_XTRA}
112.endif
113
114.-include <local.dpadd.mk>
115
116# DPLIBS helps us ensure we keep DPADD and LDADD in sync
117DPLIBS_QUALIFIER_LIST ?= ${VAR_QUALIFIER_LIST}
118DPLIBS += ${DPLIBS_QUALIFIER_LIST:u:@Q@${DPLIBS.$Q:U}@}
119DPLIBS+= ${DPLIBS_LAST} ${DPLIBS_QUALIFIER_LIST:u:@Q@${DPLIBS_LAST.$Q:U}@}
120DPADD+= ${DPLIBS:N-*}
121.for __lib in ${DPLIBS}
122.if "${__lib:M-*}" != ""
123LDADD += ${__lib}
124.else
125LDADD += ${LDADD_${__lib:T:R}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}}
126.endif
127.endfor
128
129# DPADD can contain things other than libs
130__dpadd_libs := ${DPADD:M*/lib*}
131
132.if defined(PROG) && ${MK_PROG_LDORDER_MK:Uno} != "no"
133# some libs have dependencies...
134# DPLIBS_* allows bsd.libnames.mk to flag libs which must be included
135# in DPADD for a given library.
136# Gather all such dependencies into __ldadd_all_xtras
137# dups will be dealt with later.
138# Note: libfoo_pic uses DPLIBS_libfoo
139__ldadd_all_xtras=
140.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}@}@}
141__ldadd_all_xtras+= ${LDADD_${__lib}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}}
142.if "${DPADD:M${__lib}}" == ""
143DPADD+= ${__lib}
144.endif
145.endfor
146.endif
147# Last of all... for libc and libgcc
148DPADD+= ${DPADD_LAST}
149
150# de-dupuplicate __ldadd_all_xtras into __ldadd_xtras
151# in reverse order so that libs end up listed after all that needed them.
152__ldadd_xtras=
153.for __lib in ${__ldadd_all_xtras:[-1..1]}
154.if "${__ldadd_xtras:M${__lib}}" == "" || ${NEED_IMPLICIT_LDADD:tl:Uno} != "no"
155__ldadd_xtras+= ${__lib}
156.endif
157.endfor
158
159.if !empty(__ldadd_xtras)
160# now back to the original order
161__ldadd_xtras:= ${__ldadd_xtras:[-1..1]}
162LDADD+= ${__ldadd_xtras}
163.endif
164
165# Convert DPADD into -I and -L options and add them to CPPFLAGS and LDADD
166# For the -I's convert the path to a relative one.  For separate objdirs
167# the DPADD paths will be to the obj tree so we need to subst anyway.
168
169# update this
170__dpadd_libs := ${DPADD:M*/lib*}
171
172# Order -L's to search ours first.
173# Avoids picking up old versions already installed.
174__dpadd_libdirs := ${__dpadd_libs:R:H:S/^/-L/g:O:u:N-L}
175LDADD += ${__dpadd_libdirs:M-L${OBJTOP}/*}
176LDADD += ${__dpadd_libdirs:N-L${OBJTOP}/*:N-L${HOST_LIBDIR:U/usr/lib}}
177.if defined(HOST_LIBDIR) && ${HOST_LIBDIR} != "/usr/lib"
178LDADD+= -L${HOST_LIBDIR}
179.endif
180
181.if !make(dpadd)
182.ifdef LIB
183# Each lib is its own src_lib, we want to include it in SRC_LIBS
184# so that the correct INCLUDES_* will be picked up automatically.
185SRC_LIBS+= ${_OBJDIR}/lib${LIB}.a
186.endif
187.endif
188
189#
190# This little bit of magic, assumes that SRC_libfoo will be
191# set if it cannot be correctly derrived from ${LIBFOO}
192# Note that SRC_libfoo and INCLUDES_libfoo should be named for the
193# actual library name not the variable name that might refer to it.
194# 99% of the time the two are the same, but the DPADD logic
195# only has the library name available, so stick to that.
196#
197
198SRC_LIBS?=
199# magic_libs includes those we want to link with
200# as well as those we might look at
201__dpadd_magic_libs += ${__dpadd_libs} ${SRC_LIBS}
202DPMAGIC_LIBS += ${__dpadd_magic_libs} \
203	${__dpadd_magic_libs:@d@${DPMAGIC_LIBS_${d:T:R}}@}
204
205# we skip this for staged libs
206.for __lib in ${DPMAGIC_LIBS:O:u:N${STAGE_OBJTOP:Unot}*/lib/*}
207#
208# if SRC_libfoo is not set, then we assume that the srcdir corresponding
209# to where we found the library is correct.
210#
211SRC_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELSRCTOP},}
212#
213# This is a no-brainer but just to be complete...
214#
215OBJ_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELOBJTOP},}
216#
217# If INCLUDES_libfoo is not set, then we'll use ${SRC_libfoo}/h if it exists,
218# else just ${SRC_libfoo}.
219#
220.if !empty(SRC_${__lib:T:R})
221INCLUDES_${__lib:T:R} ?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h:${SRC_${__lib:T:R}}}
222.endif
223.endfor
224
225# even for staged libs we sometimes
226# need to allow direct -I to avoid cicular dependencies
227.for __lib in ${DPMAGIC_LIBS:O:u:T:R}
228.if !empty(SRC_${__lib}) && empty(INCLUDES_${__lib})
229# must be a staged lib
230.if exists(${SRC_${__lib}}/h)
231INCLUDES_${__lib} = -I${SRC_${__lib}}/h
232.else
233INCLUDES_${__lib} = -I${SRC_${__lib}}
234.endif
235.endif
236.endfor
237
238# when linking a shared lib, avoid non pic libs
239SHLDADD+= ${LDADD:N-[lL]*}
240.for __lib in ${__dpadd_libs:u}
241.if defined(SHLIB_NAME) && ${LDADD:M-l${__lib:T:R:S,lib,,}} != ""
242.if ${__lib:T:N*_pic.a:N*.so} == "" || exists(${__lib:R}.so)
243SHLDADD+= -l${__lib:T:R:S,lib,,}
244.elif exists(${__lib:R}_pic.a)
245SHLDADD+= -l${__lib:T:R:S,lib,,}_pic
246.else
247.warning ${RELDIR}.${TARGET_SPEC} needs ${__lib:T:R}_pic.a
248SHLDADD+= -l${__lib:T:R:S,lib,,}
249.endif
250SHLDADD+= -L${__lib:H}
251.endif
252.endfor
253
254# Now for the bits we actually need
255__dpadd_incs=
256.for __lib in ${__dpadd_libs:u}
257.if (make(${PROG}_p) || defined(NEED_GPROF)) && exists(${__lib:R}_p.a)
258__ldadd=-l${__lib:T:R:S,lib,,}
259LDADD := ${LDADD:S,^${__ldadd}$,${__ldadd}_p,g}
260.endif
261.endfor
262
263#
264# We take care of duplicate suppression later.
265# don't apply :T:R too early
266__dpadd_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_${x:T:R}}@}
267__dpadd_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_${x:T:R}}@}
268
269__dpadd_last_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_LAST_${x:T:R}}@}
270__dpadd_last_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_LAST_${x:T:R}}@}
271
272.if defined(HOSTPROG) || ${MACHINE:Nhost*} == ""
273# we want any -I/usr/* last
274__dpadd_last_incs := \
275	${__dpadd_last_incs:N-I/usr/*} \
276	${__dpadd_incs:M-I/usr/*} \
277	${__dpadd_last_incs:M-I/usr/*}
278__dpadd_incs := ${__dpadd_incs:N-I/usr/*}
279.endif
280
281#
282# eliminate any duplicates - but don't mess with the order
283# force evaluation now - to avoid giving make a headache
284#
285.for t in CFLAGS CXXFLAGS
286# avoid duplicates
287__$t_incs:=${$t:M-I*:O:u}
288.for i in ${__dpadd_incs}
289.if "${__$t_incs:M$i}" == ""
290$t+= $i
291__$t_incs+= $i
292.endif
293.endfor
294.endfor
295
296.for t in CFLAGS_LAST CXXFLAGS_LAST
297# avoid duplicates
298__$t_incs:=${$t:M-I*:u}
299.for i in ${__dpadd_last_incs}
300.if "${__$t_incs:M$i}" == ""
301$t+= $i
302__$t_incs+= $i
303.endif
304.endfor
305.endfor
306
307# This target is used to gather a list of
308# dir: ${DPADD}
309# entries
310.if make(*dpadd*)
311.if !target(dpadd)
312dpadd:	.NOTMAIN
313.if defined(DPADD) && ${DPADD} != ""
314	@echo "${RELDIR}: ${DPADD:S,${OBJTOP}/,,}"
315.endif
316.endif
317.endif
318
319.ifdef SRC_PATHADD
320# We don't want to assume that we need to .PATH every element of
321# SRC_LIBS, but the Makefile cannot do
322# .PATH: ${SRC_libfoo}
323# since the value of SRC_libfoo must be available at the time .PATH:
324# is read - and we only just worked it out.
325# Further, they can't wait until after include of {lib,prog}.mk as
326# the .PATH is needed before then.
327# So we let the Makefile do
328# SRC_PATHADD+= ${SRC_libfoo}
329# and we defer the .PATH: until now so that SRC_libfoo will be available.
330.PATH: ${SRC_PATHADD}
331.endif
332
333# after all that, if doing -n we don't care
334.if ${.MAKEFLAGS:Ux:M-n} != ""
335DPADD =
336.elif ${.MAKE.MODE:Mmeta*} != "" && exists(${.MAKE.DEPENDFILE})
337DPADD_CLEAR_DPADD ?= yes
338.if ${DPADD_CLEAR_DPADD} == "yes"
339# save this
340__dpadd_libs := ${__dpadd_libs}
341# we have made what use of it we can of DPADD
342DPADD =
343.endif
344.endif
345
346.endif
347