gendirdeps.mk revision 246149
1# $Id: gendirdeps.mk,v 1.10 2012/06/30 00:37:50 sjg Exp $
2
3# Copyright (c) 2010, Juniper Networks, Inc.
4# 
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions 
7# are met: 
8# 1. Redistributions of source code must retain the above copyright
9#    notice, this list of conditions and the following disclaimer. 
10# 2. Redistributions in binary form must reproduce the above copyright
11#    notice, this list of conditions and the following disclaimer in the
12#    documentation and/or other materials provided with the distribution.  
13# 
14# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25
26#
27# This makefile [re]generates ${.MAKE.DEPENDFILE}
28#
29
30.include <install-new.mk>
31
32# Assumptions:
33#	RELDIR is the relative path from ${SRCTOP} to ${_CURDIR}
34#		(SRCTOP is ${SB}/src)
35#	_CURDIR is the absolute version of ${.CURDIR}
36#	_OBJDIR is the absolute version of ${.OBJDIR}
37#	_objroot is realpath of ${_OBJTOP} without ${MACHINE}
38#		this may be different from _OBJROOT if $SB/obj is a
39#		symlink to another filesystem.
40#		_objroot must be a prefix match for _objtop
41
42.MAIN: all
43
44# keep this simple
45.MAKE.MODE = compat
46
47all:
48
49_CURDIR ?= ${.CURDIR}
50_OBJDIR ?= ${.OBJDIR}
51_OBJTOP ?= ${OBJTOP}
52_OBJROOT ?= ${OBJROOT:U${_OBJTOP}}
53_objroot ?= ${_OBJROOT:tA}
54
55_this = ${.PARSEDIR}/${.PARSEFILE}
56
57# remember what to make
58_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
59
60# We do _not_ want to read our own output!
61.MAKE.DEPENDFILE = /dev/null
62
63# caller should have set this
64META_FILES ?= ${.MAKE.META.FILES}
65
66.if !empty(META_FILES)
67
68.if ${.MAKE.LEVEL} > 0 && !empty(GENDIRDEPS_FILTER)
69# so we can compare below
70.-include <${_DEPENDFILE}>
71# yes, I mean :U with no value
72_DIRDEPS := ${DIRDEPS:U:O:u}
73.endif
74
75META_FILES := ${META_FILES:T:O:u}
76.export META_FILES
77
78# pickup customizations
79.-include "local.gendirdeps.mk"
80
81# these are actually prefixes that we'll skip
82# they should all be absolute paths
83SKIP_GENDIRDEPS ?=
84.if !empty(SKIP_GENDIRDEPS)
85_skip_gendirdeps = egrep -v '^(${SKIP_GENDIRDEPS:O:u:ts|})' |
86.else
87_skip_gendirdeps =
88.endif
89
90# this (*should* be set in meta.sys.mk) 
91# is the script that extracts what we want.
92META2DEPS ?= ${.PARSEDIR}/meta2deps.sh
93META2DEPS := ${META2DEPS}
94
95.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" && ${DEBUG_GENDIRDEPS:Uno:Mmeta2d*} != ""
96_time = time
97_sh_x = sh -x
98_py_d = -ddd
99.else
100_time =
101_sh_x =
102_py_d =
103.endif
104
105.if ${META2DEPS:E} == "py"
106# we can afford to do this all the time.
107DPDEPS ?= no
108META2DEPS_CMD = ${_time} ${PYTHON} ${META2DEPS} ${_py_d} \
109	-R ${RELDIR} -H ${HOST_TARGET} -O ${M2D_OBJROOT}
110.if ${DPDEPS:tl} != "no"
111META2DEPS_CMD += -D ${DPDEPS}
112.endif
113.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} == ""
114# meta2deps.py only groks objroot
115# so we need to give it what it expects
116M2D_OBJROOT = ${OBJTOP}/
117# and tell it not to add machine qualifiers
118META2DEPS_ARGS += MACHINE=none
119.else
120.if defined(SB_OBJROOT)
121M2D_OBJROOT ?= ${SB_OBJROOT}
122.else
123M2D_OBJROOT = ${OBJTOP}/
124.endif
125.endif
126.if defined(SB_BACKING_SB) 
127META2DEPS_CMD += -S ${SB_BACKING_SB}/src -O ${SB_BACKING_SB}/${SB_OBJPREFIX}
128.endif
129META2DEPS_FILTER = sed 's,^src:,${SRCTOP}/,;s,^\([^/]\),${OBJTOP}/\1,' |
130.elif ${META2DEPS:E} == "sh"
131META2DEPS_CMD = ${_time} ${_sh_x} ${META2DEPS} \
132	OBJTOP=${_objtop} SB_OBJROOT=${_objroot}
133.else
134META2DEPS_CMD ?= ${META2DEPS}
135.endif
136
137# we are only interested in the dirs
138# sepecifically those we read something from.
139# we canonicalize them to keep things simple
140# if we are using a split-fs sandbox, it gets a little messier.
141_objtop := ${_OBJTOP:tA}
142dir_list != cd ${_OBJDIR} && \
143	${META2DEPS_CMD} MACHINE=${MACHINE} \
144	SRCTOP=${SRCTOP} RELDIR=${RELDIR} CURDIR=${_CURDIR} \
145	${META2DEPS_ARGS} \
146	${META_FILES:O:u} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \
147	sed 's,//*$$,,;s,\.${HOST_TARGET}$$,.host,'
148
149.if ${dir_list:M*ERROR\:*} != ""
150.warning ${dir_list:tW:C,.*(ERROR),\1,}
151.warning Skipping ${_DEPENDFILE:S,${SRCTOP}/,,}
152# we are not going to update anything
153.else
154
155.if !empty(DPADD)
156_nonlibs := ${DPADD:T:Nlib*:N*include}
157.if !empty(_nonlibs)
158dir_list += ${_nonlibs:@x@${DPADD:M*/$x}@:H:tA}
159.endif
160.endif
161
162# DIRDEPS represent things that had to have been built first
163# so they should all be undir OBJTOP.
164# Note that ${_OBJTOP}/bsd/include/machine will get reported 
165# to us as $SRCTOP/bsd/sys/$MACHINE_ARCH/include meaning we
166# will want to visit bsd/include
167# so we add 
168# ${"${dir_list:M*bsd/sys/${MACHINE_ARCH}/include}":?bsd/include:}
169# to GENDIRDEPS_DIR_LIST_XTRAS
170dirdep_list = \
171	${dir_list:M${_objtop}*/*:C,${_objtop}[^/]*/,,} \
172	${GENDIRDEPS_DIR_LIST_XTRAS}
173
174# anything we use from an object dir other than ours
175# needs to be qualified with its .<machine> suffix
176# (we used the pseudo machine "host" for the HOST_TARGET).
177qualdir_list = \
178	${dir_list:M${_objroot}*/*/*:N${SRCTOP}*:N${_objtop}*:C,${_objroot}([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,}
179
180.if ${_OBJROOT} != ${_objroot}
181dirdep_list += \
182	${dir_list:M${_OBJTOP}*/*:C,${_OBJTOP}[^/]*/,,}
183
184qualdir_list += \
185	${dir_list:M${_OBJROOT}*/*/*:N${SRCTOP}*:N${_OBJTOP}*:C,${_OBJROOT}([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,}
186.endif
187
188dirdep_list := ${dirdep_list:O:u}
189qualdir_list := ${qualdir_list:O:u}
190
191DIRDEPS = \
192	${dirdep_list:N${RELDIR}:N${RELDIR}/*} \
193	${qualdir_list:N${RELDIR}.*:N${RELDIR}/*}
194
195# We only consider things below $RELDIR/ if they have a makefile.
196# This is the same test that _DIRDEPS_USE applies.
197# We have do a double test with dirdep_list as it _may_ contain 
198# qualified dirs - if we got anything from a stage dir.
199# qualdir_list we know are all qualified.
200# It would be nice do peform this check for all of DIRDEPS,
201# but we cannot assume that all of the tree is present, 
202# in fact we can only assume that RELDIR is.
203DIRDEPS += \
204	${dirdep_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/$d/$m):?$d:${exists(${SRCTOP}/${d:R}/$m):?$d:}}@}@} \
205	${qualdir_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/${d:R}/$m):?$d:}@}@}
206
207DIRDEPS := ${DIRDEPS:${GENDIRDEPS_FILTER:UNno:ts:}:O:u}
208
209.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != ""
210.info ${RELDIR}: dir_list='${dir_list}'
211.info ${RELDIR}: dirdep_list='${dirdep_list}'
212.info ${RELDIR}: qualdir_list='${qualdir_list}'
213.info ${RELDIR}: SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS}'
214.info ${RELDIR}: GENDIRDEPS_FILTER='${GENDIRDEPS_FILTER}'
215.info ${RELDIR}: FORCE_DPADD='${DPADD}'
216.info ${RELDIR}: DIRDEPS='${DIRDEPS}'
217.endif
218
219# SRC_DIRDEPS is for checkout logic
220src_dirdep_list = \
221	${dir_list:M${SRCTOP}/*:S,${SRCTOP}/,,}
222
223SRC_DIRDEPS = \
224	${src_dirdep_list:N${RELDIR}:N${RELDIR}/*:C,(/h)/.*,,}
225
226SRC_DIRDEPS := ${SRC_DIRDEPS:${GENDIRDEPS_SRC_FILTER:UN/*:ts:}:O:u}
227
228# if you want to capture SRC_DIRDEPS in .MAKE.DEPENDFILE put
229# SRC_DIRDEPS_FILE = ${_DEPENDFILE} 
230# in local.gendirdeps.mk
231.if ${SRC_DIRDEPS_FILE:Uno:tl} != "no"
232ECHO_SRC_DIRDEPS = echo 'SRC_DIRDEPS = \'; echo '${SRC_DIRDEPS:@d@	$d \\${.newline}@}'; echo;
233
234.if ${SRC_DIRDEPS_FILE:T} == ${_DEPENDFILE:T}
235_include_src_dirdeps = ${ECHO_SRC_DIRDEPS}
236.else
237all: ${SRC_DIRDEPS_FILE}
238.if !target(${SRC_DIRDEPS_FILE})
239${SRC_DIRDEPS_FILE}: ${META_FILES} ${_this} ${META2DEPS}
240	@(${ECHO_SRC_DIRDEPS}) > $@
241.endif
242.endif
243.endif
244_include_src_dirdeps ?= 
245
246all:	${_DEPENDFILE}
247
248# if this is going to exist it would be there by now
249.if !exists(.depend)
250CAT_DEPEND = /dev/null
251.endif
252CAT_DEPEND ?= .depend
253
254.if !empty(_DIRDEPS) && ${DIRDEPS} != ${_DIRDEPS}
255# we may have changed a filter
256.PHONY: ${_DEPENDFILE}
257.endif
258
259# 'cat .depend' should suffice, but if we are mixing build modes
260# .depend may contain things we don't want.
261# The sed command at the end of the stream, allows for the filters
262# to output _{VAR} tokens which we will turn into proper ${VAR} references.
263${_DEPENDFILE}: ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS}
264	@(echo '# Autogenerated - do NOT edit!'; echo; \
265	echo 'DEP_RELDIR := $${_PARSEDIR:S,$${SRCTOP}/,,}'; echo; \
266	echo 'DEP_MACHINE := $${.PARSEFILE:E}'; echo; \
267	echo 'DIRDEPS = \'; \
268	echo '${DIRDEPS:@d@	$d \\${.newline}@}'; echo; \
269	${_include_src_dirdeps} \
270	echo '.include <dirdeps.mk>'; \
271	echo; \
272	echo '.if $${DEP_RELDIR} == $${_DEP_RELDIR}'; \
273	echo '# local dependencies - needed for -jN in clean tree'; \
274	[ -s ${CAT_DEPEND} ] && { grep : ${CAT_DEPEND} | grep -v '[/\\]'; }; \
275	echo '.endif' ) | sed 's,_\([{(]\),$$\1,g' > $@.new${.MAKE.PID}
276	@${InstallNew}; InstallNew -s $@.new${.MAKE.PID}
277
278.endif				# meta2deps failed
279.elif !empty(SUBDIR)
280
281DIRDEPS := ${SUBDIR:S,^,${RELDIR}/,:O:u}
282
283all:	${_DEPENDFILE}
284
285${_DEPENDFILE}: ${MAKEFILE} ${_this}
286	@(echo '# Autogenerated - do NOT edit!'; echo; \
287	echo 'DEP_RELDIR := $${_PARSEDIR:S,$${SRCTOP}/,,}'; echo; \
288	echo 'DEP_MACHINE := $${.PARSEFILE:E}'; echo; \
289	echo 'DIRDEPS = \'; \
290	echo '${DIRDEPS:@d@	$d \\${.newline}@}'; echo; \
291	echo '.include <dirdeps.mk>'; \
292	echo ) | sed 's,_\([{(]\),$$\1,g' > $@.new
293	@${InstallNew}; InstallNew $@.new
294
295.else
296
297# nothing to do
298all ${_DEPENDFILE}:
299
300.endif
301${_DEPENDFILE}: .PRECIOUS
302