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, version 3 of the License ONLY.
5 # This program is distributed in the hope that it will be useful,
6 # but WITHOUT ANY WARRANTY; without even the implied warranty of
7 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 # GNU General Public License for more details.
10 # You should have received a copy of the GNU General Public License
11 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # FSubDirPath TOP d1 ... ;
16 # Returns path to named directory.
18 # If jam is invoked in a subdirectory of the TOP, then we
19 # need to prepend a ../ for every level we must climb up
20 # (TOP-UP), and then append the directory names we must
21 # climb down (TOP-DOWN), plus the named directories d1 ...
22 # If TOP was set externally, or computed from another TOP
23 # that was, we'll have to reroot the whole thing at TOP-ROOT.
24 local _r = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ;
25 return $(_r:R=$($(<[1])-ROOT)) ;
31 # SubDir TOP d1 d2 ... ;
33 # Support for a project tree spanning multiple directories.
35 # SubDir declares a Jamfile's location in a project tree, setting
36 # Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
39 # TOP is a user-select variable name for root of the tree, and
40 # d1 d2 ... are the directory elements that lead from the root
41 # of the tree to the directory of the Jamfile.
43 # TOP can be set externally, but normally the first SubDir call
44 # computes TOP as the path up from the current directory; the
45 # path contains one ../ for each of d1 d2 ...
47 # SubDir reads once the project-specific rules file Jamrules
48 # in the TOP directory, if present. This can be overridden
49 # with the variable TOPRULES.
51 # SubDir supports multiple, overlaid project trees: SubDir
52 # invocations with different TOPs can appear in the same Jamfile.
53 # The location established by the first SubDir call is used set
54 # the TOPs for the subsequent SubDir calls.
56 # SubDir's public variables:
58 # $(TOP) = path from CWD to root.
59 # $(SUBDIR) = path from CWD to the directory SubDir names.
60 # $(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
61 # $(SEARCH_SOURCE) = $(SUBDIR)
62 # ###$(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
63 # $(LOCATE_SOURCE) = $(SUBDIR)
64 # $(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
65 # $(LOCATE_BIN) = $(ALL_LOCATE_BIN) $(ALL_LOCATE_TARGET) $(SUBDIR)
66 # $(LOCATE_LIB) = $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
67 # $(LOCATE_LIBSO) = $(ALL_LOCATE_LIBSO) $(ALL_LOCATE_LIB) $(ALL_LOCATE_TARGET) $(SUBDIR)
68 # $(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s
70 local _top = $(<[1]) ;
71 local _tokens = $(<[2-]) ;
72 local _xpath = $(_tokens:J=$(PATH_SEPARATOR)) ;
77 # First time through sets up relative root and includes Jamrules.
78 if ! $(_top) { Exit 'SubDir syntax error' ; }
82 # First time we've seen this TOP.
83 # We'll initialize a number of internal variables:
85 # $(TOP-UP) = directories from ROOT to a common point
86 # $(TOP-DOWN) = directories from common point to TOP
87 # $(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
88 # $(SUBDIR_UP) = current value of $(TOP-UP)
89 # $(SUBDIR_DOWN) = current value of $(TOP-DOWN)
90 # $(SUBDIR_ROOT) = current value of $(TOP-ROOT)
94 # We'll ignore the relative (UP/DOWN) path that
95 # got us here, and instead remember the hard ROOT.
98 $(_top)-ROOT = $($(_top)) ;
102 # Establishing a new TOP. In the simplest case,
103 # (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
104 # merely a certain number of directories down from
105 # the current directory, and FSubDirPath will set
106 # TOP to a path consisting of ../ for each of the
107 # elements of _tokens, because that represents how
108 # far below TOP the current directory sits.
110 # In the more complicated case, the starting directory
111 # isn't the directory of jam's invocation but an
112 # location established by previous SubDir call. The
113 # starting directory is SUBDIR_UP directories up from
114 # SUBDIR_ROOT, and then SUBDIR_DOWN directories down
115 # from that. If SUBDIR_ROOT is not set, that means
116 # SUBDIR_DOWN and SUBDIR_UP represent the path from
117 # the directory of jam's invocation.
119 # In the most complicated case, the _tokens also
120 # represents directories down, because TOP is being
121 # estalished in a directory other than TOP's root.
122 # Hopefully, _tokens and SUBDIR_DOWN represent the
123 # same final directory, relative to the new TOP and
124 # the previous SubDIr's TOP. To find the new TOP,
125 # we have to chop off any common directories from
126 # then ends of _tokens and SUBDIR_DOWN. To do so,
127 # we reverse each of them, call FStripCommon to
128 # remove the initial common elements, and then
129 # reverse them again. After this process, if
130 # both _tokens and SUBDIR_DOWN have elements, it
131 # means the directory names estalished by the two
132 # SubDir calls don't match, and a warning is issued.
133 # All hell will likely break loose at this point,
134 # since the whole SubDir scheme relies on the SubDir
135 # calls accurately naming the current directory.
137 # Strip common trailing elements of _tokens and SUBDIR_DOWN.
138 _tokens = [ ListReverse $(_tokens) ] ;
139 SUBDIR_DOWN = [ ListReverse $(SUBDIR_DOWN) ] ;
140 FStripCommon _tokens : SUBDIR_DOWN ;
141 SUBDIR_DOWN = [ ListReverse $(SUBDIR_DOWN) ] ;
142 _tokens = [ ListReverse $(_tokens) ] ;
144 if $(SUBDIR_DOWN) && $(_tokens) { Echo 'Warning:' SubDir $(<) 'misplaced!' ; }
146 # We'll remember the relative (UP/DOWN) path that
147 # got us here, plus any hard ROOT starting point
148 # for the UP/DOWN. If TOP is never set externally,
149 # ROOT will always be "" (directory of jam's invocation).
150 $(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
151 $(_top)-DOWN = $(SUBDIR_DOWN) ;
152 $(_top)-ROOT = $(SUBDIR_ROOT:E="") ;
153 $(_top) = [ FSubDirPath $(_top) ] ;
156 # Set subdir vars for the inclusion of the Jamrules,
157 # just in case they have SubDir rules of their own.
158 # Note that SUBDIR_DOWN is empty: it's all the way
159 # up where the Jamrules live. These gets overrided
160 # just after the inclusion.
161 SUBDIR_UP = $($(_top)-UP) ;
163 SUBDIR_ROOT = $($(_top)-ROOT) ;
165 # Include $(TOPRULES) or $(TOP)/Jamrules.
166 # Include $(TOPRULES) if set.
167 # Otherwise include $(TOP)/Jamrules if present.
169 softinclude $($(_top)RULES) ;
171 NoCare $(JAMRULES:R=$($(_top)):G=$(_top)) ;
172 softinclude $(JAMRULES:R=$($(_top)):G=$(_top)) ;
175 # soft-include "Jamrules.configure"
176 softinclude $($(_top))/Jamrules.configure ;
179 # Get path from $(TOP) to named directory.
180 # Save dir tokens for other potential uses.
181 SUBDIR_UP = $($(_top)-UP) ;
182 SUBDIR_DOWN = $($(_top)-DOWN) $(_tokens) ;
183 SUBDIR_ROOT = $($(_top)-ROOT) ;
184 SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
186 SUBDIR = [ FSubDirPath $(<) ] ;
188 # Now set up SEARCH_SOURCE, LOCATE_TARGET, LOCATE_BIN, SOURCE_GRIST
189 # These can be reset if needed. For example, if the source
190 # directory should not hold object files, LOCATE_TARGET can
191 # subsequently be redefined.
192 SEARCH_SOURCE = $(SUBDIR) ;
194 #if $(SUBDIR) = '.' { sdr = "" ; } else { sdr = "$(PATH_SEPARATOR)$(SUBDIR)" ; }
196 if $(ALL_LOCATE_TARGET) {
197 if ! ( $(_xpath) ~= '^/' ) { _xpath = "$(PATH_SEPARATOR[1])$(_xpath)" ; }
198 LOCATE_TARGET = "$(ALL_LOCATE_TARGET[1])$(_xpath)" ;
199 #LOCATE_SOURCE = "$(ALL_LOCATE_TARGET)$(_xpath)" ;
200 LOCATE_SOURCE = $(SUBDIR) ;
202 LOCATE_TARGET = $(SUBDIR) ;
203 LOCATE_SOURCE = $(SUBDIR) ;
206 if $(ALL_LOCATE_BIN) {
207 LOCATE_BIN = $(ALL_LOCATE_BIN) ;
209 LOCATE_BIN = $(LOCATE_TARGET) ;
212 if $(ALL_LOCATE_LIB) {
213 LOCATE_LIB = $(ALL_LOCATE_LIB) ;
215 LOCATE_LIB = $(LOCATE_TARGET) ;
218 if $(ALL_LOCATE_LIBSO) {
219 LOCATE_LIBSO = $(ALL_LOCATE_LIBSO) ;
221 LOCATE_LIBSO = $(LOCATE_LIB) ;
224 #Echo "ALL_LOCATE_LIB = $(ALL_LOCATE_LIB)" ;
225 #Echo "LOCATE_LIB = $(LOCATE_LIB)" ;
227 SOURCE_GRIST = [ FGrist $(SUBDIR_TOKENS) ] ;
228 #if ! $(LOCATE_BIN) { LOCATE_BIN = $(LOCATE_TARGET) ; }
230 ## OPT_HEADER_CACHE_EXT
231 # With the header cache, we can grist all files found
232 # during a header scan without incurring a performance
235 HDRGRIST = $(SOURCE_GRIST) ;
237 # Reset per-directory ccflags, hdrs, etc,
238 # listed in SUBDIRRESET.
239 # Note use of variable expanded assignment var
240 SUBDIR$(SUBDIRRESET) = ;
242 # Invoke user-specific SubDir extensions,
243 # rule names listed in SUBDIRRULES.
244 # Note use of variable expanded rule invocation
245 $(SUBDIRRULES) $(<) ;
249 #rule SubDirDcFlags {
250 # SUBDIRDCFLAGS += $(<) ;
255 SUBDIRCCFLAGS += $(<) ;
259 rule SubDirC++Flags {
260 SUBDIRC++FLAGS += $(<) ;
264 rule SubDirObjCFlags {
265 SUBDIROBJCFLAGS += $(<) ;
270 SUBDIRHDRS += [ FDirName $(<) ] ;
275 SUBDIRDEFINES += $(<) ;
279 rule SubIncludeMany {
280 # SubIncludeMany TOP d1 ... ;
282 # Include a subdirectory's Jamfile.
284 # We use SubDir to get there, in case the included Jamfile
285 # either doesn't have its own SubDir (naughty) or is a subtree
287 #Echo 'including ' $(<) ':' $(>) ;
289 if ! $($(<[1])) { Exit 'SubIncludeMany' $(<[1]) 'without prior SubDir' $(<[1]) ; }
291 include $(JAMFILE:D=$(SUBDIR)) ;
295 rule SubIncludeOnce {
296 # SubIncludeOnce varname : TOP d1 ... ;
298 # Include a subdirectory's Jamfile.
300 local _vn = $(<[1]) ;
302 #Echo "processing $(_vn)" ;
305 SubIncludeMany $(>) ;
307 # Echo "skiped $(_vn) -- $($(_vn))" ;
314 # SubInclude TOP d1 ... ;
316 # Include a subdirectory's Jamfile.
317 if ! $($(<[1])) { Exit 'SubInclude' $(<[1]) 'without prior SubDir' $(<[1]) ; }
318 local _sbiguard = _K8JAM_SUB_GUARD_$(<:J=_) ;
319 SubIncludeOnce $(_sbiguard) : $(<) ;
324 # SubRules TOP d1 ... : Other-TOP ;
326 # Read another tree's Jamrules, by giving it's path according
327 # to this tree and it's own name.
328 if ! $($(<[1])) { Exit 'SubRules' $(<[1]) 'without prior SubDir' $(<[1]) ; }
334 # /MakeLocate targets : directory
336 # Creates _dir_ and causes _target_ to be built into _dir_
338 # This is done by setting the target-specific variable LOCATE
339 # on _targets_, and arranges with @MkDir to create the target
343 # Note we grist the directory name with 'dir',
344 # so that directory path components and other
345 # targets don't conflict.
346 local srcname = $(<[1]:G=) ;
347 local srcdir = $(srcname:D) ;
348 local outdir = $(>[1]:G=dir) ;
351 odir = $(outdir)$(PATH_SEPARATOR)$(srcdir) ;
355 #Echo 'MakeLocate:' "$(<)" '|' "$(>)" ;
356 #Echo 'srcname:' "$(srcname)" ;
357 #Echo 'srcdir :' "$(srcdir)" ;
358 #Echo 'outdir :' "$(outdir)" ;
359 #Echo 'odir :' "$(odir)" ;
361 LOCATE on $(<) = $(>) ;
362 Depends $(<) : $(odir) ;