1# RCSid:
2#       $Id: dirdeps-targets.mk,v 1.24 2020/12/11 18:15:43 sjg Exp $
3#
4#       @(#) Copyright (c) 2019-2020 Simon J. Gerraty
5#
6#       This file is provided in the hope that it will
7#       be of use.  There is absolutely NO WARRANTY.
8#       Permission to copy, redistribute or otherwise
9#       use this file is hereby granted provided that
10#       the above copyright notice and this notice are
11#       left intact.
12#
13#       Please send copies of changes and bug-fixes to:
14#       sjg@crufty.net
15#
16
17##
18# This makefile is used to set initial DIRDEPS for top-level build
19# targets.
20#
21# The basic idea is that we have a list of directories in
22# DIRDEPS_TARGETS_DIRS which are relative to SRCTOP.
23# When asked to make 'foo' we look for any directory named 'foo'
24# under DIRDEPS_TARGETS_DIRS.
25# We then search those dirs for any Makefile.depend*
26# Finally we select any that match conditions like REQUESTED_MACHINE
27# or TARGET_SPEC and initialize DIRDEPS accordingly.
28#
29# We will check each of the initial DIRDEPS for Makefile.dirdeps.options
30# and include any found.
31# This makes it feasible to tweak options like MK_DIRDEPS_CACHE
32# for a specific target.
33#
34# If MK_STATIC_DIRDEPS_CACHE is defined we will check if the
35# initial DIRDEPS has a static cache (Makefile.dirdeps.cache).
36# This only makes sense for seriously expensive targets.
37#
38
39.if ${.MAKE.LEVEL} == 0
40# pickup customizations
41.-include <local.dirdeps-targets.mk>
42
43# for DIRDEPS_BUILD this is how we prime the pump
44# include . to allow any directory to work as a target
45DIRDEPS_TARGETS_DIRS ?= targets targets/pseudo
46# these prefixes can modify how we behave
47# they need to be stripped when looking for target dirs
48DIRDEPS_TARGETS_PREFIX_LIST ?= pkg- build-
49
50# some .TARGETS need filtering
51DIRDEPS_TARGETS_FILTER += Nall
52
53# matching target dirs if any
54tdirs := ${.TARGETS:${DIRDEPS_TARGETS_FILTER:ts:}:${DIRDEPS_TARGETS_PREFIX_LIST:@p@S,^$p,,@:ts:}:@t@${DIRDEPS_TARGETS_DIRS:@d@$d/$t@}@:@d@${exists(${SRCTOP}/$d):?$d:}@}
55
56.if !empty(DEBUG_DIRDEPS_TARGETS)
57.info tdirs=${tdirs}
58.endif
59
60.if !empty(tdirs)
61# some things we know we want to ignore
62DIRDEPS_TARGETS_SKIP_LIST += \
63	*~ \
64	*.bak \
65	*.inc \
66	*.old \
67	*.options \
68	*.orig \
69	*.rej \
70
71# the list of MACHINEs we consider
72DIRDEPS_TARGETS_MACHINE_LIST += \
73	${ALL_MACHINE_LIST:U} \
74	${PSEUDO_MACHINE_LIST:Ucommon host host32} \
75	${TARGET_MACHINE_LIST}
76
77DIRDEPS_TARGETS_MACHINE_LIST := ${DIRDEPS_TARGETS_MACHINE_LIST:O:u}
78
79# raw Makefile.depend* list
80tdeps != 'cd' ${SRCTOP} && 'ls' -1 ${tdirs:O:u:@d@$d/${.MAKE.DEPENDFILE_PREFIX}*@:S,^./,,} 2> /dev/null; echo
81.if ${DEBUG_DIRDEPS_TARGETS:U:Mdep*} != ""
82.info tdeps=${tdeps}
83.endif
84# remove things we know we don't want
85tdeps := ${tdeps:${DIRDEPS_TARGETS_SKIP_LIST:${M_ListToSkip}}}
86.if ${DEBUG_DIRDEPS_TARGETS:U:Mdep*} != ""
87.info tdeps=${tdeps}
88.endif
89
90# plain entries (no qualifiers) these apply to any TARGET_SPEC
91ptdeps := ${tdeps:M*${.MAKE.DEPENDFILE_PREFIX}:S,/${.MAKE.DEPENDFILE_PREFIX},,}
92
93# MACHINE qualified entries
94mqtdeps := ${DIRDEPS_TARGETS_MACHINE_LIST:@m@${tdeps:M*.$m}@:S,/${.MAKE.DEPENDFILE_PREFIX},,}
95
96tqtdeps =
97.if ${TARGET_SPEC_VARS:[#]} > 1
98# TARGET_SPEC qualified entries
99.if !empty(TARGET_SPEC_LIST)
100# we have a list of valid TARGET_SPECS; use it
101tqtdeps := ${TARGET_SPEC_LIST:U:O:u:@t@${tdeps:M*.$t}@:S,/${.MAKE.DEPENDFILE_PREFIX},,}
102.else
103# do we have a list of valid tuple members for at least
104# the last tupple element? if so match on that
105TARGET_SPEC_LAST_LIST ?= ${${TARGET_SPEC_VARS:[-1]}_LIST}
106.if !empty(TARGET_SPEC_LAST_LIST)
107tqtdeps := ${TARGET_SPEC_LAST_LIST:U:O:u:@t@${tdeps:M*,$t}@:S,/${.MAKE.DEPENDFILE_PREFIX},,}
108.else
109# this is sub-optimal match MACHINE,
110tqtdeps := ${DIRDEPS_TARGETS_MACHINE_LIST:@m@${tdeps:M*.$m,*}@:S,/${.MAKE.DEPENDFILE_PREFIX},,}
111.endif
112.endif
113.endif
114
115# now work out what we want in DIRDEPS
116.if empty(REQUESTED_MACHINE)
117# we want them all just as found
118DIRDEPS = ${ptdeps} ${mqtdeps} ${tqtdeps}
119.else
120# we only want those that match REQUESTED_MACHINE/REQUESTED_TARGET_SPEC
121# or REQUESTED_TARGET_SPEC (TARGET_SPEC)
122DIRDEPS = \
123	${ptdeps:@d@$d.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC:U${REQUESTED_MACHINE}}}@} \
124	${mqtdeps:M*.${REQUESTED_MACHINE}} \
125	${tqtdeps:M*.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC}}}
126.endif
127# clean up
128DIRDEPS := ${DIRDEPS:O:u}
129
130.if !empty(DEBUG_DIRDEPS_TARGETS)
131.for x in tdeps ptdeps mqtdeps tqtdeps DIRDEPS
132.info $x=${$x}
133.endfor
134.endif
135.endif
136# if we got DIRDEPS get to work
137.if !empty(DIRDEPS)
138DIRDEPS.dirs := ${DIRDEPS:S,^,${SRCTOP}/,:@d@${exists($d):?$d:${d:R}}@}
139# some targets want to tweak options we might want to process now
140.for m in ${DIRDEPS.dirs:S,$,/Makefile.dirdeps.options,}
141.-include <$m>
142.endfor
143.if defined(MK_STATIC_DIRDEPS_CACHE)
144# some targets are very expensive to compute dirdeps for
145# so we may have a static cache
146.for c in ${DIRDEPS.dirs:S,$,/Makefile.dirdeps.cache,}
147.if exists($c)
148STATIC_DIRDEPS_CACHE ?= $c
149.if ${MK_STATIC_DIRDEPS_CACHE} == "yes"
150DIRDEPS_CACHE ?= $c
151MK_DIRDEPS_CACHE = yes
152.endif
153.endif
154.endfor
155.if defined(STATIC_DIRDEPS_CACHE)
156.export STATIC_DIRDEPS_CACHE
157.endif
158.endif
159
160# allow a top-level makefile to do other stuff
161# before including dirdeps.mk
162.if ${MK_DIRDEPS_TARGETS_INCLUDE_DIRDEPS:Uyes} == "yes"
163.include <dirdeps.mk>
164.endif
165
166DIRDEPS_TARGETS_SKIP += all clean* destroy*
167
168.for t in ${.TARGETS:${DIRDEPS_TARGETS_SKIP:${M_ListToSkip}}}
169$t: dirdeps
170.endfor
171.endif
172.endif
173