xref: /dflybsd-src/contrib/bmake/mk/ldorder.mk (revision 9e7ae5a0527a977cab412aede3a532cfe2903bbb)
1*6eef5f0cSAntonio Huete Jimenez# $Id: ldorder.mk,v 1.26 2021/12/08 05:56:50 sjg Exp $
2ca58f742SDaniel Fojt#
3ca58f742SDaniel Fojt#	@(#) Copyright (c) 2015, Simon J. Gerraty
4ca58f742SDaniel Fojt#
5ca58f742SDaniel Fojt#	This file is provided in the hope that it will
6ca58f742SDaniel Fojt#	be of use.  There is absolutely NO WARRANTY.
7ca58f742SDaniel Fojt#	Permission to copy, redistribute or otherwise
8ca58f742SDaniel Fojt#	use this file is hereby granted provided that
9ca58f742SDaniel Fojt#	the above copyright notice and this notice are
10ca58f742SDaniel Fojt#	left intact.
11ca58f742SDaniel Fojt#
12ca58f742SDaniel Fojt#	Please send copies of changes and bug-fixes to:
13ca58f742SDaniel Fojt#	sjg@crufty.net
14ca58f742SDaniel Fojt#
15ca58f742SDaniel Fojt
16ca58f742SDaniel Fojt# Try to compute optimal link order.
17ca58f742SDaniel Fojt# When using only shared libs link order does not much matter,
18ca58f742SDaniel Fojt# but archive libs are a different matter.
19ca58f742SDaniel Fojt
20ca58f742SDaniel Fojt# We can construct a graph of .ldorder-lib${LIB*} dependencies
21ca58f742SDaniel Fojt# and associate each with _LDORDER_USE to output the relevant
22ca58f742SDaniel Fojt# ld flags.
23ca58f742SDaniel Fojt# Due to the nature of make, the result will be in the reverse order
24ca58f742SDaniel Fojt# that we want to feed to ld.
25ca58f742SDaniel Fojt# So we need to reverse it before use.
26ca58f742SDaniel Fojt
27ca58f742SDaniel Fojt.if !target(_LDORDER_USE)
28ca58f742SDaniel Fojt# does caller want to use ldorder?
29ca58f742SDaniel Fojt# yes for prog, normally no for lib
30ca58f742SDaniel Fojt.if ${.ALLTARGETS:Mldorder} != ""
31ca58f742SDaniel Fojt_ldorder_use:
32ca58f742SDaniel Fojt.endif
33ca58f742SDaniel Fojt
34ca58f742SDaniel Fojt# define this if we need a barrier between local and external libs
35ca58f742SDaniel Fojt# see below
36ca58f742SDaniel FojtLDORDER_EXTERN_BARRIER ?= .ldorder-extern-barrier
37ca58f742SDaniel Fojt
38ca58f742SDaniel Fojt.-include <local.ldorder.mk>
39ca58f742SDaniel Fojt
40ca58f742SDaniel Fojt# convert /path/to/libfoo.a into _{LIBFOO}
41ca58f742SDaniel FojtLDORDER_INC_FILTER += S,+,PLUS,g S,.so$$,,g
42ca58f742SDaniel FojtLDORDER_LIBS_FILTER += O:u
43ca58f742SDaniel FojtLDORDER_INC ?= ldorder.inc
44ca58f742SDaniel Fojt# for meta mode
45ca58f742SDaniel FojtREFERENCE_FILE ?= :
46ca58f742SDaniel Fojt
47ca58f742SDaniel Fojt_LDORDER_USE: .ldorder-rm .USE .NOTMAIN
48ca58f742SDaniel Fojt	@echo depends: ${.ALLSRC:M.ldorder-lib*} > /dev/null
49ca58f742SDaniel Fojt	@echo ${LDADD_${.TARGET:T:S,.ldorder-,,}:U${.TARGET:T:S/.ldorder-lib/-l/}} >> .ldorder
50ca58f742SDaniel Fojt	@${META_COOKIE_TOUCH}
51ca58f742SDaniel Fojt
52ca58f742SDaniel Fojt# we need to truncate our working file
53ca58f742SDaniel Fojt.ldorder-rm: .NOTMAIN
54ca58f742SDaniel Fojt	@rm -f .ldorder ldorder-*
55ca58f742SDaniel Fojt	@${.ALLSRC:O:u:@f@${REFERENCE_FILE} < $f;@}
56ca58f742SDaniel Fojt	@${META_COOKIE_TOUCH}
57ca58f742SDaniel Fojt
58ca58f742SDaniel Fojt# make sure this exists
59ca58f742SDaniel Fojt.ldorder:	.NOTMAIN
60ca58f742SDaniel Fojt
61ca58f742SDaniel Fojt# and finally we need to reverse the order of content
62ca58f742SDaniel Fojtldorder: .ldorder .NOTMAIN
63ca58f742SDaniel Fojt	@{ test ! -s .ldorder || cat -n .ldorder | sort -rn | \
64ca58f742SDaniel Fojt	sed '/ldorder-/d;s,^[[:space:]0-9]*,,'; } > ${.TARGET}
65ca58f742SDaniel Fojt
66ca58f742SDaniel Fojt# Initially we hook contents of DPLIBS and DPADD into our graph
67ca58f742SDaniel FojtLDORDER_LIBS ?= ${DPLIBS} ${DPADD:M*/lib*} ${__dpadd_libs}
68ca58f742SDaniel Fojt# we need to remember this
69ca58f742SDaniel Fojt_LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}}
70ca58f742SDaniel Fojt
71ca58f742SDaniel Fojt.if empty(_LDORDER_LIBS)
72ca58f742SDaniel Fojt# don't use stale ldorder
73ca58f742SDaniel FojtLDADD_LDORDER =
74ca58f742SDaniel Fojt.else
75ca58f742SDaniel Fojt# this is how you use it
76ca58f742SDaniel FojtLDADD_LDORDER ?= `cat ldorder`
77ca58f742SDaniel Fojt.endif
78ca58f742SDaniel Fojt
79ca58f742SDaniel Fojt# for debug below
80ca58f742SDaniel Fojt_ldorder = ${RELDIR}.${TARGET_SPEC}
81ca58f742SDaniel Fojt
82ca58f742SDaniel Fojt# we make have some libs that exist outside of $SB
83ca58f742SDaniel Fojt# and want to insert a barrier
84ca58f742SDaniel Fojt.if target(${LDORDER_EXTERN_BARRIER})
85ca58f742SDaniel Fojt# eg. in local.ldorder.mk
86ca58f742SDaniel Fojt# ${LDORDER_EXTERN_BARRIER}:
87ca58f742SDaniel Fojt#	@test -z "${extern_ldorders}" || \
88ca58f742SDaniel Fojt#	echo -Wl,-Bdynamic >> .ldorder
89ca58f742SDaniel Fojt#
90ca58f742SDaniel Fojt# feel free to put more suitable version in local.ldorder.mk if needed
91ca58f742SDaniel Fojt# we do *not* count host libs in extern_ldorders
92ca58f742SDaniel Fojtextern_ldorders ?= ${__dpadd_libs:tA:N/lib*:N/usr/lib*:N${SB}/*:N${SB_OBJROOT:tA}*:T:${LDORDER_LIBS_FILTER:ts:}:R:C/\.so.*//:S,^,.ldorder-,:N.ldorder-}
93ca58f742SDaniel Fojtsb_ldorders ?= ${.ALLTARGETS:M.ldorder-*:N${LDORDER_EXTERN_BARRIER}:N.ldorder-rm:${extern_ldorders:${M_ListToSkip}}:N.ldorder-}
94ca58f742SDaniel Fojt
95ca58f742SDaniel Fojt# finally in Makefile after include of *.mk put
96ca58f742SDaniel Fojt# .ldorder ${sb_ldorders}: ${LDORDER_EXTERN_BARRIER}
97ca58f742SDaniel Fojt# ${LDORDER_EXTERN_BARRIER}: ${extern_ldorders}
98ca58f742SDaniel Fojt.endif
99ca58f742SDaniel Fojt
100ca58f742SDaniel Fojt.endif				# !target(_LDORDER_USE)
101ca58f742SDaniel Fojt
102ca58f742SDaniel Fojt.if !empty(LDORDER_LIBS) && target(_ldorder_use)
103ca58f742SDaniel Fojt# canonicalize - these are just tokens anyway
104ca58f742SDaniel FojtLDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}:R:C/\.so.*//}
105ca58f742SDaniel Fojt_ldorders := ${LDORDER_LIBS:T:Mlib*:S,^,.ldorder-,}
106ca58f742SDaniel Fojt
107ca58f742SDaniel Fojt.for t in ${_ldorders}
108ca58f742SDaniel Fojt.if !target($t)
109ca58f742SDaniel Fojt$t: _LDORDER_USE
110ca58f742SDaniel Fojt.endif
111ca58f742SDaniel Fojt.endfor
112ca58f742SDaniel Fojt
113ca58f742SDaniel Fojt# and this makes it all happen
114ca58f742SDaniel Fojt.ldorder: ${_ldorders}
115ca58f742SDaniel Fojt
116ca58f742SDaniel Fojt# this is how we get the dependencies
117ca58f742SDaniel Fojt.if ${.INCLUDEDFROMFILE:M*.${LDORDER_INC}} != ""
118ca58f742SDaniel Fojt_ldorder := .ldorder-${.INCLUDEDFROMFILE:S/.${LDORDER_INC}//}
119ca58f742SDaniel Fojt${_ldorder}: ${_ldorders}
120ca58f742SDaniel Fojt.ldorder-rm: ${.INCLUDEDFROMDIR}/${.INCLUDEDFROMFILE}
121ca58f742SDaniel Fojt.endif
122ca58f742SDaniel Fojt
123ca58f742SDaniel Fojt# set DEBUG_LDORDER to pattern[s] that match the dirs of interest
124ca58f742SDaniel Fojt.if ${DEBUG_LDORDER:Uno:@x@${RELDIR:M$x}@} != ""
125ca58f742SDaniel Fojt.info ${_ldorder}: ${_ldorders}
126ca58f742SDaniel Fojt.endif
127ca58f742SDaniel Fojt
128ca58f742SDaniel Fojt# now try to find more ...
129ca58f742SDaniel Fojt# each *.${LDORDER_INC} should set LDORDER_LIBS to what it needs
130ca58f742SDaniel Fojt# it can also add to CFLAGS etc.
131ca58f742SDaniel Fojt.for __inc in ${LDORDER_LIBS:S,$,.${LDORDER_INC},}
132ca58f742SDaniel Fojt.if !target(__${__inc}__)
133*6eef5f0cSAntonio Huete Jimenez__${__inc}__: .NOTMAIN
134ca58f742SDaniel Fojt# make sure this is reset
135ca58f742SDaniel FojtLDORDER_LIBS =
136ca58f742SDaniel Fojt_ldorders =
137ca58f742SDaniel Fojt.-include <${__inc}>
138ca58f742SDaniel Fojt.endif
139ca58f742SDaniel Fojt.endfor
140ca58f742SDaniel Fojt
141ca58f742SDaniel Fojt.endif				# !empty(LDORDER_LIBS)
142ca58f742SDaniel Fojt
143ca58f742SDaniel Fojt.ifdef LIB
144ca58f742SDaniel Fojt# you can make this depend on files (must match *ldorder*)
145ca58f742SDaniel Fojt# to add extra content - like CFLAGS
146ca58f742SDaniel FojtlibLDORDER_INC = lib${LIB}.${LDORDER_INC}
147ca58f742SDaniel Fojt.if !commands(${libLDORDER_INC})
148ca58f742SDaniel Fojt.if target(ldorder-header)
149ca58f742SDaniel Fojt${libLDORDER_INC}: ldorder-header
150ca58f742SDaniel Fojt.endif
151ca58f742SDaniel Fojt${libLDORDER_INC}:
152ca58f742SDaniel Fojt	@(cat /dev/null ${.ALLSRC:M*ldorder*}; \
153ca58f742SDaniel Fojt	echo 'LDORDER_LIBS= ${_LDORDER_LIBS:T:R:${LDORDER_INC_FILTER:ts:}:tu:C,.*,_{&},:N_{}}'; \
154ca58f742SDaniel Fojt	echo; echo '.include <ldorder.mk>' ) | sed 's,_{,$${,g' > ${.TARGET}
155ca58f742SDaniel Fojt.endif
156ca58f742SDaniel Fojt.endif
157