]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bmake/mk/ldorder.mk
tools/tools/locale: fix static-colldef
[FreeBSD/FreeBSD.git] / contrib / bmake / mk / ldorder.mk
1 # $Id: ldorder.mk,v 1.25 2018/04/24 23:50:26 sjg Exp $
2 #
3 #       @(#) Copyright (c) 2015, 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 # 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.
19
20 # We can construct a graph of .ldorder-lib${LIB*} dependencies
21 # and associate each with _LDORDER_USE to output the relevant
22 # ld flags.
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.
26
27 .if !target(_LDORDER_USE)
28 # does caller want to use ldorder?
29 # yes for prog, normally no for lib
30 .if ${.ALLTARGETS:Mldorder} != ""
31 _ldorder_use:
32 .endif
33
34 # define this if we need a barrier between local and external libs
35 # see below
36 LDORDER_EXTERN_BARRIER ?= .ldorder-extern-barrier
37
38 .-include <local.ldorder.mk>
39
40 # convert /path/to/libfoo.a into _{LIBFOO}
41 LDORDER_INC_FILTER += S,+,PLUS,g S,.so$$,,g
42 LDORDER_LIBS_FILTER += O:u
43 LDORDER_INC ?= ldorder.inc
44 # for meta mode
45 REFERENCE_FILE ?= :
46
47 _LDORDER_USE: .ldorder-rm .USE .NOTMAIN
48         @echo depends: ${.ALLSRC:M.ldorder-lib*} > /dev/null
49         @echo ${LDADD_${.TARGET:T:S,.ldorder-,,}:U${.TARGET:T:S/.ldorder-lib/-l/}} >> .ldorder
50         @${META_COOKIE_TOUCH}
51
52 # we need to truncate our working file
53 .ldorder-rm: .NOTMAIN
54         @rm -f .ldorder ldorder-*
55         @${.ALLSRC:O:u:@f@${REFERENCE_FILE} < $f;@}
56         @${META_COOKIE_TOUCH}
57
58 # make sure this exists
59 .ldorder:       .NOTMAIN
60
61 # and finally we need to reverse the order of content
62 ldorder: .ldorder .NOTMAIN
63         @{ test ! -s .ldorder || cat -n .ldorder | sort -rn | \
64         sed '/ldorder-/d;s,^[[:space:]0-9]*,,'; } > ${.TARGET}
65
66 # Initially we hook contents of DPLIBS and DPADD into our graph
67 LDORDER_LIBS ?= ${DPLIBS} ${DPADD:M*/lib*} ${__dpadd_libs}
68 # we need to remember this
69 _LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}}
70
71 .if empty(_LDORDER_LIBS)
72 # don't use stale ldorder
73 LDADD_LDORDER =
74 .else
75 # this is how you use it
76 LDADD_LDORDER ?= `cat ldorder`
77 .endif
78
79 # for debug below
80 _ldorder = ${RELDIR}.${TARGET_SPEC}
81
82 # we make have some libs that exist outside of $SB
83 # and want to insert a barrier
84 .if target(${LDORDER_EXTERN_BARRIER})
85 # eg. in local.ldorder.mk
86 # ${LDORDER_EXTERN_BARRIER}:
87 #       @test -z "${extern_ldorders}" || \
88 #       echo -Wl,-Bdynamic >> .ldorder
89 #
90 # feel free to put more suitable version in local.ldorder.mk if needed
91 # we do *not* count host libs in extern_ldorders
92 extern_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-}
93 sb_ldorders ?= ${.ALLTARGETS:M.ldorder-*:N${LDORDER_EXTERN_BARRIER}:N.ldorder-rm:${extern_ldorders:${M_ListToSkip}}:N.ldorder-}
94
95 # finally in Makefile after include of *.mk put
96 # .ldorder ${sb_ldorders}: ${LDORDER_EXTERN_BARRIER}
97 # ${LDORDER_EXTERN_BARRIER}: ${extern_ldorders}
98 .endif
99
100 .endif                          # !target(_LDORDER_USE)
101
102 .if !empty(LDORDER_LIBS) && target(_ldorder_use)
103 # canonicalize - these are just tokens anyway
104 LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}:R:C/\.so.*//}
105 _ldorders := ${LDORDER_LIBS:T:Mlib*:S,^,.ldorder-,}
106
107 .for t in ${_ldorders}
108 .if !target($t)
109 $t: _LDORDER_USE
110 .endif
111 .endfor
112
113 # and this makes it all happen
114 .ldorder: ${_ldorders}
115
116 # this is how we get the dependencies
117 .if ${.INCLUDEDFROMFILE:M*.${LDORDER_INC}} != ""
118 _ldorder := .ldorder-${.INCLUDEDFROMFILE:S/.${LDORDER_INC}//}
119 ${_ldorder}: ${_ldorders}
120 .ldorder-rm: ${.INCLUDEDFROMDIR}/${.INCLUDEDFROMFILE}
121 .endif
122
123 # set DEBUG_LDORDER to pattern[s] that match the dirs of interest
124 .if ${DEBUG_LDORDER:Uno:@x@${RELDIR:M$x}@} != ""
125 .info ${_ldorder}: ${_ldorders}
126 .endif
127
128 # now try to find more ...
129 # each *.${LDORDER_INC} should set LDORDER_LIBS to what it needs
130 # it can also add to CFLAGS etc.
131 .for __inc in ${LDORDER_LIBS:S,$,.${LDORDER_INC},}
132 .if !target(__${__inc}__)
133 __${__inc}__:
134 # make sure this is reset
135 LDORDER_LIBS =
136 _ldorders =
137 .-include <${__inc}>
138 .endif
139 .endfor
140
141 .endif                          # !empty(LDORDER_LIBS)
142
143 .ifdef LIB
144 # you can make this depend on files (must match *ldorder*)
145 # to add extra content - like CFLAGS
146 libLDORDER_INC = lib${LIB}.${LDORDER_INC}
147 .if !commands(${libLDORDER_INC})
148 .if target(ldorder-header)
149 ${libLDORDER_INC}: ldorder-header
150 .endif
151 ${libLDORDER_INC}:
152         @(cat /dev/null ${.ALLSRC:M*ldorder*}; \
153         echo 'LDORDER_LIBS= ${_LDORDER_LIBS:T:R:${LDORDER_INC_FILTER:ts:}:tu:C,.*,_{&},:N_{}}'; \
154         echo; echo '.include <ldorder.mk>' ) | sed 's,_{,$${,g' > ${.TARGET}
155 .endif
156 .endif