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