1# $Id: dpadd.mk,v 1.31 2023/11/25 01:07:49 sjg Exp $ 2# 3# @(#) Copyright (c) 2004-2023, 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## 17# DESCRIPTION: 18# This makefile manages a number of variables that simplify 19# dealing with libs in a build. 20# 21# Primary inputs are DPLIBS, DPADD and SRC_LIBS: 22# 23# DPLIBS 24# List of LIB* that we will actually link with 25# should be in correct link order. 26# DPLIBS is a short-cut to ensure that DPADD and LDADD are 27# kept in sync. 28# 29# DPADD List of LIB* that should already be built. 30# 31# SRC_LIBS 32# List of LIB* that we want headers from, we do *not* 33# require that such libs have been built. 34# 35# The above all get added to DPMAGIC_LIBS which is what we 36# process. 37# 38# We expect LIB* to be set to absolute path of a library - 39# suitable for putting in DPADD. 40# eg. 41# 42# LIBC ?= ${OBJTOP}/lib/libc/libc.a 43# 44# From such a path we can derrive a number of other variables 45# for which we can supply sensible default values. 46# We name all these variables for the basename of the library 47# (libc in our example above -- ${__lib:T:R} in below): 48# 49# LDADD_${__lib:T:R}: 50# What should be added to LDADD (eg -lc) 51# 52# OBJ_${__lib:T:R}: 53# This is trivial - just the dirname of the built library. 54# 55# SRC_${__lib:T:R}: 56# Where the src for ${__lib} is, if LIB* is set as above 57# we can simply substitute ${SRCTOP} for ${OBJTOP} in 58# the dirname. 59# 60# INCLUDES_${__lib:T:R}: 61# What should be added to CFLAGS 62# 63# If the directory ${SRC_${__lib:T:R}}/h exists we will 64# only add -I${SRC_${__lib:T:R}}/h on the basis that 65# this is where the public api is kept. 66# 67# Otherwise default will be -I${OBJ_${__lib:T:R}} 68# -I${SRC_${__lib:T:R}} 69# 70# Note much of the above is skipped for staged libs 71# eg. 72# LIBC ?= ${STAGE_OBJTOP}/usr/lib/libc.a 73# 74# Since we can safely assume that -I${STAGE_OBJTOP}/usr/include 75# and -L${STAGE_OBJTOP}/usr/lib are sufficient, and we should 76# have no need of anything else. 77# 78# Sometimes things are more complicated so allow for 79# DPLIBS to be qualified with each of the variables in 80# DPLIBS_QUALIFIER_LIST (default is VAR_QUALIFIER_LIST same as 81# init.mk) 82 83.if !target(__${.PARSEFILE}__) 84__${.PARSEFILE}__: .NOTMAIN 85 86# sometimes we play games with .CURDIR etc 87# _* hold the original values of .* 88_OBJDIR?= ${.OBJDIR} 89_CURDIR?= ${.CURDIR} 90 91.if ${_CURDIR} == ${SRCTOP} 92RELDIR=. 93RELTOP=. 94.else 95RELDIR?= ${_CURDIR:S,${SRCTOP}/,,} 96.if ${RELDIR} == ${_CURDIR} 97RELDIR?= ${_OBJDIR:S,${OBJTOP}/,,} 98.endif 99RELTOP?= ${RELDIR:C,[^/]+,..,g} 100.endif 101RELOBJTOP?= ${OBJTOP} 102RELSRCTOP?= ${SRCTOP} 103 104# we get included just about everywhere so this is handy... 105# C*DEBUG_XTRA are for defining on cmd line etc 106# so do not use in makefiles. 107.ifdef CFLAGS_DEBUG_XTRA 108CFLAGS_LAST += ${CFLAGS_DEBUG_XTRA} 109.endif 110.ifdef CXXFLAGS_DEBUG_XTRA 111CXXFLAGS_LAST += ${CXXFLAGS_DEBUG_XTRA} 112.endif 113 114.-include <local.dpadd.mk> 115 116# DPLIBS helps us ensure we keep DPADD and LDADD in sync 117DPLIBS_QUALIFIER_LIST ?= ${VAR_QUALIFIER_LIST} 118DPLIBS += ${DPLIBS_QUALIFIER_LIST:u:@Q@${DPLIBS.$Q:U}@} 119DPLIBS+= ${DPLIBS_LAST} ${DPLIBS_QUALIFIER_LIST:u:@Q@${DPLIBS_LAST.$Q:U}@} 120DPADD+= ${DPLIBS:N-*} 121.for __lib in ${DPLIBS} 122.if "${__lib:M-*}" != "" 123LDADD += ${__lib} 124.else 125LDADD += ${LDADD_${__lib:T:R}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}} 126.endif 127.endfor 128 129# DPADD can contain things other than libs 130__dpadd_libs := ${DPADD:M*/lib*} 131 132.if defined(PROG) && ${MK_PROG_LDORDER_MK:Uno} != "no" 133# some libs have dependencies... 134# DPLIBS_* allows bsd.libnames.mk to flag libs which must be included 135# in DPADD for a given library. 136# Gather all such dependencies into __ldadd_all_xtras 137# dups will be dealt with later. 138# Note: libfoo_pic uses DPLIBS_libfoo 139__ldadd_all_xtras= 140.for __lib in ${__dpadd_libs:@d@${DPLIBS_${d:T:R:S,_pic,,}} ${DPLIBS_QUALIFIER_LIST:u:@Q@${DPLIBS_${d:T:R:S,_pic,,}.$Q:U}@}@} 141__ldadd_all_xtras+= ${LDADD_${__lib}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}} 142.if "${DPADD:M${__lib}}" == "" 143DPADD+= ${__lib} 144.endif 145.endfor 146.endif 147# Last of all... for libc and libgcc 148DPADD+= ${DPADD_LAST} 149 150# de-dupuplicate __ldadd_all_xtras into __ldadd_xtras 151# in reverse order so that libs end up listed after all that needed them. 152__ldadd_xtras= 153.for __lib in ${__ldadd_all_xtras:[-1..1]} 154.if "${__ldadd_xtras:M${__lib}}" == "" || ${NEED_IMPLICIT_LDADD:tl:Uno} != "no" 155__ldadd_xtras+= ${__lib} 156.endif 157.endfor 158 159.if !empty(__ldadd_xtras) 160# now back to the original order 161__ldadd_xtras:= ${__ldadd_xtras:[-1..1]} 162LDADD+= ${__ldadd_xtras} 163.endif 164 165# Convert DPADD into -I and -L options and add them to CPPFLAGS and LDADD 166# For the -I's convert the path to a relative one. For separate objdirs 167# the DPADD paths will be to the obj tree so we need to subst anyway. 168 169# update this 170__dpadd_libs := ${DPADD:M*/lib*} 171 172# Order -L's to search ours first. 173# Avoids picking up old versions already installed. 174__dpadd_libdirs := ${__dpadd_libs:R:H:S/^/-L/g:O:u:N-L} 175LDADD += ${__dpadd_libdirs:M-L${OBJTOP}/*} 176LDADD += ${__dpadd_libdirs:N-L${OBJTOP}/*:N-L${HOST_LIBDIR:U/usr/lib}} 177.if defined(HOST_LIBDIR) && ${HOST_LIBDIR} != "/usr/lib" 178LDADD+= -L${HOST_LIBDIR} 179.endif 180 181.if !make(dpadd) 182.ifdef LIB 183# Each lib is its own src_lib, we want to include it in SRC_LIBS 184# so that the correct INCLUDES_* will be picked up automatically. 185SRC_LIBS+= ${_OBJDIR}/lib${LIB}.a 186.endif 187.endif 188 189# 190# This little bit of magic, assumes that SRC_libfoo will be 191# set if it cannot be correctly derrived from ${LIBFOO} 192# Note that SRC_libfoo and INCLUDES_libfoo should be named for the 193# actual library name not the variable name that might refer to it. 194# 99% of the time the two are the same, but the DPADD logic 195# only has the library name available, so stick to that. 196# 197 198SRC_LIBS?= 199# magic_libs includes those we want to link with 200# as well as those we might look at 201__dpadd_magic_libs += ${__dpadd_libs} ${SRC_LIBS} 202DPMAGIC_LIBS += ${__dpadd_magic_libs} \ 203 ${__dpadd_magic_libs:@d@${DPMAGIC_LIBS_${d:T:R}}@} 204 205# we skip this for staged libs 206.for __lib in ${DPMAGIC_LIBS:O:u:N${STAGE_OBJTOP:Unot}*/lib/*} 207# 208# if SRC_libfoo is not set, then we assume that the srcdir corresponding 209# to where we found the library is correct. 210# 211SRC_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELSRCTOP},} 212# 213# This is a no-brainer but just to be complete... 214# 215OBJ_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELOBJTOP},} 216# 217# If INCLUDES_libfoo is not set, then we'll use ${SRC_libfoo}/h if it exists, 218# else just ${SRC_libfoo}. 219# 220.if !empty(SRC_${__lib:T:R}) 221INCLUDES_${__lib:T:R} ?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h:${SRC_${__lib:T:R}}} 222.endif 223.endfor 224 225# even for staged libs we sometimes 226# need to allow direct -I to avoid cicular dependencies 227.for __lib in ${DPMAGIC_LIBS:O:u:T:R} 228.if !empty(SRC_${__lib}) && empty(INCLUDES_${__lib}) 229# must be a staged lib 230.if exists(${SRC_${__lib}}/h) 231INCLUDES_${__lib} = -I${SRC_${__lib}}/h 232.else 233INCLUDES_${__lib} = -I${SRC_${__lib}} 234.endif 235.endif 236.endfor 237 238# when linking a shared lib, avoid non pic libs 239SHLDADD+= ${LDADD:N-[lL]*} 240.for __lib in ${__dpadd_libs:u} 241.if defined(SHLIB_NAME) && ${LDADD:M-l${__lib:T:R:S,lib,,}} != "" 242.if ${__lib:T:N*_pic.a:N*.so} == "" || exists(${__lib:R}.so) 243SHLDADD+= -l${__lib:T:R:S,lib,,} 244.elif exists(${__lib:R}_pic.a) 245SHLDADD+= -l${__lib:T:R:S,lib,,}_pic 246.else 247.warning ${RELDIR}.${TARGET_SPEC} needs ${__lib:T:R}_pic.a 248SHLDADD+= -l${__lib:T:R:S,lib,,} 249.endif 250SHLDADD+= -L${__lib:H} 251.endif 252.endfor 253 254# Now for the bits we actually need 255__dpadd_incs= 256.for __lib in ${__dpadd_libs:u} 257.if (make(${PROG}_p) || defined(NEED_GPROF)) && exists(${__lib:R}_p.a) 258__ldadd=-l${__lib:T:R:S,lib,,} 259LDADD := ${LDADD:S,^${__ldadd}$,${__ldadd}_p,g} 260.endif 261.endfor 262 263# 264# We take care of duplicate suppression later. 265# don't apply :T:R too early 266__dpadd_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_${x:T:R}}@} 267__dpadd_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_${x:T:R}}@} 268 269__dpadd_last_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_LAST_${x:T:R}}@} 270__dpadd_last_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_LAST_${x:T:R}}@} 271 272.if defined(HOSTPROG) || ${MACHINE:Nhost*} == "" 273# we want any -I/usr/* last 274__dpadd_last_incs := \ 275 ${__dpadd_last_incs:N-I/usr/*} \ 276 ${__dpadd_incs:M-I/usr/*} \ 277 ${__dpadd_last_incs:M-I/usr/*} 278__dpadd_incs := ${__dpadd_incs:N-I/usr/*} 279.endif 280 281# 282# eliminate any duplicates - but don't mess with the order 283# force evaluation now - to avoid giving make a headache 284# 285.for t in CFLAGS CXXFLAGS 286# avoid duplicates 287__$t_incs:=${$t:M-I*:O:u} 288.for i in ${__dpadd_incs} 289.if "${__$t_incs:M$i}" == "" 290$t+= $i 291__$t_incs+= $i 292.endif 293.endfor 294.endfor 295 296.for t in CFLAGS_LAST CXXFLAGS_LAST 297# avoid duplicates 298__$t_incs:=${$t:M-I*:u} 299.for i in ${__dpadd_last_incs} 300.if "${__$t_incs:M$i}" == "" 301$t+= $i 302__$t_incs+= $i 303.endif 304.endfor 305.endfor 306 307# This target is used to gather a list of 308# dir: ${DPADD} 309# entries 310.if make(*dpadd*) 311.if !target(dpadd) 312dpadd: .NOTMAIN 313.if defined(DPADD) && ${DPADD} != "" 314 @echo "${RELDIR}: ${DPADD:S,${OBJTOP}/,,}" 315.endif 316.endif 317.endif 318 319.ifdef SRC_PATHADD 320# We don't want to assume that we need to .PATH every element of 321# SRC_LIBS, but the Makefile cannot do 322# .PATH: ${SRC_libfoo} 323# since the value of SRC_libfoo must be available at the time .PATH: 324# is read - and we only just worked it out. 325# Further, they can't wait until after include of {lib,prog}.mk as 326# the .PATH is needed before then. 327# So we let the Makefile do 328# SRC_PATHADD+= ${SRC_libfoo} 329# and we defer the .PATH: until now so that SRC_libfoo will be available. 330.PATH: ${SRC_PATHADD} 331.endif 332 333# after all that, if doing -n we don't care 334.if ${.MAKEFLAGS:Ux:M-n} != "" 335DPADD = 336.elif ${.MAKE.MODE:Mmeta*} != "" && exists(${.MAKE.DEPENDFILE}) 337DPADD_CLEAR_DPADD ?= yes 338.if ${DPADD_CLEAR_DPADD} == "yes" 339# save this 340__dpadd_libs := ${__dpadd_libs} 341# we have made what use of it we can of DPADD 342DPADD = 343.endif 344.endif 345 346.endif 347