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-]) ] ;
27 return $(_r:R=$($(<[1])-ROOT)) ;
33 # SubDir TOP d1 d2 ... ;
35 # Support for a project tree spanning multiple directories.
37 # SubDir declares a Jamfile's location in a project tree, setting
38 # Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
41 # TOP is a user-select variable name for root of the tree, and
42 # d1 d2 ... are the directory elements that lead from the root
43 # of the tree to the directory of the Jamfile.
45 # TOP can be set externally, but normally the first SubDir call
46 # computes TOP as the path up from the current directory; the
47 # path contains one ../ for each of d1 d2 ...
49 # SubDir reads once the project-specific rules file Jamrules
50 # in the TOP directory, if present. This can be overridden
51 # with the variable TOPRULES.
53 # SubDir supports multiple, overlaid project trees: SubDir
54 # invocations with different TOPs can appear in the same Jamfile.
55 # The location established by the first SubDir call is used set
56 # the TOPs for the subsequent SubDir calls.
58 # SubDir's public variables:
60 # $(TOP) = path from CWD to root.
61 # $(SUBDIR) = path from CWD to the directory SubDir names.
62 # $(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
63 # $(SEARCH_SOURCE) = $(SUBDIR)
64 # ###$(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
65 # $(LOCATE_SOURCE) = $(SUBDIR)
66 # $(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
67 # $(LOCATE_BIN) = $(ALL_LOCATE_BIN) $(ALL_LOCATE_TARGET) $(SUBDIR)
68 # $(LOCATE_LIB) = $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
69 # $(LOCATE_LIBSO) = $(ALL_LOCATE_LIBSO) $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
70 # $(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s
72 local _top = $(<[1]) ;
73 local _tokens = $(<[2-]) ;
74 local _xpath = $(_tokens:J=$(PATH_SEPARATOR)) ;
78 if $(_xpath) != "" { _xpath = "$(PATH_SEPARATOR)$(_xpath)" ; }
82 # First time through sets up relative root and includes Jamrules.
83 if ! $(_top) { Exit 'SubDir syntax error' ; }
87 # First time we've seen this TOP.
88 # We'll initialize a number of internal variables:
90 # $(TOP-UP) = directories from ROOT to a common point
91 # $(TOP-DOWN) = directories from common point to TOP
92 # $(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
93 # $(SUBDIR_UP) = current value of $(TOP-UP)
94 # $(SUBDIR_DOWN) = current value of $(TOP-DOWN)
95 # $(SUBDIR_ROOT) = current value of $(TOP-ROOT)
99 # We'll ignore the relative (UP/DOWN) path that
100 # got us here, and instead remember the hard ROOT.
103 $(_top)-ROOT = $($(_top)) ;
107 # Establishing a new TOP. In the simplest case,
108 # (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
109 # merely a certain number of directories down from
110 # the current directory, and FSubDirPath will set
111 # TOP to a path consisting of ../ for each of the
112 # elements of _tokens, because that represents how
113 # far below TOP the current directory sits.
115 # In the more complicated case, the starting directory
116 # isn't the directory of jam's invocation but an
117 # location established by previous SubDir call. The
118 # starting directory is SUBDIR_UP directories up from
119 # SUBDIR_ROOT, and then SUBDIR_DOWN directories down
120 # from that. If SUBDIR_ROOT is not set, that means
121 # SUBDIR_DOWN and SUBDIR_UP represent the path from
122 # the directory of jam's invocation.
124 # In the most complicated case, the _tokens also
125 # represents directories down, because TOP is being
126 # estalished in a directory other than TOP's root.
127 # Hopefully, _tokens and SUBDIR_DOWN represent the
128 # same final directory, relative to the new TOP and
129 # the previous SubDIr's TOP. To find the new TOP,
130 # we have to chop off any common directories from
131 # then ends of _tokens and SUBDIR_DOWN. To do so,
132 # we reverse each of them, call FStripCommon to
133 # remove the initial common elements, and then
134 # reverse them again. After this process, if
135 # both _tokens and SUBDIR_DOWN have elements, it
136 # means the directory names estalished by the two
137 # SubDir calls don't match, and a warning is issued.
138 # All hell will likely break loose at this point,
139 # since the whole SubDir scheme relies on the SubDir
140 # calls accurately naming the current directory.
142 # Strip common trailing elements of _tokens and SUBDIR_DOWN.
143 _tokens = [ ListReverse $(_tokens) ] ;
144 SUBDIR_DOWN = [ ListReverse $(SUBDIR_DOWN) ] ;
145 FStripCommon _tokens : SUBDIR_DOWN ;
146 SUBDIR_DOWN = [ ListReverse $(SUBDIR_DOWN) ] ;
147 _tokens = [ ListReverse $(_tokens) ] ;
149 if $(SUBDIR_DOWN) && $(_tokens) { Echo 'Warning:' SubDir $(<) 'misplaced!' ; }
151 # We'll remember the relative (UP/DOWN) path that
152 # got us here, plus any hard ROOT starting point
153 # for the UP/DOWN. If TOP is never set externally,
154 # ROOT will always be "" (directory of jam's invocation).
155 $(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
156 $(_top)-DOWN = $(SUBDIR_DOWN) ;
157 $(_top)-ROOT = $(SUBDIR_ROOT:E="") ;
158 $(_top) = [ FSubDirPath $(_top) ] ;
161 # Set subdir vars for the inclusion of the Jamrules,
162 # just in case they have SubDir rules of their own.
163 # Note that SUBDIR_DOWN is empty: it's all the way
164 # up where the Jamrules live. These gets overrided
165 # just after the inclusion.
166 SUBDIR_UP = $($(_top)-UP) ;
168 SUBDIR_ROOT = $($(_top)-ROOT) ;
170 # Include $(TOPRULES) or $(TOP)/Jamrules.
171 # Include $(TOPRULES) if set.
172 # Otherwise include $(TOP)/Jamrules if present.
174 softinclude $($(_top)RULES) ;
176 NoCare $(JAMRULES:R=$($(_top)):G=$(_top)) ;
177 softinclude $(JAMRULES:R=$($(_top)):G=$(_top)) ;
181 # Get path from $(TOP) to named directory.
182 # Save dir tokens for other potential uses.
183 SUBDIR_UP = $($(_top)-UP) ;
184 SUBDIR_DOWN = $($(_top)-DOWN) $(_tokens) ;
185 SUBDIR_ROOT = $($(_top)-ROOT) ;
186 SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
188 SUBDIR = [ FSubDirPath $(<) ] ;
190 # Now set up SEARCH_SOURCE, LOCATE_TARGET, LOCATE_BIN, SOURCE_GRIST
191 # These can be reset if needed. For example, if the source
192 # directory should not hold object files, LOCATE_TARGET can
193 # subsequently be redefined.
194 SEARCH_SOURCE = $(SUBDIR) ;
196 #if $(SUBDIR) = '.' { sdr = "" ; } else { sdr = "$(PATH_SEPARATOR)$(SUBDIR)" ; }
198 if $(ALL_LOCATE_TARGET) {
199 LOCATE_TARGET = "$(ALL_LOCATE_TARGET)$(_xpath)" ;
200 #LOCATE_SOURCE = "$(ALL_LOCATE_TARGET)$(_xpath)" ;
201 LOCATE_SOURCE = "$(SUBDIR)" ;
203 LOCATE_TARGET = $(SUBDIR) ;
204 LOCATE_SOURCE = $(SUBDIR) ;
207 if $(ALL_LOCATE_BIN) {
208 LOCATE_BIN = $(ALL_LOCATE_BIN) ;
210 LOCATE_BIN = $(LOCATE_TARGET) ;
213 if $(ALL_LOCATE_LIB) {
214 LOCATE_LIB = $(ALL_LOCATE_LIB) ;
216 LOCATE_LIB = $(LOCATE_TARGET) ;
219 if $(ALL_LOCATE_LIBSO) {
220 LOCATE_LIBSO = $(ALL_LOCATE_LIBSO) ;
222 LOCATE_LIBSO = $(LOCATE_LIB) ;
225 #Echo "ALL_LOCATE_LIB = $(ALL_LOCATE_LIB)" ;
226 #Echo "LOCATE_LIB = $(LOCATE_LIB)" ;
228 SOURCE_GRIST = [ FGrist $(SUBDIR_TOKENS) ] ;
229 #if ! $(LOCATE_BIN) { LOCATE_BIN = $(LOCATE_TARGET) ; }
231 ## OPT_HEADER_CACHE_EXT
232 # With the header cache, we can grist all files found
233 # during a header scan without incurring a performance
236 HDRGRIST = $(SOURCE_GRIST) ;
238 # Reset per-directory ccflags, hdrs, etc,
239 # listed in SUBDIRRESET.
240 # Note use of variable expanded assignment var
241 SUBDIR$(SUBDIRRESET) = ;
243 # Invoke user-specific SubDir extensions,
244 # rule names listed in SUBDIRRULES.
245 # Note use of variable expanded rule invocation
246 $(SUBDIRRULES) $(<) ;
250 #rule SubDirDcFlags {
251 # SUBDIRDCFLAGS += $(<) ;
256 SUBDIRCCFLAGS += $(<) ;
260 rule SubDirC++Flags {
261 SUBDIRC++FLAGS += $(<) ;
265 rule SubDirObjCFlags {
266 SUBDIROBJCFLAGS += $(<) ;
271 SUBDIRHDRS += [ FDirName $(<) ] ;
276 SUBDIRDEFINES += $(<) ;
280 rule SubIncludeMany {
281 # SubIncludeMany TOP d1 ... ;
283 # Include a subdirectory's Jamfile.
285 # We use SubDir to get there, in case the included Jamfile
286 # either doesn't have its own SubDir (naughty) or is a subtree
288 #Echo 'including ' $(<) ':' $(>) ;
290 if ! $($(<[1])) { Exit 'SubIncludeMany' $(<[1]) 'without prior SubDir' $(<[1]) ; }
292 include $(JAMFILE:D=$(SUBDIR)) ;
296 rule SubIncludeOnce {
297 # SubIncludeOnce varname : TOP d1 ... ;
299 # Include a subdirectory's Jamfile.
301 local _vn = $(<[1]) ;
303 #Echo "processing $(_vn)" ;
306 SubIncludeMany $(>) ;
308 # Echo "skiped $(_vn) -- $($(_vn))" ;
315 # SubInclude TOP d1 ... ;
317 # Include a subdirectory's Jamfile.
318 if ! $($(<[1])) { Exit 'SubInclude' $(<[1]) 'without prior SubDir' $(<[1]) ; }
319 local _sbiguard = _K8JAM_SUB_GUARD_$(<:J=_) ;
320 SubIncludeOnce $(_sbiguard) : $(<) ;
325 # SubRules TOP d1 ... : Other-TOP ;
327 # Read another tree's Jamrules, by giving it's path according
328 # to this tree and it's own name.
329 if ! $($(<[1])) { Exit 'SubRules' $(<[1]) 'without prior SubDir' $(<[1]) ; }
335 # /MakeLocate targets : directory
337 # Creates _dir_ and causes _target_ to be built into _dir_
339 # This is done by setting the target-specific variable LOCATE
340 # on _targets_, and arranges with @MkDir to create the target
344 # Note we grist the directory name with 'dir',
345 # so that directory path components and other
346 # targets don't conflict.
347 local srcname = $(<[1]:G=) ;
348 local srcdir = $(srcname:D) ;
349 local outdir = $(>[1]:G=dir) ;
352 odir = $(outdir)$(PATH_SEPARATOR)$(srcdir) ;
356 #Echo 'MakeLocate:' "$(<)" '|' "$(>)" ;
357 #Echo 'srcname:' "$(srcname)" ;
358 #Echo 'srcdir :' "$(srcdir)" ;
359 #Echo 'outdir :' "$(outdir)" ;
360 #Echo 'odir :' "$(odir)" ;
362 LOCATE on $(<) = $(>) ;
363 Depends $(<) : $(odir) ;