1 # $Id: ldorder.mk,v 1.18 2018/02/11 18:27:59 sjg Exp $
3 # @(#) Copyright (c) 2015, Simon J. Gerraty
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
12 # Please send copies of changes and bug-fixes to:
16 # Try to compute optimal link order.
17 # When using only shared libs link order does not much matter,
18 # but archive libs are a different matter.
20 # We can construct a graph of .ldorder-lib${LIB*} dependencies
21 # and associate each with _LDORDER_USE to output the relevant
23 # Due to the nature of make, the result will be in the reverse order
24 # that we want to feed to ld.
25 # So we need to reverse it before use.
27 .if !target(_LDORDER_USE)
28 # does caller want to use ldorder?
29 # yes for prog, normally no for lib
30 _ldorder_use := ${.ALLTARGETS:Mldorder}
32 .-include <local.ldorder.mk>
34 # convert /path/to/libfoo.a into _{LIBFOO}
35 LDORDER_INC_FILTER += S,+,PLUS,g S,.so$$,,g
36 LDORDER_LIBS_FILTER += O:u
37 LDORDER_INC ?= ldorder.inc
40 _LDORDER_USE: .ldorder-rm .USE .NOTMAIN
41 @echo depends: ${.ALLSRC:M.ldorder-lib*} > /dev/null
42 @echo ${LDADD_${.TARGET:T:S,.ldorder-,,}:U${.TARGET:T:S/.ldorder-lib/-l/}} >> .ldorder
45 # we need to truncate our working file
47 @rm -f .ldorder ldorder-*
48 @${.ALLSRC:O:u:@f@${REFERENCE_FILE} < $f;@}
51 # make sure this exists
54 # and finally we need to reverse the order of content
55 ldorder: .ldorder .NOTMAIN
56 @{ test ! -s .ldorder || cat -n .ldorder | sort -rn | \
57 sed '/ldorder-/d;s,^[[:space:]0-9]*,,'; } > ${.TARGET}
59 # Initially we hook contents of DPLIBS and DPADD into our graph
60 LDORDER_LIBS ?= ${DPLIBS} ${DPADD:M*/lib*} ${__dpadd_libs}
61 # we need to remember this
62 _LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}}
64 .if empty(_LDORDER_LIBS)
65 # don't use stale ldorder
68 # this is how you use it
69 LDADD_LDORDER ?= `cat ldorder`
73 _ldorder = ${RELDIR}.${TARGET_SPEC}
75 .endif # !target(_LDORDER_USE)
77 .if !empty(LDORDER_LIBS) && !empty(_ldorder_use)
78 # canonicalize - these are just tokens anyway
79 LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}:R:C/\.so.*//}
80 _ldorders := ${LDORDER_LIBS:T:Mlib*:S,^,.ldorder-,}
82 .for t in ${_ldorders}
88 # and this makes it all happen
89 .ldorder: ${_ldorders}
91 # this is how we get the dependencies
92 .if ${.INCLUDEDFROMFILE:M*.${LDORDER_INC}} != ""
93 _ldorder := .ldorder-${.INCLUDEDFROMFILE:S/.${LDORDER_INC}//}
94 ${_ldorder}: ${_ldorders}
95 .ldorder-rm: ${.INCLUDEDFROMDIR}/${.INCLUDEDFROMFILE}
98 # set DEBUG_LDORDER to pattern[s] that match the dirs of interest
99 .if ${DEBUG_LDORDER:Uno:@x@${RELDIR:M$x}@} != ""
100 .info ${_ldorder}: ${_ldorders}
103 # now try to find more ...
104 # each *.${LDORDER_INC} should set LDORDER_LIBS to what it needs
105 # it can also add to CFLAGS etc.
106 .for __inc in ${LDORDER_LIBS:S,$,.${LDORDER_INC},}
107 .if !target(__${__inc}__)
109 # make sure this is reset
115 .endif # !empty(LDORDER_LIBS)
118 # you can make this depend on files (must match *ldorder*)
119 # to add extra content - like CFLAGS
120 libLDORDER_INC = lib${LIB}.${LDORDER_INC}
121 .if !commands(${libLDORDER_INC})
123 @(cat /dev/null ${.ALLSRC:M*ldorder*}; \
124 echo 'LDORDER_LIBS= ${_LDORDER_LIBS:T:R:${LDORDER_INC_FILTER:ts:}:tu:C,.*,_{&},}'; \
125 echo; echo '.include <ldorder.mk>' ) | sed 's,_{,$${,g' > ${.TARGET}