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