freebsd-skq/share/mk/bsd.dep.mk

370 lines
11 KiB
Makefile
Raw Normal View History

1999-08-28 00:22:10 +00:00
# $FreeBSD$
#
# The include file <bsd.dep.mk> handles Makefile dependencies.
#
#
# +++ variables +++
#
# CLEANDEPENDDIRS Additional directories to remove for the cleandepend
# target.
#
# CLEANDEPENDFILES Additional files to remove for the cleandepend target.
#
# CTAGS A tags file generation program [gtags]
#
# CTAGSFLAGS Options for ctags(1) [not set]
#
# DEPENDFILE dependencies file [.depend]
#
# GTAGSFLAGS Options for gtags(1) [-o]
#
# HTAGSFLAGS Options for htags(1) [not set]
#
# SRCS List of source files (c, c++, assembler)
#
# DPSRCS List of source files which are needed for generating
# dependencies, ${SRCS} are always part of it.
#
# +++ targets +++
#
# cleandepend:
# remove ${CLEANDEPENDFILES}; remove ${CLEANDEPENDDIRS} and all
# contents.
#
# depend:
# Make the dependencies for the source files, and store
# them in the file ${DEPENDFILE}.
#
# tags:
# In "ctags" mode, create a tags file for the source files.
# In "gtags" mode, create a (GLOBAL) gtags file for the
# source files. If HTML is defined, htags(1) is also run
# after gtags(1).
.if !target(__<bsd.init.mk>__)
.error bsd.dep.mk cannot be included directly.
.endif
CTAGS?= gtags
CTAGSFLAGS?=
GTAGSFLAGS?= -o
HTAGSFLAGS?=
.if ${MK_DIRDEPS_BUILD} == "no"
.MAKE.DEPENDFILE= ${DEPENDFILE}
.endif
CLEANDEPENDFILES+= ${DEPENDFILE} ${DEPENDFILE}.*
.if ${MK_META_MODE} == "yes"
CLEANDEPENDFILES+= *.meta
.endif
# Keep `tags' here, before SRCS are mangled below for `depend'.
2004-12-21 09:43:25 +00:00
.if !target(tags) && defined(SRCS) && !defined(NO_TAGS)
tags: ${SRCS}
.if ${CTAGS:T} == "gtags"
@cd ${.CURDIR} && ${CTAGS} ${GTAGSFLAGS} ${.OBJDIR}
.if defined(HTML)
@cd ${.CURDIR} && htags ${HTAGSFLAGS} -d ${.OBJDIR} ${.OBJDIR}
.endif
.else
@${CTAGS} ${CTAGSFLAGS} -f /dev/stdout \
${.ALLSRC:N*.h} | sed "s;${.CURDIR}/;;" > ${.TARGET}
.endif
.endif
.if !empty(.MAKE.MODE:Mmeta) && empty(.MAKE.MODE:Mnofilemon)
_meta_filemon= 1
.endif
# By default META_MODE is disabled in bmake if there is no OBJDIR
# unless .MAKE.MODE contains "curdirOk=[^0nNfF]"
.if defined(_meta_filemon) && ${.OBJDIR} == ${.CURDIR} && \
(empty(.MAKE.MODE:tl:Mcurdirok=*) || \
!empty(.MAKE.MODE:tl:Mcurdirok=[0NnFf]*))
.undef _meta_filemon
.endif
# Skip reading .depend when not needed to speed up tree-walks and simple
# lookups. See _SKIP_BUILD logic in bsd.init.mk for more details.
# Also skip generating or including .depend.* files if in meta+filemon mode
# since it will track dependencies itself. OBJS_DEPEND_GUESS is still used
# for _meta_filemon but not for _SKIP_DEPEND.
.if !defined(NO_SKIP_DEPEND) && defined(_SKIP_BUILD)
_SKIP_DEPEND= 1
.endif
.if ${MK_DIRDEPS_BUILD} == "no"
.if defined(_SKIP_DEPEND) || defined(_meta_filemon)
.MAKE.DEPENDFILE= /dev/null
.endif
.endif
.if defined(SRCS)
CLEANFILES?=
.for _S in ${SRCS:N*.[dhly]}
OBJS_DEPEND_GUESS.${_S:${OBJS_SRCS_FILTER:ts:}}.o+= ${_S}
.endfor
# Lexical analyzers
.for _LSRC in ${SRCS:M*.l:N*/*}
.for _LC in ${_LSRC:R}.c
${_LC}: ${_LSRC}
${LEX} ${LFLAGS} ${LFLAGS.${_LSRC}} -o${.TARGET} ${.ALLSRC}
OBJS_DEPEND_GUESS.${_LC:R}.o+= ${_LC}
SRCS:= ${SRCS:S/${_LSRC}/${_LC}/}
CLEANFILES+= ${_LC}
.endfor
.endfor
# Yacc grammars
.for _YSRC in ${SRCS:M*.y:N*/*}
.for _YC in ${_YSRC:R}.c
SRCS:= ${SRCS:S/${_YSRC}/${_YC}/}
CLEANFILES+= ${_YC}
.if !empty(YFLAGS:M-d) && !empty(SRCS:My.tab.h)
Rework some multi-output target dependency handling. This reworks my last commit in r301285 to more closely match what was in r241298 (but reverted in r294878). This is addressing "missing .meta file" rebuilds but also ensuring that files are always generated when needed in each case. Note that this is not a complete rework of the problem areas identified in r301285 as most are "good enough" right now as the new pattern is too verbose. It's only worth making this current change where headers may be generated in the INCS list; where missing .meta file rebuilds are spotted. --- Technical details follow --- Several attempts to deal with this problem of multi-output targets, with and without META MODE, were explained in r241298, r294878, and r301285. The general problem is with multi-output targets such as: foo.c foo.h: touch foo.c foo.h foo.c foo.h: touch foo.c touch foo.h foo.c foo.h: foo.in ./generator ${.ALLSRC} This pattern is problematic in jobs mode as both files end up being built concurrently and leads to races. With META MODE it is worse as both targets end up rebuilding if they lack a .meta file. So the generator is force built twice even though it is only needed once. There are also problems in that 'make foo.h' may be ran before 'make foo.c'; The order of make generating the targets is not guaranteed. An older attempted workaround to this (discussed in r294878) was: foo.h: foo.c foo.c: foo.in ./generator ${.ALLSRC} This appears fine except that if foo.h is missing and foo.c exists then foo.h will never be regenerated. This pattern is close to the solution in this commit though: foo.h: foo.c .NOMETA .if !exists(foo.h) foo.c: .PHONY .META .endif foo.c: foo.in ./generator ${.ALLSRC} There's 2 differences here: 1. foo.h will never expect to have a .meta file since the foo.c target will generate both and own the .meta file. 2. If foo.h does not exist then it needs to force foo.c to be rebuilt with .PHONY. That normally disables META MODE though so .META is given to tell bmake we do really expect a .meta file. This pattern cannot work with implicit suffix rules since the .c and .h files may be generated at different times (buildincludes vs depend/all). Sponsored by: Dell EMC MFC after: 2 weeks
2019-07-19 00:15:25 +00:00
# Multi-output targets both expect a .meta file and will fight over it. Only
# allow it on the .c file instead.
y.tab.h: ${_YC} .NOMETA
# Force rebuild the .c file if any of its other outputs are missing.
.if !exists(y.tab.h)
${_YC}: .PHONY .META
.endif
${_YC}: ${_YSRC}
${YACC} ${YFLAGS} ${YFLAGS.${_YSRC}} ${.ALLSRC}
cp y.tab.c ${_YC}
CLEANFILES+= y.tab.c y.tab.h
.elif !empty(YFLAGS:M-d)
.for _YH in ${_YC:R}.h
Rework some multi-output target dependency handling. This reworks my last commit in r301285 to more closely match what was in r241298 (but reverted in r294878). This is addressing "missing .meta file" rebuilds but also ensuring that files are always generated when needed in each case. Note that this is not a complete rework of the problem areas identified in r301285 as most are "good enough" right now as the new pattern is too verbose. It's only worth making this current change where headers may be generated in the INCS list; where missing .meta file rebuilds are spotted. --- Technical details follow --- Several attempts to deal with this problem of multi-output targets, with and without META MODE, were explained in r241298, r294878, and r301285. The general problem is with multi-output targets such as: foo.c foo.h: touch foo.c foo.h foo.c foo.h: touch foo.c touch foo.h foo.c foo.h: foo.in ./generator ${.ALLSRC} This pattern is problematic in jobs mode as both files end up being built concurrently and leads to races. With META MODE it is worse as both targets end up rebuilding if they lack a .meta file. So the generator is force built twice even though it is only needed once. There are also problems in that 'make foo.h' may be ran before 'make foo.c'; The order of make generating the targets is not guaranteed. An older attempted workaround to this (discussed in r294878) was: foo.h: foo.c foo.c: foo.in ./generator ${.ALLSRC} This appears fine except that if foo.h is missing and foo.c exists then foo.h will never be regenerated. This pattern is close to the solution in this commit though: foo.h: foo.c .NOMETA .if !exists(foo.h) foo.c: .PHONY .META .endif foo.c: foo.in ./generator ${.ALLSRC} There's 2 differences here: 1. foo.h will never expect to have a .meta file since the foo.c target will generate both and own the .meta file. 2. If foo.h does not exist then it needs to force foo.c to be rebuilt with .PHONY. That normally disables META MODE though so .META is given to tell bmake we do really expect a .meta file. This pattern cannot work with implicit suffix rules since the .c and .h files may be generated at different times (buildincludes vs depend/all). Sponsored by: Dell EMC MFC after: 2 weeks
2019-07-19 00:15:25 +00:00
# Multi-output targets both expect a .meta file and will fight over it. Only
# allow it on the .c file instead.
${_YH}: ${_YC} .NOMETA
# Force rebuild the .c file if any of its other outputs are missing.
.if !exists(${_YH})
${_YC}: .PHONY .META
.endif
${_YC}: ${_YSRC}
${YACC} ${YFLAGS} ${YFLAGS.${_YSRC}} -o ${_YC} ${.ALLSRC}
SRCS+= ${_YH}
CLEANFILES+= ${_YH}
.endfor
.else
${_YC}: ${_YSRC}
${YACC} ${YFLAGS} ${YFLAGS.${_YSRC}} -o ${_YC} ${.ALLSRC}
.endif
OBJS_DEPEND_GUESS.${_YC:R}.o+= ${_YC}
.endfor
.endfor
# DTrace probe definitions
.if ${SRCS:M*.d}
CFLAGS+= -I${.OBJDIR}
.endif
.for _DSRC in ${SRCS:M*.d:N*/*}
.for _D in ${_DSRC:R}
SRCS+= ${_D}.h
${_D}.h: ${_DSRC}
${DTRACE} ${DTRACEFLAGS} -h -s ${.ALLSRC}
SRCS:= ${SRCS:S/^${_DSRC}$//}
OBJS+= ${_D}.o
CLEANFILES+= ${_D}.h ${_D}.o
${_D}.o: ${_DSRC} ${OBJS:S/^${_D}.o$//}
@rm -f ${.TARGET}
${DTRACE} ${DTRACEFLAGS} -G -o ${.TARGET} -s ${.ALLSRC:N*.h}
.if defined(LIB)
CLEANFILES+= ${_D}.pico ${_D}.po ${_D}.nossppico
${_D}.pico: ${_DSRC} ${SOBJS:S/^${_D}.pico$//}
@rm -f ${.TARGET}
${DTRACE} ${DTRACEFLAGS} -G -o ${.TARGET} -s ${.ALLSRC:N*.h}
${_D}.po: ${_DSRC} ${POBJS:S/^${_D}.po$//}
@rm -f ${.TARGET}
${DTRACE} ${DTRACEFLAGS} -G -o ${.TARGET} -s ${.ALLSRC:N*.h}
${_D}.nossppico: ${_DSRC} ${SOBJS:S/^${_D}.nossppico$//}
@rm -f ${.TARGET}
${DTRACE} ${DTRACEFLAGS} -G -o ${.TARGET} -s ${.ALLSRC:N*.h}
.endif
.endfor
.endfor
.endif # defined(SRCS)
.if ${MAKE_VERSION} < 20160220
DEPEND_MP?= -MP
.endif
# Handle OBJS=../somefile.o hacks. Just replace '/' rather than use :T to
# avoid collisions.
DEPEND_FILTER= C,/,_,g
.if !empty(OBJS)
DEPENDOBJS+= ${OBJS}
.else
DEPENDSRCS+= ${SRCS:M*.[cSC]} ${SRCS:M*.cxx} ${SRCS:M*.cpp} ${SRCS:M*.cc}
DEPENDSRCS+= ${DPSRCS:M*.[cSC]} ${DPSRCS:M*.cxx} ${DPSRCS:M*.cpp} ${DPSRCS:M*.cc}
.if !empty(DEPENDSRCS)
DEPENDOBJS+= ${DEPENDSRCS:${OBJS_SRCS_FILTER:ts:}:S,$,.o,}
.endif
.endif # !empty(OBJS)
.if !empty(DEPENDOBJS)
DEPENDFILES+= ${DEPENDOBJS:O:u:${DEPEND_FILTER}:C/^/${DEPENDFILE}./}
.endif
.if defined(_SKIP_DEPEND)
# Don't bother statting any .meta files for .depend*
${DEPENDOBJS}: .NOMETA
${DEPENDFILE}: .NOMETA
# Unset these to avoid looping/statting on them later.
.undef DEPENDSRCS
.undef DEPENDOBJS
.undef DEPENDFILES
.endif # defined(_SKIP_DEPEND)
DEPEND_CFLAGS+= -MD ${DEPEND_MP} -MF${DEPENDFILE}.${.TARGET:${DEPEND_FILTER}}
DEPEND_CFLAGS+= -MT${.TARGET}
.if !defined(_meta_filemon)
.if !empty(DEPEND_CFLAGS)
# Only add in DEPEND_CFLAGS for CFLAGS on files we expect from DEPENDOBJS
# as those are the only ones we will include.
DEPEND_CFLAGS_CONDITION= "${DEPENDOBJS:${DEPEND_FILTER}:M${.TARGET:${DEPEND_FILTER}}}" != ""
CFLAGS+= ${${DEPEND_CFLAGS_CONDITION}:?${DEPEND_CFLAGS}:}
.endif
.for __depend_obj in ${DEPENDFILES}
.if ${MAKE_VERSION} < 20160220
.sinclude "${.OBJDIR}/${__depend_obj}"
.else
.dinclude "${.OBJDIR}/${__depend_obj}"
.endif
.endfor
.endif # !defined(_meta_filemon)
.if ${MK_DIRDEPS_BUILD} == "yes" && ${.MAKE.DEPENDFILE} != "/dev/null"
FAST_DEPEND: Always run depend via beforebuild which removes many hacks. This will generate dependencies rather than depending on the previous behavior of depending on the guessed OBJS: *.h dependecies or a user running 'make depend'. Experimentation showed that depending only on headers was not enough and prone to .ORDER errors. Downstream users may also have added dependencies into beforedepend or afterdepend targets. The safest way to ensure dependencies are generated before build is to run 'make depend' beforehand rather than just depending on DPSRCS+SRCS. Note that the OBJS_DEPEND_GUESS mechanism (a.k.a .if !exists(.depend) then foo.o: *.h) is still useful as it improves incremental builds with missing .depend.* files and allows 'make foo.o' to usually work, while this 'beforebuild: depend' ensures that the build will always find all dependencies. The 'make foo.o' case has no means of a 'beforebuild' hook. This also removes several hacks in the DIRDEPS_BUILD: - NO_INSTALL_INCLUDES is no longer needed as it mostly was to work around .ORDER problems with building the needed headers early. - DIRDEPS_BUILD: It is no longer necesarry to track "local dependencies" in Makefile.depend. These were only in Makefile.depend for 'clean builds' since nothing would generate the files due to skipping 'make depend' and early dependency bugs that have been fixed, such as adding headers into SRCS for the OBJS_DEPEND_GUESS mechanism. Normally if a .depend file does not exist then a dependency is added by bsd.lib.mk/bsd.prog.mk from OBJS: *.h. However, meta.autodep.mk creates a .depend file from created meta files and inserts that into Makefile.depend. It also only tracks *.[ch] files though which can miss some dependencies that are hooked into 'make depend'. This .depend that is created then breaks incremental builds due to the !exists(.depend) checks for OBJS_DEPEND_GUESS. The goal was to skip 'make depend' yet it only really works the first time. After that files are not generated as expected, which r288966 tried to address but was using buildfiles: rather than beforebuild: and was reverted in r291725. As noted previously, depending only on headers in beforebuild: would create .ORDER errors in some cases. meta.autodep.mk is still used to generate Makefile.depend though via: gendirdeps: Makefile.depend .END: gendirdeps This commit allows removing all of the "local dependencies" in Makefile.depend which cuts down on churn and removes some of the arch-dependent Makefile.depend files. The "local dependencies" were also problematic for bootstrapping. Sponsored by: EMC / Isilon Storage Division
2016-02-24 17:19:18 +00:00
# Prevent meta.autodep.mk from tracking "local dependencies".
.depend:
.include <meta.autodep.mk>
# If using filemon then _EXTRADEPEND is skipped since it is not needed.
.if defined(_meta_filemon)
# this depend: bypasses that below
# the dependency helps when bootstrapping
depend: beforedepend ${DPSRCS} ${SRCS} afterdepend
beforedepend:
afterdepend: beforedepend
.endif
.endif
# Guess some dependencies for when no ${DEPENDFILE}.OBJ is generated yet.
# For meta+filemon the .meta file is checked for since it is the dependency
# file used.
.for __obj in ${DEPENDOBJS:O:u}
# If the obj has any '/', then replace with '_'. For meta files, this is
# mimicing what bmake's meta_name() does and adding in the full path
# as well to ensure that the expected meta file is read.
.if ${__obj:M*/*}
.if ${MAKE_VERSION} < 20171028
_meta_obj= ${.OBJDIR:C,/,_,g}_${__obj:C,/,_,g}.meta
.else
_meta_obj= ${__obj:C,/,_,g}.meta
.endif # ${MAKE_VERSION} < 20171028
.else
_meta_obj= ${__obj}.meta
.endif # ${__obj:M*/*}
_dep_obj= ${DEPENDFILE}.${__obj:${DEPEND_FILTER}}
.if defined(_meta_filemon)
_depfile= ${.OBJDIR}/${_meta_obj}
.else
_depfile= ${.OBJDIR}/${_dep_obj}
.endif
.if !exists(${_depfile}) || defined(_meta_filemon)
# - Headers are normally built in beforebuild when included in DPSRCS or SRCS.
# So we don't need it as a guessed dependency (it may lead to cyclic problems
# if custom rules are defined). The only time this causes a problem is when
# 'make foo.o' is ran.
# - For meta mode we still need to know which file to depend on to avoid
# ambiguous suffix transformation rules from .PATH. Meta mode does not
# use .depend files when filemon is in use.
.if !target(${__obj})
${__obj}: ${OBJS_DEPEND_GUESS}
.endif
${__obj}: ${OBJS_DEPEND_GUESS.${__obj}}
.endif # !exists(${_depfile}) || defined(_meta_filemon)
.endfor
FAST_DEPEND: Always run depend via beforebuild which removes many hacks. This will generate dependencies rather than depending on the previous behavior of depending on the guessed OBJS: *.h dependecies or a user running 'make depend'. Experimentation showed that depending only on headers was not enough and prone to .ORDER errors. Downstream users may also have added dependencies into beforedepend or afterdepend targets. The safest way to ensure dependencies are generated before build is to run 'make depend' beforehand rather than just depending on DPSRCS+SRCS. Note that the OBJS_DEPEND_GUESS mechanism (a.k.a .if !exists(.depend) then foo.o: *.h) is still useful as it improves incremental builds with missing .depend.* files and allows 'make foo.o' to usually work, while this 'beforebuild: depend' ensures that the build will always find all dependencies. The 'make foo.o' case has no means of a 'beforebuild' hook. This also removes several hacks in the DIRDEPS_BUILD: - NO_INSTALL_INCLUDES is no longer needed as it mostly was to work around .ORDER problems with building the needed headers early. - DIRDEPS_BUILD: It is no longer necesarry to track "local dependencies" in Makefile.depend. These were only in Makefile.depend for 'clean builds' since nothing would generate the files due to skipping 'make depend' and early dependency bugs that have been fixed, such as adding headers into SRCS for the OBJS_DEPEND_GUESS mechanism. Normally if a .depend file does not exist then a dependency is added by bsd.lib.mk/bsd.prog.mk from OBJS: *.h. However, meta.autodep.mk creates a .depend file from created meta files and inserts that into Makefile.depend. It also only tracks *.[ch] files though which can miss some dependencies that are hooked into 'make depend'. This .depend that is created then breaks incremental builds due to the !exists(.depend) checks for OBJS_DEPEND_GUESS. The goal was to skip 'make depend' yet it only really works the first time. After that files are not generated as expected, which r288966 tried to address but was using buildfiles: rather than beforebuild: and was reverted in r291725. As noted previously, depending only on headers in beforebuild: would create .ORDER errors in some cases. meta.autodep.mk is still used to generate Makefile.depend though via: gendirdeps: Makefile.depend .END: gendirdeps This commit allows removing all of the "local dependencies" in Makefile.depend which cuts down on churn and removes some of the arch-dependent Makefile.depend files. The "local dependencies" were also problematic for bootstrapping. Sponsored by: EMC / Isilon Storage Division
2016-02-24 17:19:18 +00:00
# Always run 'make depend' to generate dependencies early and to avoid the
# need for manually running it. The dirdeps build should only do this in
# sub-makes though since MAKELEVEL0 is for dirdeps calculations.
.if ${MK_DIRDEPS_BUILD} == "no" || ${.MAKE.LEVEL} > 0
beforebuild: depend
.endif
.if !target(depend)
.if defined(SRCS)
depend: beforedepend ${DEPENDFILE} afterdepend
# Tell bmake not to look for generated files via .PATH
.NOPATH: ${DEPENDFILE} ${DEPENDFILES}
# A .depend file will only be generated if there are commands in
# beforedepend/_EXTRADEPEND/afterdepend The _EXTRADEPEND target is
# ignored if using meta+filemon since it handles all dependencies. The other
# targets are kept as they be used for generating something. The target is
# kept to allow 'make depend' to generate files.
${DEPENDFILE}: ${SRCS} ${DPSRCS}
.if !defined(_SKIP_DEPEND)
.if exists(${.OBJDIR}/${DEPENDFILE}) || \
((commands(beforedepend) || \
(!defined(_meta_filemon) && commands(_EXTRADEPEND)) || \
commands(afterdepend)) && !empty(.MAKE.MODE:Mmeta))
rm -f ${DEPENDFILE}
.endif
.endif
.if !defined(_meta_filemon) && target(_EXTRADEPEND)
_EXTRADEPEND: .USE
${DEPENDFILE}: _EXTRADEPEND
.endif
.ORDER: ${DEPENDFILE} afterdepend
.else
depend: beforedepend afterdepend
.endif
.if !target(beforedepend)
beforedepend:
.else
.ORDER: beforedepend ${DEPENDFILE}
.ORDER: beforedepend afterdepend
.endif
.if !target(afterdepend)
afterdepend:
.endif
.endif
.if defined(SRCS)
.if ${CTAGS:T} == "gtags"
CLEANDEPENDFILES+= GPATH GRTAGS GSYMS GTAGS
1997-04-13 06:44:25 +00:00
.if defined(HTML)
CLEANDEPENDDIRS+= HTML
.endif
.else
CLEANDEPENDFILES+= tags
.endif
.endif
.if !target(cleandepend)
cleandepend:
.if !empty(CLEANDEPENDFILES)
rm -f ${CLEANDEPENDFILES}
.endif
.if !empty(CLEANDEPENDDIRS)
rm -rf ${CLEANDEPENDDIRS}
1997-04-13 06:44:25 +00:00
.endif
.endif
.ORDER: cleandepend all
.ORDER: cleandepend depend
.if ${MK_AUTO_OBJ} == "yes"
.ORDER: cleanobj depend
.ORDER: cleandir depend
.endif
.if !target(checkdpadd) && (defined(DPADD) || defined(LDADD))
_LDADD_FROM_DPADD= ${DPADD:R:T:C;^lib(.*)$;-l\1;g}
# Ignore -Wl,--start-group/-Wl,--end-group as it might be required in the
# LDADD list due to unresolved symbols
_LDADD_CANONICALIZED= ${LDADD:N:R:T:C;^lib(.*)$;-l\1;g:N-Wl,--[es]*-group}
checkdpadd:
.if ${_LDADD_FROM_DPADD} != ${_LDADD_CANONICALIZED}
@echo ${.CURDIR}
@echo "DPADD -> ${_LDADD_FROM_DPADD}"
@echo "LDADD -> ${_LDADD_CANONICALIZED}"
.endif
.endif