added jam build system, please try it out - the advantage would be that it already...
[supertux.git] / mk / jam / jamcompatibility.jam
1 #============================================================================
2 # Several hacks to make the build compatible with certain old/broken jam
3 # versions
4 #============================================================================
5
6 # boostjam is evil: It is compatible to jam 2.4 but has a version number 3.1, we# try to detect boostjam with the ARGV extension
7 if $(ARGV[0])
8 {
9 # boostjam hacks
10   JAMVERSION = 2.4 ;
11   rule FIncludes
12   {
13     return -I$(<) ;
14   }
15   rule FDefines
16   {
17     return -D$(<) ;
18   }
19 }
20
21 if $(JAMVERSION) < 2.4
22 {
23     EXIT "Error: This buildsystem requires jam version 2.4 or later." ;
24 }
25 # don't confuse users for now...
26 #if $(JAMVERSION) = 2.4 & $(JAM_DEBUG)
27 #{
28 #    echo "Warning: It is recommended to use jam2.5rc3 or later." ;
29 #}
30
31 # All scripts invoked by the build system expect a Bourne or compatible shell.
32 # Reject C-shell and its variants (such as tcsh).  Unfortunately, this is a bit
33 # of an ugly hack.  It would be nicer to perform this logic at the very end of
34 # this file as a last-minute assertion.  Unfortunately, however, it seems that
35 # references to $(SHELL) in any of the included files get bound at the point
36 # of reference, thus we need to perform this filtering as early as possible.
37 if [ Match (csh) : $(SHELL) ]
38 {
39   SHELL = "/bin/sh" ;
40 }
41
42 # jam 2.4s SubDir rule had some problems and misses the usefull SUBDIRRULES
43 # extension. So we override it here with a better version (from jam 2.5rc3)
44 if $(JAMVERSION) = 2.4
45 {
46
47 rule SubDir
48 {
49         #
50         # SubDir TOP d1 d2 ... ;
51         #
52         # Support for a project tree spanning multiple directories.
53         #
54         # SubDir declares a Jamfile's location in a project tree, setting
55         # Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
56         # files can be found.
57         #
58         # TOP is a user-select variable name for root of the tree, and
59         # d1 d2 ...  are the directory elements that lead from the root
60         # of the tree to the directory of the Jamfile.
61         #
62         # TOP can be set externally, but normally the first SubDir call
63         # computes TOP as the path up from the current directory; the
64         # path contains one ../ for each of d1 d2 ...
65         #
66         # SubDir reads once the project-specific rules file Jamrules 
67         # in the TOP directory, if present.  This can be overridden
68         # with the variable TOPRULES.
69         #
70         # SubDir supports multiple, overlaid project trees:  SubDir
71         # invocations with different TOPs can appear in the same Jamfile.
72         # The location established by the first SubDir call is used set
73         # the TOPs for the subsequent SubDir calls.
74         #
75         # SubDir's public variables:
76         #
77         #       $(TOP) = path from CWD to root.
78         #       $(SUBDIR) = path from CWD to the directory SubDir names.
79         #       $(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
80         #       $(SEARCH_SOURCE) = $(SUBDIR)
81         #       $(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
82         #       $(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
83         #       $(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s 
84         #
85
86         local _top = $(<[1]) ;
87         local _tokens = $(<[2-]) ;
88
89         #
90         # First time through sets up relative root and includes Jamrules.
91         #
92
93         if ! $(_top)
94         {
95             Exit SubDir syntax error ;
96         }
97
98         if ! $($(_top)-SET)
99         {
100             $(_top)-SET = true ;
101
102             # First time we've seen this TOP.
103             # We'll initialize a number of internal variables:
104             #
105             #   $(TOP-UP) = directories from ROOT to a common point
106             #   $(TOP-DOWN) = directories from common point to TOP
107             #   $(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
108             #   $(SUBDIR_UP) = current value of $(TOP-UP)
109             #   $(SUBDIR_DOWN) = current value of $(TOP-DOWN)
110             #   $(SUBDIR_ROOT) = current value of $(TOP-ROOT)
111             #
112
113             if $($(_top))
114             {
115                 # TOP externally set.
116                 # We'll ignore the relative (UP/DOWN) path that
117                 # got us here, and instead remember the hard ROOT.
118
119                 $(_top)-UP = ;
120                 $(_top)-DOWN = ;
121                 $(_top)-ROOT = $($(_top)) ;
122             }
123             else
124             {
125                 # TOP not preset.
126
127                 # Establishing a new TOP.  In the simplest case,
128                 # (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
129                 # merely a certain number of directories down from
130                 # the current directory, and FSubDirPath will set
131                 # TOP to a path consisting of ../ for each of the
132                 # elements of _tokens, because that represents how 
133                 # far below TOP the current directory sits.
134                 #
135                 # In the more complicated case, the starting directory
136                 # isn't the directory of jam's invocation but an 
137                 # location established by previous SubDir call.  The
138                 # starting directory is SUBDIR_UP directories up from
139                 # SUBDIR_ROOT, and then SUBDIR_DOWN directories down
140                 # from that.   If SUBDIR_ROOT is not set, that means
141                 # SUBDIR_DOWN and SUBDIR_UP represent the path from
142                 # the directory of jam's invocation.
143                 #
144                 # In the most complicated case, the _tokens also 
145                 # represents directories down, because TOP is being
146                 # estalished in a directory other than TOP's root.
147                 # Hopefully, _tokens and SUBDIR_DOWN represent the
148                 # same final directory, relative to the new TOP and
149                 # the previous SubDIr's TOP.  To find the new TOP,
150                 # we have to chop off any common directories from
151                 # then ends of _tokens and SUBDIR_DOWN.  To do so,
152                 # we reverse each of them, call FStripCommon to
153                 # remove the initial common elements, and then
154                 # reverse them again.  After this process, if
155                 # both _tokens and SUBDIR_DOWN have elements, it
156                 # means the directory names estalished by the two
157                 # SubDir calls don't match, and a warning is issued.
158                 # All hell will likely break loose at this point,
159                 # since the whole SubDir scheme relies on the SubDir
160                 # calls accurately naming the current directory.
161
162                 # Strip common trailing elements of _tokens and SUBDIR_DOWN.
163
164                 _tokens = [ FReverse $(_tokens) ] ;
165                 SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
166                 FStripCommon _tokens : SUBDIR_DOWN ;
167                 SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
168                 _tokens = [ FReverse $(_tokens) ] ;
169
170                 if $(SUBDIR_DOWN) && $(_tokens) 
171                 { 
172                     Echo Warning: SubDir $(<) misplaced! ; 
173                 }
174
175                 # We'll remember the relative (UP/DOWN) path that
176                 # got us here, plus any hard ROOT starting point
177                 # for the UP/DOWN.  If TOP is never set externally,
178                 # ROOT will always be "" (directory of jam's invocation).
179
180                 $(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
181                 $(_top)-DOWN = $(SUBDIR_DOWN) ;
182                 $(_top)-ROOT = $(SUBDIR_ROOT:E="") ;
183                 $(_top) = [ FSubDirPath $(_top) ] ;
184             }
185
186             # Set subdir vars for the inclusion of the Jamrules,
187             # just in case they have SubDir rules of their own.
188             # Note that SUBDIR_DOWN is empty: it's all the way
189             # up where the Jamrules live.  These gets overrided
190             # just after the inclusion.
191
192             SUBDIR_UP = $($(_top)-UP) ;
193             SUBDIR_DOWN = ;
194             SUBDIR_ROOT = $($(_top)-ROOT) ;
195
196             # Include $(TOPRULES) or $(TOP)/Jamrules.
197             # Include $(TOPRULES) if set.
198             # Otherwise include $(TOP)/Jamrules if present.
199
200             if $($(_top)RULES) { 
201                 include $($(_top)RULES) ;
202             } else { 
203                 NoCare $(JAMRULES:R=$($(_top)):G=$(_top)) ;
204                 include $(JAMRULES:R=$($(_top)):G=$(_top)) ;
205             }
206         }
207
208         # Get path from $(TOP) to named directory.
209         # Save dir tokens for other potential uses.
210
211         SUBDIR_UP = $($(_top)-UP) ;
212         SUBDIR_DOWN = $($(_top)-DOWN) $(_tokens) ;
213         SUBDIR_ROOT = $($(_top)-ROOT) ;
214         SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
215
216         SUBDIR = [ FSubDirPath $(<) ] ;
217
218         # Now set up SEARCH_SOURCE, LOCATE_TARGET, SOURCE_GRIST
219         # These can be reset if needed.  For example, if the source
220         # directory should not hold object files, LOCATE_TARGET can
221         # subsequently be redefined.
222
223 #echo SS: $(SUBDIR) ;
224         SEARCH_SOURCE = $(SUBDIR) ;
225         LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
226         LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
227         SOURCE_GRIST = [ FGrist $(SUBDIR_TOKENS) ] ;
228
229         # Reset per-directory ccflags, hdrs, etc,
230         # listed in SUBDIRRESET.
231         # Note use of variable expanded assignment var
232
233         SUBDIR$(SUBDIRRESET) = ;
234
235         # Invoke user-specific SubDir extensions,
236         # rule names listed in SUBDIRRULES.
237         # Note use of variable expanded rule invocation
238
239         $(SUBDIRRULES) $(<) ;
240 }
241
242 rule FSubDirPath
243 {
244         # FSubDirPath TOP d1 ... ;
245
246         # Returns path to named directory.
247
248         # If jam is invoked in a subdirectory of the TOP, then we
249         # need to prepend a ../ for every level we must climb up
250         # (TOP-UP), and then append the directory names we must 
251         # climb down (TOP-DOWN), plus the named directories d1 ...
252         # If TOP was set externally, or computed from another TOP 
253         # that was, we'll have to reroot the whole thing at TOP-ROOT.
254
255         local _r = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ;
256
257         return $(_r:R=$($(<[1])-ROOT)) ;
258 }
259
260 rule SubInclude
261 {
262         # SubInclude TOP d1 ... ;
263         #
264         # Include a subdirectory's Jamfile.
265
266         # We use SubDir to get there, in case the included Jamfile
267         # either doesn't have its own SubDir (naughty) or is a subtree
268         # with its own TOP.
269
270         if ! $($(<[1]))
271         {
272             Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ;
273         }
274
275         SubDir $(<) ;
276
277         include $(JAMFILE:D=$(SUBDIR)) ;
278 }
279
280 rule SubRules
281 {
282         # SubRules TOP d1 ... : Other-TOP ;
283         #
284         # Read another tree's Jamrules, by giving it's path according
285         # to this tree and it's own name.
286
287         if ! $($(<[1]))
288         {
289             Exit SubRules $(<[1]) without prior SubDir $(<[1]) ;
290         }
291
292         SubDir $(<) ;
293         SubDir $(>) ;
294 }
295
296 ## Now we try to fix up the already messed settings
297 ## XXX We can only hope that jam2.4 users don't try starting jam from
298 ## subdirectories
299 TOP-SET = true ;
300 TOP-UP = ;
301 TOP-DOWN = ;
302 TOP-ROOT = $(TOP) ;
303 SUBDIR_UP = $(TOP-UP) ;
304 SUBDIR_DOWN = ;
305 SUBDIR_ROOT = $(TOP-ROOT) ;
306
307 #SubDir TOP ;
308
309 } # end if $(JAMVERSION) = 2.4
310
311 # MakeLocate rule from jam 2.4 isn't optimal. Use improved version from jam
312 # 2.5
313 if $(JAMVERSION) = 2.4
314 {
315
316 rule MakeLocate
317 {
318         # MakeLocate targets : directory ;
319
320         # Sets special variable LOCATE on targets, and arranges    
321         # with MkDir to create target directory.
322
323         # Note we grist the directory name with 'dir',
324         # so that directory path components and other
325         # targets don't conflict.
326
327         if $(>)
328         {
329             LOCATE on $(<) = $(>) ;
330             Depends $(<) : $(>[1]:G=dir) ;
331             MkDir $(>[1]:G=dir) ;
332         }
333 }
334
335 }
336