xref: /freebsd/contrib/bmake/mk/autodep.mk (revision 8aac90f18aef7c9eea906c3ff9a001ca7b94f375)
1# SPDX-License-Identifier: BSD-2-Clause
2#
3# RCSid:
4#	$Id: autodep.mk,v 1.43 2024/02/17 17:26:57 sjg Exp $
5#
6#	@(#) Copyright (c) 1999-2024, Simon J. Gerraty
7#
8#	This file is provided in the hope that it will
9#	be of use.  There is absolutely NO WARRANTY.
10#	Permission to copy, redistribute or otherwise
11#	use this file is hereby granted provided that
12#	the above copyright notice and this notice are
13#	left intact.
14#
15#	Please send copies of changes and bug-fixes to:
16#	sjg@crufty.net
17
18# This module provides automagic dependency generation along the
19# lines suggested in the GNU make.info
20# The depend target is mainly for backwards compatibility,
21# dependencies are normally updated as part of compilation.
22
23.if !target(__${.PARSEFILE}__)
24__${.PARSEFILE}__: .NOTMAIN
25
26DEPENDFILE?= .depend
27.for d in ${DEPENDFILE:N.depend}
28# bmake only groks .depend
29.if ${MAKE_VERSION} < 20160218
30.-include <$d>
31.else
32.dinclude <$d>
33.endif
34.endfor
35
36# should have been set by sys.mk
37CXX_SUFFIXES ?= .cc .ccm .cpp .cxx .C
38
39# it does nothing if SRCS is not defined or is empty
40.if defined(SRCS) && !empty(SRCS)
41DEPSRCS ?= ${SRCS}
42__depsrcs = ${DEPSRCS:M*.c}
43__depsrcs += ${DEPSRCS:M*.y}
44__depsrcs += ${DEPSRCS:M*.l}
45__depsrcs += ${DEPSRCS:M*.s}
46__depsrcs += ${DEPSRCS:M*.S}
47__depsrcs += ${DEPSRCS:M*.pc}
48.for s in ${CXX_SUFFIXES}
49__depsrcs += ${DEPSRCS:M*$s}
50.endfor
51
52.for s in ${__depsrcs}
53${s:T:R}.d:	$s
54.endfor
55
56__depsrcs := ${__depsrcs:T:R:S/$/.d/g}
57# we also need to handle makefiles where the .d's from __depsrcs
58# don't  match those from OBJS
59# we avoid using := here, since the modifier applied to OBJS
60# can cause trouble if there are any undefined vars in OBJS.
61__dependsrcsx ?= ${__depsrcs} ${OBJS:S/.o/.d/}
62__dependsrcs = ${__dependsrcsx:O:u}
63
64# clean up any .c files we may have generated
65#__gensrcs := ${DEPSRCS:M*.y} ${DEPSRCS:M*.l}
66#CLEANFILES += ${__gensrcs:T:R:S/$/.c/g}
67
68# set this to -MMD to ignore /usr/include
69# actually it ignores <> so may not be a great idea
70CFLAGS_MD ?= -MD
71# -MF etc not available on all gcc versions.
72# we "fix" the .o later
73.if ${COMPILER_TYPE:Ugcc} == "gcc" && ${COMPILER_VERSION:U0} < 30000
74CFLAGS_MF =
75.endif
76CFLAGS_MF ?= -MF ${.TARGET:T:R}.d -MT ${.TARGET:T:R}.o
77CFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
78RM?= rm
79MAKE_SHELL ?= sh
80
81# watch out for people who don't use CPPFLAGS
82CPPFLAGS_MD = ${CFLAGS:M-[IUD]*} ${CPPFLAGS}
83CXXFLAGS_MD = ${CXXFLAGS:M-[IUD]*} ${CPPFLAGS}
84
85# just in case these need to be different
86CC_MD ?= ${CC}
87CXX_MD ?= ${CXX}
88
89# so we can do an explicit make depend, but not otherwise
90.if make(depend)
91.SUFFIXES:	.d
92
93.if empty(CFLAGS_MD)
94.y.d:
95	@echo updating dependencies for $<
96	@${YACC} ${YFLAGS} $<
97	@${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} y.tab.c | sed '/:/s/^/$@ /' > $@" || { ${RM} -f y.tab.c $@; false; }
98	@${RM} -f y.tab.c
99
100.l.d:
101	@echo updating dependencies for $<
102	${LEX} ${LFLAGS} $<
103	@${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} lex.yy.c | sed '/:/s/^/$@ /' > $@" || { ${RM} -f lex.yy.c $@; false; }
104	@${RM} -f lex.yy.c
105
106.c.d:
107	@echo updating dependencies for $<
108	@${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
109
110.s.d .S.d:
111	@echo updating dependencies for $<
112	@${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} ${AINC} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
113
114${CXX_SUFFIXES:%=%.d}:
115	@echo updating dependencies for $<
116	@${MAKE_SHELL} -ec "${CXX_MD} -M ${CXXFLAGS_MD} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
117
118.else
119
120.y.d:
121	${YACC} ${YFLAGS} $<
122	${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} y.tab.c > $@ || { ${RM} -f y.tab.c $@; false; }
123	${RM} -f y.tab.c
124
125.l.d:
126	${LEX} ${LFLAGS} $<
127	${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} lex.yy.c > $@ || { ${RM} -f lex.yy.c $@; false; }
128	${RM} -f lex.yy.c
129
130.c.d:
131	${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} $< > $@ || { ${RM} -f $@; false; }
132
133.s.d .S.d:
134	${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} ${AINC} $< > $@ || { ${RM} -f $@; false; }
135
136${CXX_SUFFIXES:%=%.d}:
137	${CXX_MD} ${CFLAGS_MD:S/D//} ${CXXFLAGS_MD} $< > $@ || { ${RM} -f $@; false; }
138
139.endif
140
141.if !target(depend)
142depend: beforedepend ${DEPENDFILE} afterdepend _SUBDIRUSE
143
144${DEPENDFILE}:	${DEPSRCS} ${__dependsrcs}
145.NOPATH:	${__dependsrcs}
146.OPTIONAL:	${__dependsrcs}
147.endif
148.endif				# make(depend)
149
150.if empty(CFLAGS_MD)
151# make sure the .d's are generated/updated
152${PROG} ${_LIBS}:	${DEPENDFILE}
153.endif
154
155.ORDER:	beforedepend ${DEPENDFILE} afterdepend
156
157.if ${.OBJDIR} != ${.CURDIR}
158__depfiles = *.d
159.else
160__depfiles = ${__dependsrcs}
161.endif
162
163DEPCLEANFILES = ${DEPENDFILE} ${__depfiles} y.tab.d *.tmp.d
164
165cleandir: cleanautodepend
166cleanautodepend:
167	${RM} -f ${DEPCLEANFILES}
168
169CLEANFILES += ${DEPCLEANFILES}
170
171.if defined(__dependsrcs) && !empty(__dependsrcs)
172.if make(depend) || !(make(clean*) || make(destroy*) || make(obj) || make(*install) || make(install-*))
173# this ensures we do the right thing if only building a shared or
174# profiled lib
175OBJ_SUFFIXES ?= .o .po .so .So
176MDLIB_SED = -e '/:/s,^\([^\.:]*\)\.[psS]*o,${OBJ_SUFFIXES:S,^,\1,},'
177.ifdef NOMD_SED
178.ifdef LIB
179MD_SED = sed ${MDLIB_SED}
180.else
181MD_SED = cat
182.endif
183.else
184# arrange to put some variable names into ${DEPENDFILE}
185.ifdef LIB
186MD_SED = sed ${MDLIB_SED}
187.else
188MD_SED = sed
189.endif
190SUBST_DEPVARS += SB TOP BACKING SRC SRCDIR BASE BASEDIR
191.for v in ${SUBST_DEPVARS}
192.if defined(${v}) && !empty(${v})
193MD_SED += -e 's,${$v},$${$v},'
194.endif
195.endfor
196.endif
197.if (${MD_SED} == "sed")
198MD_SED = cat
199.endif
200
201# this will be done whenever make finishes successfully
202.if ${MAKE_VERSION:U0:[1]:C/.*-//} < 20050530
203.END:
204.else
205.END:	${DEPENDFILE}
206# we do not want to trigger building .d's just use them if they exist
207${DEPENDFILE}:	${__dependsrcs:@d@${exists($d):?$d:}@}
208.endif
209	-@${MD_SED} ${__depfiles} > ${DEPENDFILE}.new 2> /dev/null && \
210	test -s ${DEPENDFILE}.new && mv ${DEPENDFILE}.new ${DEPENDFILE}; \
211	${RM} -f ${DEPENDFILE}.new
212.endif
213.endif
214.else
215depend: beforedepend afterdepend _SUBDIRUSE
216.endif
217
218.if !target(beforedepend)
219beforedepend:
220.endif
221.if !target(afterdepend)
222afterdepend:
223.endif
224
225.-include <ccm.dep.mk>
226
227.endif
228