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