1 # $Id: dirdeps.mk,v 1.28 2013/03/25 21:11:43 sjg Exp $
3 # Copyright (c) 2010-2013, Juniper Networks, Inc.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 # Much of the complexity here is for supporting cross-building.
28 # If a tree does not support that, simply using plain Makefile.depend
29 # should provide sufficient clue.
30 # Otherwise the recommendation is to use Makefile.depend.${MACHINE}
33 # Note: this file gets multiply included.
34 # This is what we do with DIRDEPS
37 # This is a list of directories - relative to SRCTOP, it is
38 # normally only of interest to .MAKE.LEVEL 0.
39 # In some cases the entry may be qualified with a .<machine>
40 # or .<target_spec> suffix (see TARGET_SPEC_VARS below),
41 # for example to force building something for the pseudo
42 # machines "host" or "common" regardless of current ${MACHINE}.
44 # All unqualified entries end up being qualified with .${TARGET_SPEC}
45 # and partially qualified (if TARGET_SPEC_VARS has multiple
46 # entries) are also expanded to a full .<target_spec>.
47 # The _DIRDEPS_USE target uses the suffix to set TARGET_SPEC
48 # correctly when visiting each entry.
50 # The fully qualified directory entries are used to construct a
51 # dependency graph that will drive the build later.
53 # Also, for each fully qualified directory target, we will search
54 # using ${.MAKE.DEPENDFILE_PREFERENCE} to find additional
55 # dependencies. We use Makefile.depend (default value for
56 # .MAKE.DEPENDFILE_PREFIX) to refer to these makefiles to
57 # distinguish them from others.
59 # Each Makefile.depend file sets DEP_RELDIR to be the
60 # the RELDIR (path relative to SRCTOP) for its directory, and
61 # since each Makefile.depend file includes dirdeps.mk, this
62 # processing is recursive and results in .MAKE.LEVEL 0 learning the
63 # dependencies of the tree wrt the initial directory (_DEP_RELDIR).
66 # Indicates whether .MAKE.LEVEL 0 builds anything:
67 # if "no" sub-makes are used to build everything,
68 # if "yes" sub-makes are only used to build for other machines.
69 # It is best to use "no", but this can require fixing some
70 # makefiles to not do anything at .MAKE.LEVEL 0.
73 # The default value is just MACHINE, and for most environments
74 # this is sufficient. The _DIRDEPS_USE target actually sets
75 # both MACHINE and TARGET_SPEC to the suffix of the current
76 # target so that in the general case TARGET_SPEC can be ignored.
78 # If more than MACHINE is needed then sys.mk needs to decompose
79 # TARGET_SPEC and set the relevant variables accordingly.
80 # It is important that MACHINE be included in and actually be
81 # the first member of TARGET_SPEC_VARS. This allows other
82 # variables to be considered optional, and some of the treatment
83 # below relies on MACHINE being the first entry.
84 # Note: TARGET_SPEC cannot contain any '.'s so the target
85 # triple used by compiler folk won't work (directly anyway).
89 # # Always list MACHINE first,
90 # # other variables might be optional.
91 # TARGET_SPEC_VARS = MACHINE TARGET_OS
92 # .if ${TARGET_SPEC:Uno:M*,*} != ""
93 # _tspec := ${TARGET_SPEC:S/,/ /g}
94 # MACHINE := ${_tspec:[1]}
95 # TARGET_OS := ${_tspec:[2]}
97 # # We need to stop that TARGET_SPEC affecting any submakes
98 # # and deal with MACHINE=${TARGET_SPEC} in the environment.
100 # # export but do not track
101 # .export-env TARGET_SPEC
102 # .export ${TARGET_SPEC_VARS}
103 # .for v in ${TARGET_SPEC_VARS:O:u}
109 # # make sure we know what TARGET_SPEC is
110 # # as we may need it to find Makefile.depend*
111 # TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
114 .if
${.MAKE.LEVEL
} == 0
115 # only the first instance is interested in all this
117 # First off, we want to know what ${MACHINE} to build for.
118 # This can be complicated if we are using a mixture of ${MACHINE} specific
119 # and non-specific Makefile.depend*
121 .if
!target
(_DIRDEP_USE
)
122 # do some setup we only need once
123 _CURDIR ?
= ${.CURDIR
}
125 # make sure these are empty to start with
129 # If TARGET_SPEC_VARS is other than just MACHINE
130 # it should be set by sys.mk or similar by now.
131 # TARGET_SPEC must not contain any '.'s.
132 TARGET_SPEC_VARS ?
= MACHINE
133 # this is what we started with
134 TARGET_SPEC
= ${TARGET_SPEC_VARS
:@v@
${$v:U
}@
:ts
,}
135 # this is what we mostly use below
136 DEP_TARGET_SPEC
= ${TARGET_SPEC_VARS
:S
,^
,DEP_
,:@v@
${$v:U
}@
:ts
,}
137 # make sure we have defaults
138 .for v in
${TARGET_SPEC_VARS}
142 .if
${TARGET_SPEC_VARS
:[#]} > 1
143 # Ok, this gets more complex (putting it mildly).
144 # In order to stay sane, we need to ensure that all the build_dirs
145 # we compute below are fully qualified wrt DEP_TARGET_SPEC.
146 # The makefiles may only partially specify (eg. MACHINE only),
147 # so we need to construct a set of modifiers to fill in the gaps.
148 # jot 10 should output 1 2 3 .. 10
150 _tspec_x
:= ${${JOT} ${TARGET_SPEC_VARS
:[#]}:L:sh}
151 # this handles unqualified entries
152 M_dep_qual_fixes
= C
;(/[^
/.
,]+)$$;\
1.
${DEP_TARGET_SPEC};
153 # there needs to be at least one item missing for these to make sense
154 .for i in
${_tspec_x
:[2..
-1]}
155 _tspec_m
$i := ${TARGET_SPEC_VARS
:[2..
$i]:@w@
[^
,]+@
:ts
,}
156 _tspec_a
$i := ,${TARGET_SPEC_VARS
:[$i..
-1]:@v@
$${DEP_
$v}@
:ts
,}
157 M_dep_qual_fixes
+= C
;(\.
${_tspec_m
$i})$$;\
1${_tspec_a
$i};
160 # A harmless? default.
164 .if
!defined
(.MAKE.DEPENDFILE_PREFERENCE
)
165 # .MAKE.DEPENDFILE_PREFERENCE makes the logic below neater?
166 # you really want this set by sys.mk or similar
167 .MAKE.DEPENDFILE_PREFERENCE
= ${_CURDIR}/${.MAKE.DEPENDFILE
:T
}
168 .if
${.MAKE.DEPENDFILE
:E
} == "${TARGET_SPEC}"
169 .if
${TARGET_SPEC} != ${MACHINE}
170 .MAKE.DEPENDFILE_PREFERENCE
+= ${_CURDIR}/${.MAKE.DEPENDFILE
:T
:R
}.
$${MACHINE}
172 .MAKE.DEPENDFILE_PREFERENCE
+= ${_CURDIR}/${.MAKE.DEPENDFILE
:T
:R
}
176 _default_dependfile
:= ${.MAKE.DEPENDFILE_PREFERENCE
:[1]:T
}
177 _machine_dependfiles
:= ${.MAKE.DEPENDFILE_PREFERENCE
:T
:M
*${MACHINE}*}
179 # for machine specific dependfiles we require ${MACHINE} to be at the end
180 # also for the sake of sanity we require a common prefix
181 .if
!defined
(.MAKE.DEPENDFILE_PREFIX
)
182 # knowing .MAKE.DEPENDFILE_PREFIX helps
183 .if
!empty
(_machine_dependfiles
)
184 .MAKE.DEPENDFILE_PREFIX
:= ${_machine_dependfiles
:[1]:T
:R
}
186 .MAKE.DEPENDFILE_PREFIX
:= ${_default_dependfile
:T
}
191 # this is how we identify non-machine specific dependfiles
192 N_notmachine
:= ${.MAKE.DEPENDFILE_PREFERENCE
:E
:N
*${MACHINE}*:${M_ListToSkip}}
194 .
endif # !target(_DIRDEP_USE)
196 # if we were included recursively _DEP_TARGET_SPEC should be valid.
197 .if empty
(_DEP_TARGET_SPEC
)
198 # we may or may not have included a dependfile yet
199 _last_dependfile
:= ${.MAKE.MAKEFILES
:M
*/${.MAKE.DEPENDFILE_PREFIX
}*:[-1]}
200 .if
!empty
(_debug_reldir
)
201 .
info ${DEP_RELDIR}.
${DEP_TARGET_SPEC}: _last_dependfile
='${_last_dependfile}'
204 .if empty
(_last_dependfile
) ||
${_last_dependfile
:E
:${N_notmachine}} == ""
205 # this is all we have to work with
206 DEP_MACHINE
= ${TARGET_MACHINE
:U
${MACHINE}}
207 _DEP_TARGET_SPEC
:= ${DEP_TARGET_SPEC}
209 _DEP_TARGET_SPEC
= ${_last_dependfile
:${M_dep_qual_fixes
:ts
:}:E
}
211 .if
!empty
(_last_dependfile
)
212 # record that we've read dependfile for this
213 _DIRDEP_CHECKED
+= ${_CURDIR}.
${TARGET_SPEC}
217 # by now _DEP_TARGET_SPEC should be set, parse it.
218 .if
${TARGET_SPEC_VARS
:[#]} > 1
219 # we need to parse DEP_MACHINE may or may not contain more info
220 _tspec
:= ${_DEP_TARGET_SPEC
:S
/,/ /g
}
221 .for i in
${_tspec_x}
222 DEP_
${TARGET_SPEC_VARS
:[$i]} := ${_tspec
:[$i]}
224 .for v in
${TARGET_SPEC_VARS
:O
:u
}
230 DEP_MACHINE
:= ${_DEP_TARGET_SPEC}
233 # pickup customizations
234 # as below you can use !target(_DIRDEP_USE) to protect things
235 # which should only be done once.
236 .
-include "local.dirdeps.mk"
238 # the first time we are included the _DIRDEP_USE target will not be defined
239 # we can use this as a clue to do initialization and other one time things.
240 .if
!target
(_DIRDEP_USE
)
241 # make sure this target exists
244 # We normally expect to be included by Makefile.depend.*
245 # which sets the DEP_* macros below.
246 DEP_RELDIR ?
= ${RELDIR}
248 # this can cause lots of output!
249 # set to a set of glob expressions that might match RELDIR
252 # remember the initial value of DEP_RELDIR - we test for it below.
253 _DEP_RELDIR
:= ${DEP_RELDIR}
255 # things we skip for host tools
258 NSkipHostDir
= ${SKIP_HOSTDIR
:N
*.host
:S
,$,.host
,:N.host
:${M_ListToSkip}}
260 # things we always skip
261 # SKIP_DIRDEPS allows for adding entries on command line.
262 SKIP_DIR
+= .host
*.WAIT
${SKIP_DIRDEPS}
263 SKIP_DIR.host
+= ${SKIP_HOSTDIR}
265 DEP_SKIP_DIR
= ${SKIP_DIR} \
266 ${SKIP_DIR.
${DEP_TARGET_SPEC}:U
} \
267 ${SKIP_DIR.
${DEP_MACHINE}:U
} \
268 ${SKIP_DIRDEPS.
${DEP_MACHINE}:U
}
270 NSkipDir
= ${DEP_SKIP_DIR
:${M_ListToSkip}}
272 .if defined
(NO_DIRDEPS
) || defined
(NODIRDEPS
)
273 # confine ourselves to the original dir
274 DIRDEPS_FILTER
+= M
${_DEP_RELDIR}*
277 # we supress SUBDIR when visiting the leaves
278 # we assume sys.mk will set MACHINE_ARCH
279 # you can add extras to DIRDEP_USE_ENV
280 # if there is no makefile in the target directory, we skip it.
281 _DIRDEP_USE
: .USE .MAKE
282 @for m in
${.MAKE.MAKEFILE_PREFERENCE
}; do \
283 test -s
${.TARGET
:R
}/$$m || continue
; \
284 echo
"${TRACER}Checking ${.TARGET:R} for ${.TARGET:E} ..."; \
285 MACHINE_ARCH
= NO_SUBDIR
=1 ${DIRDEP_USE_ENV} \
286 TARGET_SPEC
=${.TARGET
:E
} \
287 MACHINE
=${.TARGET
:E
} \
288 ${.MAKE
} -C
${.TARGET
:R
} || exit
1; \
293 # this is how you limit it to only the machines we have been built for
295 .if empty
(ONLY_MACHINE_LIST
)
296 .if
!empty
(ALL_MACHINE_LIST
)
297 # ALL_MACHINE_LIST is the list of all legal machines - ignore anything else
298 _machine_list
!= cd
${_CURDIR} && 'ls' -1 ${ALL_MACHINE_LIST
:O
:u
:@m@
${.MAKE.DEPENDFILE
:T
:R
}.
$m@
} 2> /dev
/null
; echo
300 _machine_list
!= 'ls' -1 ${_CURDIR}/${.MAKE.DEPENDFILE_PREFIX
}.
* 2> /dev
/null
; echo
302 _only_machines
:= ${_machine_list
:${NIgnoreFiles
:UN
*.bak
}:E
:O
:u
}
304 _only_machines
:= ${ONLY_MACHINE_LIST}
307 .if empty
(_only_machines
)
308 # we must be boot-strapping
309 _only_machines
:= ${TARGET_MACHINE
:U
${ALL_MACHINE_LIST
:U
${DEP_MACHINE}}}
312 .
else # ! ALL_MACHINES
313 # if ONLY_MACHINE_LIST is set, we are limited to that
314 # if TARGET_MACHINE is set - it is really the same as ONLY_MACHINE_LIST
315 # otherwise DEP_MACHINE is it - so DEP_MACHINE will match.
316 _only_machines
:= ${ONLY_MACHINE_LIST
:U
${TARGET_MACHINE
:U
${DEP_MACHINE}}:M
${DEP_MACHINE}}
319 .if
!empty
(NOT_MACHINE_LIST
)
320 _only_machines
:= ${_only_machines
:${NOT_MACHINE_LIST
:${M_ListToSkip}}}
323 # make sure we have a starting place?
327 _debug_reldir
:= ${DEBUG_DIRDEPS
:@x@
${DEP_RELDIR
:M
$x}${${DEP_RELDIR}.
${DEP_MACHINE}:L
:M
$x}@
}
328 _debug_search
:= ${DEBUG_DIRDEPS
:@x@
${DEP_RELDIR
:M
$x}${${DEP_RELDIR}.depend
:L
:M
$x}@
}
330 # the rest is done repeatedly for every Makefile.depend we read.
331 # if we are anything but the original dir we care only about the
332 # machine type we were included for..
334 .if
${DEP_RELDIR} == "."
335 _this_dir
:= ${SRCTOP}
337 _this_dir
:= ${SRCTOP}/${DEP_RELDIR}
340 # on rare occasions, there can be a need for extra help
341 _dep_hack
:= ${_this_dir}/${.MAKE.DEPENDFILE_PREFIX
}.inc
342 .
-include "${_dep_hack}"
344 .if
${DEP_RELDIR} != ${_DEP_RELDIR} ||
${DEP_TARGET_SPEC} != ${TARGET_SPEC}
346 _machines
:= ${DEP_MACHINE}
348 # this is the machine list we actually use below
349 _machines
:= ${_only_machines}
351 .if defined
(HOSTPROG
) ||
${DEP_MACHINE} == "host"
352 # we need to build this guy's dependencies for host as well.
356 _machines
:= ${_machines
:O
:u
}
359 .if
${TARGET_SPEC_VARS
:[#]} > 1
360 # we need to tweak _machines
361 _dm
:= ${DEP_MACHINE}
362 _machines
:= ${_machines
:@DEP_MACHINE@
${DEP_TARGET_SPEC}@
}
363 DEP_MACHINE
:= ${_dm}
366 # reset each time through
369 .if
${DEP_RELDIR} == ${_DEP_RELDIR}
370 # pickup other machines for this dir if necessary
371 .if
${BUILD_AT_LEVEL0
:Uyes
} == "no"
372 _build_dirs
+= ${_machines
:@m@
${_CURDIR}.
$m@
}
374 _build_dirs
+= ${_machines
:N
${DEP_TARGET_SPEC}:@m@
${_CURDIR}.
$m@
}
375 .if
${DEP_TARGET_SPEC} == ${TARGET_SPEC}
376 # pickup local dependencies now
382 .if
!empty
(_debug_reldir
)
383 .
info ${DEP_RELDIR}.
${DEP_TARGET_SPEC}: DIRDEPS
='${DIRDEPS}'
384 .
info ${DEP_RELDIR}.
${DEP_TARGET_SPEC}: _machines
='${_machines}'
388 # these we reset each time through as they can depend on DEP_MACHINE
389 DEP_DIRDEPS_FILTER
= \
390 ${DIRDEPS_FILTER.
${DEP_TARGET_SPEC}:U
} \
391 ${DIRDEPS_FILTER.
${DEP_MACHINE}:U
} \
393 .if empty
(DEP_DIRDEPS_FILTER
)
395 DEP_DIRDEPS_FILTER
= U
398 # this is what we start with
399 __depdirs
:= ${DIRDEPS
:${NSkipDir}:${DEP_DIRDEPS_FILTER
:ts
:}:O
:u
:@d@
${SRCTOP}/$d@
}
401 # some entries may be qualified with .<machine>
402 # the :M*/*/*.* just tries to limit the dirs we check to likely ones.
403 # the ${d:E:M*/*} ensures we don't consider junos/usr.sbin/mgd
404 __qual_depdirs
:= ${__depdirs
:M
*/*/*.
*:@d@
${exists
($d):?
:${"${d:E:M*/*}":?
:${exists
(${d
:R
}):?
$d:}}}@
}
405 __unqual_depdirs
:= ${__depdirs
:${__qual_depdirs
:Uno
:${M_ListToSkip}}}
407 .if
${DEP_RELDIR} == ${_DEP_RELDIR}
408 # if it was called out - we likely need it.
409 __hostdpadd
:= ${DPADD
:U.
:M
${HOST_OBJTOP}/*:S
,${HOST_OBJTOP}/,,:H
:${NSkipDir}:${DIRDEPS_FILTER
:ts
:}:S
,$,.host
,:N.
*:@d@
${SRCTOP}/$d@
}
410 __qual_depdirs
+= ${__hostdpadd}
413 .if
!empty
(_debug_reldir
)
414 .
info depdirs
=${__depdirs}
415 .
info qualified
=${__qual_depdirs}
416 .
info unqualified
=${__unqual_depdirs}
419 # _build_dirs is what we will feed to _DIRDEP_USE
421 ${__qual_depdirs
:M
*.host
:${NSkipHostDir}:N.host
} \
422 ${__qual_depdirs
:N
*.host
} \
423 ${_machines
:@m@
${__unqual_depdirs
:@d@
$d.
$m@
}@
}
425 # qualify everything now
426 _build_dirs
:= ${_build_dirs
:${M_dep_qual_fixes
:ts
:}:O
:u
}
428 .
endif # empty DIRDEPS
430 # Normally if doing make -V something,
431 # we do not want to waste time chasing DIRDEPS
432 # but if we want to count the number of Makefile.depend* read, we do.
433 .if
${.MAKEFLAGS
:M-V
${_V_READ_DIRDEPS}} == ""
434 .if
!empty
(_build_dirs
)
435 # this makes it all happen
436 dirdeps
: ${_build_dirs}
437 ${_build_dirs}: _DIRDEP_USE
439 .if
!empty
(_debug_reldir
)
440 .
info ${DEP_RELDIR}.
${DEP_TARGET_SPEC}: needs
: ${_build_dirs}
443 # this builds the dependency graph
444 .for m in
${_machines}
445 # it would be nice to do :N${.TARGET}
446 .if
!empty
(__qual_depdirs
)
447 .for q in
${__qual_depdirs
:${M_dep_qual_fixes
:ts
:}:E
:O
:u
:N
$m}
448 .if
!empty
(_debug_reldir
) ||
${DEBUG_DIRDEPS
:@x@
${${DEP_RELDIR}.
$m:L
:M
$x}${${DEP_RELDIR}.
$q:L
:M
$x}@
} != ""
449 .
info ${DEP_RELDIR}.
$m: graph
: ${_build_dirs
:M
*.
$q}
451 ${_this_dir}.
$m: ${_build_dirs
:M
*.
$q}
454 .if
!empty
(_debug_reldir
)
455 .
info ${DEP_RELDIR}.
$m: graph
: ${_build_dirs
:M
*.
$m:N
${_this_dir}.
$m}
457 ${_this_dir}.
$m: ${_build_dirs
:M
*.
$m:N
${_this_dir}.
$m}
462 # Now find more dependencies - and recurse.
463 .for d in
${_build_dirs}
464 .if
${_DIRDEP_CHECKED
:M
$d} == ""
466 _DIRDEP_CHECKED
+= $d
467 # Note: _build_dirs is fully qualifed so d:R is always the directory
469 # Warning: there is an assumption here that MACHINE is always
470 # the first entry in TARGET_SPEC_VARS.
471 # If TARGET_SPEC and MACHINE are insufficient, you have a problem.
472 _m
:= ${.MAKE.DEPENDFILE_PREFERENCE
:T
:S
;${TARGET_SPEC}$;${d
:E
};:S
;${MACHINE};${d
:E
:C
/,.
*//};:@m@
${exists
(${d
:R
}/$m):?
${d
:R
}/$m:}@
:[1]}
474 _qm
:= ${_m
:${M_dep_qual_fixes
:ts
:}}
475 .if
!empty
(_debug_search
)
476 .
info Looking for
${_qm}
478 # we pass _DEP_TARGET_SPEC to tell the next step what we want
479 _DEP_TARGET_SPEC
:= ${d
:E
}
480 # some makefiles may still look at this
481 _DEP_MACHINE
:= ${d
:E
:C
/,.
*//}
482 .if
!empty
(_debug_reldir
) && ${_qm} != ${_m}
483 .
info loading
${_m} for
${d
:E
}
493 .elif
${.MAKE.LEVEL
} > 42
494 .error You should have stopped recursing by now.
496 _DEP_RELDIR
:= ${DEP_RELDIR}
497 # pickup local dependencies