1 # This program is free software: you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation, either version 3 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # FSubDirPath TOP d1 ... ;
17 # Returns path to named directory.
19 # If jam is invoked in a subdirectory of the TOP, then we
20 # need to prepend a ../ for every level we must climb up
21 # (TOP-UP), and then append the directory names we must
22 # climb down (TOP-DOWN), plus the named directories d1 ...
23 # If TOP was set externally, or computed from another TOP
24 # that was, we'll have to reroot the whole thing at TOP-ROOT.
25 local _r = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ;
26 return $(_r:R=$($(<[1])-ROOT)) ;
32 # SubDir TOP d1 d2 ... ;
34 # Support for a project tree spanning multiple directories.
36 # SubDir declares a Jamfile's location in a project tree, setting
37 # Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
40 # TOP is a user-select variable name for root of the tree, and
41 # d1 d2 ... are the directory elements that lead from the root
42 # of the tree to the directory of the Jamfile.
44 # TOP can be set externally, but normally the first SubDir call
45 # computes TOP as the path up from the current directory; the
46 # path contains one ../ for each of d1 d2 ...
48 # SubDir reads once the project-specific rules file Jamrules
49 # in the TOP directory, if present. This can be overridden
50 # with the variable TOPRULES.
52 # SubDir supports multiple, overlaid project trees: SubDir
53 # invocations with different TOPs can appear in the same Jamfile.
54 # The location established by the first SubDir call is used set
55 # the TOPs for the subsequent SubDir calls.
57 # SubDir's public variables:
59 # $(TOP) = path from CWD to root.
60 # $(SUBDIR) = path from CWD to the directory SubDir names.
61 # $(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
62 # $(SEARCH_SOURCE) = $(SUBDIR)
63 # ###$(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
64 # $(LOCATE_SOURCE) = $(SUBDIR)
65 # $(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
66 # $(LOCATE_BIN) = $(ALL_LOCATE_BIN) $(ALL_LOCATE_TARGET) $(SUBDIR)
67 # $(LOCATE_LIB) = $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
68 # $(LOCATE_LIBSO) = $(ALL_LOCATE_LIBSO) $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
69 # $(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s
71 local _top = $(<[1]) ;
72 local _tokens = $(<[2-]) ;
73 local _xpath = $(_tokens:J=$(PATH_SEPARATOR)) ;
78 # First time through sets up relative root and includes Jamrules.
79 if ! $(_top) { Exit 'SubDir syntax error' ; }
83 # First time we've seen this TOP.
84 # We'll initialize a number of internal variables:
86 # $(TOP-UP) = directories from ROOT to a common point
87 # $(TOP-DOWN) = directories from common point to TOP
88 # $(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
89 # $(SUBDIR_UP) = current value of $(TOP-UP)
90 # $(SUBDIR_DOWN) = current value of $(TOP-DOWN)
91 # $(SUBDIR_ROOT) = current value of $(TOP-ROOT)
95 # We'll ignore the relative (UP/DOWN) path that
96 # got us here, and instead remember the hard ROOT.
99 $(_top)-ROOT = $($(_top)) ;
103 # Establishing a new TOP. In the simplest case,
104 # (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
105 # merely a certain number of directories down from
106 # the current directory, and FSubDirPath will set
107 # TOP to a path consisting of ../ for each of the
108 # elements of _tokens, because that represents how
109 # far below TOP the current directory sits.
111 # In the more complicated case, the starting directory
112 # isn't the directory of jam's invocation but an
113 # location established by previous SubDir call. The
114 # starting directory is SUBDIR_UP directories up from
115 # SUBDIR_ROOT, and then SUBDIR_DOWN directories down
116 # from that. If SUBDIR_ROOT is not set, that means
117 # SUBDIR_DOWN and SUBDIR_UP represent the path from
118 # the directory of jam's invocation.
120 # In the most complicated case, the _tokens also
121 # represents directories down, because TOP is being
122 # estalished in a directory other than TOP's root.
123 # Hopefully, _tokens and SUBDIR_DOWN represent the
124 # same final directory, relative to the new TOP and
125 # the previous SubDIr's TOP. To find the new TOP,
126 # we have to chop off any common directories from
127 # then ends of _tokens and SUBDIR_DOWN. To do so,
128 # we reverse each of them, call FStripCommon to
129 # remove the initial common elements, and then
130 # reverse them again. After this process, if
131 # both _tokens and SUBDIR_DOWN have elements, it
132 # means the directory names estalished by the two
133 # SubDir calls don't match, and a warning is issued.
134 # All hell will likely break loose at this point,
135 # since the whole SubDir scheme relies on the SubDir
136 # calls accurately naming the current directory.
138 # Strip common trailing elements of _tokens and SUBDIR_DOWN.
139 _tokens = [ ListReverse $(_tokens) ] ;
140 SUBDIR_DOWN = [ ListReverse $(SUBDIR_DOWN) ] ;
141 FStripCommon _tokens : SUBDIR_DOWN ;
142 SUBDIR_DOWN = [ ListReverse $(SUBDIR_DOWN) ] ;
143 _tokens = [ ListReverse $(_tokens) ] ;
145 if $(SUBDIR_DOWN) && $(_tokens) { Echo 'Warning:' SubDir $(<) 'misplaced!' ; }
147 # We'll remember the relative (UP/DOWN) path that
148 # got us here, plus any hard ROOT starting point
149 # for the UP/DOWN. If TOP is never set externally,
150 # ROOT will always be "" (directory of jam's invocation).
151 $(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
152 $(_top)-DOWN = $(SUBDIR_DOWN) ;
153 $(_top)-ROOT = $(SUBDIR_ROOT:E="") ;
154 $(_top) = [ FSubDirPath $(_top) ] ;
157 # Set subdir vars for the inclusion of the Jamrules,
158 # just in case they have SubDir rules of their own.
159 # Note that SUBDIR_DOWN is empty: it's all the way
160 # up where the Jamrules live. These gets overrided
161 # just after the inclusion.
162 SUBDIR_UP = $($(_top)-UP) ;
164 SUBDIR_ROOT = $($(_top)-ROOT) ;
166 # Include $(TOPRULES) or $(TOP)/Jamrules.
167 # Include $(TOPRULES) if set.
168 # Otherwise include $(TOP)/Jamrules if present.
170 softinclude $($(_top)RULES) ;
172 NoCare $(JAMRULES:R=$($(_top)):G=$(_top)) ;
173 softinclude $(JAMRULES:R=$($(_top)):G=$(_top)) ;
177 # Get path from $(TOP) to named directory.
178 # Save dir tokens for other potential uses.
179 SUBDIR_UP = $($(_top)-UP) ;
180 SUBDIR_DOWN = $($(_top)-DOWN) $(_tokens) ;
181 SUBDIR_ROOT = $($(_top)-ROOT) ;
182 SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
184 SUBDIR = [ FSubDirPath $(<) ] ;
186 # Now set up SEARCH_SOURCE, LOCATE_TARGET, LOCATE_BIN, SOURCE_GRIST
187 # These can be reset if needed. For example, if the source
188 # directory should not hold object files, LOCATE_TARGET can
189 # subsequently be redefined.
190 SEARCH_SOURCE = $(SUBDIR) ;
192 #if $(SUBDIR) = '.' { sdr = "" ; } else { sdr = "$(PATH_SEPARATOR)$(SUBDIR)" ; }
194 if $(ALL_LOCATE_TARGET) {
195 if ! ( $(_xpath) ~= '^/' ) { _xpath = "$(PATH_SEPARATOR[1])$(_xpath)" ; }
196 LOCATE_TARGET = "$(ALL_LOCATE_TARGET[1])$(_xpath)" ;
197 #LOCATE_SOURCE = "$(ALL_LOCATE_TARGET)$(_xpath)" ;
198 LOCATE_SOURCE = $(SUBDIR) ;
200 LOCATE_TARGET = $(SUBDIR) ;
201 LOCATE_SOURCE = $(SUBDIR) ;
204 if $(ALL_LOCATE_BIN) {
205 LOCATE_BIN = $(ALL_LOCATE_BIN) ;
207 LOCATE_BIN = $(LOCATE_TARGET) ;
210 if $(ALL_LOCATE_LIB) {
211 LOCATE_LIB = $(ALL_LOCATE_LIB) ;
213 LOCATE_LIB = $(LOCATE_TARGET) ;
216 if $(ALL_LOCATE_LIBSO) {
217 LOCATE_LIBSO = $(ALL_LOCATE_LIBSO) ;
219 LOCATE_LIBSO = $(LOCATE_LIB) ;
222 #Echo "ALL_LOCATE_LIB = $(ALL_LOCATE_LIB)" ;
223 #Echo "LOCATE_LIB = $(LOCATE_LIB)" ;
225 SOURCE_GRIST = [ FGrist $(SUBDIR_TOKENS) ] ;
226 #if ! $(LOCATE_BIN) { LOCATE_BIN = $(LOCATE_TARGET) ; }
228 ## OPT_HEADER_CACHE_EXT
229 # With the header cache, we can grist all files found
230 # during a header scan without incurring a performance
233 HDRGRIST = $(SOURCE_GRIST) ;
235 # Reset per-directory ccflags, hdrs, etc,
236 # listed in SUBDIRRESET.
237 # Note use of variable expanded assignment var
238 SUBDIR$(SUBDIRRESET) = ;
240 # Invoke user-specific SubDir extensions,
241 # rule names listed in SUBDIRRULES.
242 # Note use of variable expanded rule invocation
243 $(SUBDIRRULES) $(<) ;
247 #rule SubDirDcFlags {
248 # SUBDIRDCFLAGS += $(<) ;
253 SUBDIRCCFLAGS += $(<) ;
257 rule SubDirC++Flags {
258 SUBDIRC++FLAGS += $(<) ;
262 rule SubDirObjCFlags {
263 SUBDIROBJCFLAGS += $(<) ;
268 SUBDIRHDRS += [ FDirName $(<) ] ;
273 SUBDIRDEFINES += $(<) ;
277 rule SubIncludeMany {
278 # SubIncludeMany TOP d1 ... ;
280 # Include a subdirectory's Jamfile.
282 # We use SubDir to get there, in case the included Jamfile
283 # either doesn't have its own SubDir (naughty) or is a subtree
285 #Echo 'including ' $(<) ':' $(>) ;
287 if ! $($(<[1])) { Exit 'SubIncludeMany' $(<[1]) 'without prior SubDir' $(<[1]) ; }
289 include $(JAMFILE:D=$(SUBDIR)) ;
293 rule SubIncludeOnce {
294 # SubIncludeOnce varname : TOP d1 ... ;
296 # Include a subdirectory's Jamfile.
298 local _vn = $(<[1]) ;
300 #Echo "processing $(_vn)" ;
303 SubIncludeMany $(>) ;
305 # Echo "skiped $(_vn) -- $($(_vn))" ;
312 # SubInclude TOP d1 ... ;
314 # Include a subdirectory's Jamfile.
315 if ! $($(<[1])) { Exit 'SubInclude' $(<[1]) 'without prior SubDir' $(<[1]) ; }
316 local _sbiguard = _K8JAM_SUB_GUARD_$(<:J=_) ;
317 SubIncludeOnce $(_sbiguard) : $(<) ;
322 # SubRules TOP d1 ... : Other-TOP ;
324 # Read another tree's Jamrules, by giving it's path according
325 # to this tree and it's own name.
326 if ! $($(<[1])) { Exit 'SubRules' $(<[1]) 'without prior SubDir' $(<[1]) ; }
332 # /MakeLocate targets : directory
334 # Creates _dir_ and causes _target_ to be built into _dir_
336 # This is done by setting the target-specific variable LOCATE
337 # on _targets_, and arranges with @MkDir to create the target
341 # Note we grist the directory name with 'dir',
342 # so that directory path components and other
343 # targets don't conflict.
344 local srcname = $(<[1]:G=) ;
345 local srcdir = $(srcname:D) ;
346 local outdir = $(>[1]:G=dir) ;
349 odir = $(outdir)$(PATH_SEPARATOR)$(srcdir) ;
353 #Echo 'MakeLocate:' "$(<)" '|' "$(>)" ;
354 #Echo 'srcname:' "$(srcname)" ;
355 #Echo 'srcdir :' "$(srcdir)" ;
356 #Echo 'outdir :' "$(outdir)" ;
357 #Echo 'odir :' "$(odir)" ;
359 LOCATE on $(<) = $(>) ;
360 Depends $(<) : $(odir) ;