summaryrefslogtreecommitdiff
path: root/devel/bmake/files/mk/dpadd.mk
blob: cb67bf1827f3250331025b34e5087283c2e760f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# $Id: dpadd.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
#	@(#) Copyright (c) 2004, 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.
#
	
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:

# 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+= ${DPLIBS_LAST}
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,,}}@}
__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}.
#
INCLUDES_${__lib:T:R}?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h:${SRC_${__lib:T:R}}}

.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}_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