]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | # Copyright 2001 David Abrahams |
2 | # Copyright 2004, 2005 Markus Schoepflin | |
3 | # Copyright 2011 John Maddock | |
4 | # Copyright 2013, 2017-2018 Cray, Inc. | |
5 | # | |
7c673cae | 6 | # Distributed under the Boost Software License, Version 1.0. |
92f5a8d4 TL |
7 | # (See accompanying file LICENSE_1_0.txt or copy at |
8 | # http://www.boost.org/LICENSE_1_0.txt) | |
7c673cae | 9 | |
92f5a8d4 TL |
10 | # README.md |
11 | # | |
12 | # This toolset is for the Cray Compiling Environment (CCE). | |
13 | # | |
14 | # The assembler, linker, and archiver are the same as those used in the | |
15 | # `gcc` toolset. Therefore, there is some duplication of code between the | |
16 | # `gcc` toolset and this toolset. | |
17 | # | |
18 | # # CCE Introduction | |
19 | # | |
20 | # Users want to compile and run massively parallel applications on Cray | |
21 | # supercomputers. Typically, the user compiles code on a login node of the | |
22 | # supercomputer and then runs the compiled program on multiple compute | |
23 | # nodes using a batch control system. This means the user is almost always | |
24 | # cross compiling. | |
25 | # | |
26 | # But, they're not just cross compiling. In order for a program to run on | |
27 | # a Cray supercomputer it has to link to particular libraries. There are | |
28 | # three general categories of libraries that user programs must link to: | |
7c673cae | 29 | # |
92f5a8d4 TL |
30 | # - Network libraries: Enable communication between processes on different |
31 | # compute nodes. Depends on the network hardware in the supercomputer. | |
32 | # - Compute node libraries: Depends on the hardware on the targeted | |
33 | # compute nodes. | |
34 | # - Language extension libraries: Depends on the language extensions used | |
35 | # by the program (e.g. OpenMP, Unified Parallel C, et cetera). | |
7c673cae | 36 | # |
92f5a8d4 TL |
37 | # Instead of forcing users to invoke the compiler with a bunch of |
38 | # libraries listed on the command line, CCE decides what libraries to link | |
39 | # based on the environment. This is primarily controlled by loading and | |
40 | # unloading modules (with the `module` command) to create a cross | |
41 | # compiling and linking environment suitable for the particular hardware | |
42 | # on the targeted Cray supercomputer. | |
43 | # | |
44 | # CCE compilers come in two parts: the compiler itself, and the compiler | |
45 | # driver. Invoking a compiler directly is not supported. We must always | |
46 | # invoke the compiler through a compiler driver: either `cc` for C code, | |
47 | # `CC` for C++ code, or `ftn` for Fortran code. The compiler driver is | |
48 | # responsible for gathering information from the environment and invoking | |
49 | # the selected compiler with the appropriate command line options. | |
50 | # | |
51 | # For more information on CCE, search for Cray publication S-2529 on the | |
52 | # Cray publications website (https://pubs.cray.com). | |
53 | ||
54 | import "class" : new ; | |
55 | import common ; | |
56 | import feature ; | |
57 | import gcc ; | |
58 | import generators ; | |
59 | import os ; | |
60 | import regex ; | |
61 | import set ; | |
62 | import toolset ; | |
63 | import type ; | |
64 | import unix ; | |
65 | ||
66 | ### | |
67 | ### 'init' | |
68 | ### | |
69 | ||
70 | rule init ( : : options * : requirements * ) | |
71 | { | |
72 | ||
73 | # User cannot specify a 'version' in their 'using' statement. Compiler | |
74 | # version is always controlled by loading and unloading modules in the | |
75 | # user's environment. | |
76 | ||
77 | # User cannot specify a 'command' in their 'using' statement. Using a | |
78 | # single 'command' argument only makes sense when a single executable can | |
79 | # compile different types of code (e.g. gcc will compile C or C++ based on | |
80 | # the file name extensions). In CCE, you have to invoke one of the three | |
81 | # compiler drivers: cc for C code, CC for C++ code, or ftn for Fortran | |
82 | # code. Each compiler driver compiles a single type of source code. It is | |
83 | # possible to let the user pass in three 'command' arguments, one for each | |
84 | # driver, but that seems like more effort that it's worth. | |
85 | ||
86 | local toolset = cray ; | |
87 | ||
88 | check-prgenv-module $(toolset) ; | |
89 | ||
90 | local command-c = [ validate-command $(toolset) cc ] ; | |
91 | local command-cxx = [ validate-command $(toolset) CC ] ; | |
92 | local command-fortran = [ validate-command $(toolset) ftn ] ; | |
93 | ||
94 | # Archive builder. | |
95 | local command-ar = [ validate-command $(toolset) ar ] ; | |
96 | ||
97 | # Archive indexer. | |
98 | local command-ranlib = [ validate-command $(toolset) ranlib ] ; | |
99 | ||
100 | # The 'command' variables always have one element, but they may contain | |
101 | # spaces (e.g. if 'command' is an absolute path and some path components | |
102 | # have spaces). | |
103 | ||
104 | local version = ; | |
105 | local developer-build = ; | |
106 | { | |
107 | local version-string = [ SHELL "\"$(command-cxx)\" -VV 2>&1" ] ; | |
108 | local version-components = [ MATCH "Version ([0-9]+).([0-9]+).([a-zA-Z0-9]+)" : $(version-string) ] ; | |
109 | if ! [ MATCH "([0-9]+)" : $(version-components[3]) ] | |
110 | { | |
111 | ||
112 | # The last component of the version is not a series of digits. This means | |
113 | # we're probably using a developer build of CCE (i.e. a compiler built by | |
114 | # a Cray employee). Developer builds report versions like '8.7.x'. | |
115 | ||
116 | developer-build = true ; | |
117 | ||
118 | # We want to treat developer builds as though they are the highest | |
119 | # possible patch version of the release. Effectively, we want to turn | |
120 | # '8.7.x' into '8.7.99'. | |
121 | ||
122 | version-components = $(version-components[1]) $(version-components[2]) 99 ; | |
123 | ||
124 | } | |
125 | ||
126 | version = $(version-components:J=.) ; | |
127 | } | |
128 | ||
129 | local build = ; | |
130 | if $(developer-build) | |
131 | { | |
132 | ||
133 | # If this is a developer build, we want to add the build subfeature to the | |
134 | # compiler. | |
135 | ||
136 | local version-string = [ SHELL "\"$(command-cxx)\" -VV 2>&1" ] ; | |
137 | build = [ MATCH "[(][0-9]+_([0-9a-fA-F]+)[)]" : $(version-string) ] ; | |
138 | ||
139 | # Truncate build hash to 7 characters | |
140 | build = [ MATCH "(.......)................................." : $(build) ] ; | |
141 | } | |
142 | ||
143 | # IMPORTANT: 'set-cray-feature-defaults' causes the Boost.Build tests to | |
144 | # fail. I tried using an 'init' argument called 'ignore-cray-defaults' and | |
145 | # setting up 'test-config.jam' to pass 'ignore-cray-defaults' during | |
146 | # testing, but I couldn't get the test to read my 'test-config.jam' file | |
147 | # when running tests individually. So, I just comment out | |
148 | # 'set-cray-feature-defaults' during testing. | |
149 | ||
150 | set-cray-feature-defaults ; | |
151 | ||
152 | { | |
153 | ||
154 | # 'check-init-parameters' ensures that each time a toolset is initialized, | |
155 | # it is initialized with a unique configuration. The return value is a | |
156 | # Boost.Build property condition which uniquely identifies this | |
157 | # configured instance of this toolset. Typically, toolsets use the | |
158 | # returned condition as the conditional in a 'toolset.flags' call to set | |
159 | # flags specific to this configuration of this toolset. | |
160 | ||
161 | local identifying-condition = [ common.check-init-parameters $(toolset) $(requirements) : version $(version) : build $(build) ] ; | |
162 | ||
163 | # 'handle-options' uses 'toolset.flags' to set 'CONFIG_COMMAND' variables | |
164 | # on targets when this toolset is used. The 'CONFIG_COMMAND' variables | |
165 | # specify the commands to call for compiling. This would be more relevant | |
166 | # if our 'init' rule had arguments that might affect the command that is | |
167 | # invoked (e.g. in many toolsets 'version' affects the name of the | |
168 | # compiler command). For now, we'll do this because it is a common pattern | |
169 | # in toolsets, and we may need it in the future. | |
170 | ||
171 | handle-options | |
172 | $(toolset) | |
173 | : $(identifying-condition) | |
174 | : $(command-c) $(command-cxx) $(command-fortran) $(command-ar) $(command-ranlib) | |
175 | : $(options) ; | |
176 | ||
177 | # Add compiler version to 'VERSION' variable on all targets. 'VERSION' is | |
178 | # not used in any actions, but it is used in some updating rule | |
179 | # procedures. | |
180 | ||
181 | toolset.flags $(toolset) VERSION $(identifying-condition) : [ numeric-version $(version) ] ; | |
182 | } | |
183 | } | |
184 | ||
185 | rule check-prgenv-module ( toolset ) | |
186 | { | |
187 | ||
188 | local compiler = [ os.environ PE_ENV ] ; | |
189 | compiler = $(compiler:L) ; | |
190 | ||
191 | # We could check that environment variable CRAY_PRGENV$PE_ENV is set to | |
192 | # "loaded", but this seems unnecessary and redundant. | |
193 | ||
194 | local default-compiler = cray ; | |
195 | ||
196 | if ! $(compiler) | |
197 | { | |
198 | log-warning $(toolset) : no PrgEnv module loaded | |
199 | : falling back to PrgEnv-$(default-compiler) | |
200 | : please load the PrgEnv-$(default-compiler) module next time ; | |
201 | compiler = $(default-compiler) ; | |
202 | } | |
203 | ||
204 | if $(compiler) != $(default-compiler) | |
205 | { | |
206 | log-error $(toolset) : compiler '$(compiler)' not supported | |
207 | : toolset initialization failed | |
208 | : please load the PrgEnv-$(default-compiler) module next time ; | |
209 | # Do not abort, as suggested by: | |
210 | # http://www.boost.org/build/doc/html/bbv2/extending/toolset_modules.html. | |
211 | } | |
212 | } | |
213 | ||
214 | rule set-cray-feature-defaults ( ) | |
215 | { | |
216 | ||
217 | # CCE users expect that using the 'cray' toolset without any explicit | |
218 | # options will give them the same result as invoking CCE without any | |
219 | # explicit options. So, we set feature defaults to match the default CCE | |
220 | # options. | |
221 | # | |
222 | # The decision to turn off <debug-symbols> by default was a tough one. | |
223 | # When CCE produces debugging symbols, it disables all inlining. This | |
224 | # causes a decrease in performance, which the user probably was not | |
225 | # expecting since they thought they were compiling with default CCE | |
226 | # options. | |
227 | ||
228 | feature.set-default cxxstd-dialect : gnu ; | |
229 | feature.set-default debug-symbols : off ; | |
230 | feature.set-default optimization : default ; | |
231 | feature.set-default inlining : default ; | |
232 | feature.set-default vectorize : default ; | |
233 | } | |
234 | ||
235 | ### | |
236 | ### Command line options | |
237 | ### | |
238 | ||
239 | if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] | |
240 | { | |
241 | ||
242 | # Check if '--debug-configuration' was passed on the command line. This is | |
243 | # inspired by 'common.jam' and other modules. | |
244 | ||
245 | # Variable names with a '.' prefix are intended to be globals. | |
246 | # | |
247 | # Refer to: | |
248 | # https://github.com/boostorg/build/blob/develop/CONTRIBUTING.rst | |
249 | ||
250 | # The Jam language uses dynamic scoping. Setting '.debug-configuration' in | |
251 | # this module influences the behavior of methods called from this module. | |
7c673cae | 252 | |
92f5a8d4 TL |
253 | .debug-configuration = true ; |
254 | } | |
255 | ||
256 | if [ MATCH (--debug-driver) : [ modules.peek : ARGV ] ] | |
257 | { | |
258 | ||
259 | .debug-driver = true ; | |
260 | } | |
261 | ||
262 | ### | |
263 | ### Features | |
264 | ### | |
7c673cae FG |
265 | |
266 | feature.extend toolset : cray ; | |
267 | ||
92f5a8d4 TL |
268 | # Typically, extending '<toolset>' with the value 'cray' would cause |
269 | # 'cray' to be the default '<toolset>' as long as it is the first value | |
270 | # added to '<toolset>'. However, we already imported the 'gcc' toolset, so | |
271 | # 'cray' is not the first value added to '<toolset>'. Therefore, we need | |
272 | # to call 'feature.set-default'. | |
273 | # | |
274 | # If the build request specifies a '<toolset>' (e.g. on the command line), | |
275 | # then the '<toolset>' feature default is ignored. However, if the 'cray' | |
276 | # toolset is selected in 'user-config.jam' (e.g. with 'using cray ;'), | |
277 | # then the build request will use the '<toolset>' feature default. | |
278 | # Therefore, we must use 'feature.set-default' so that selecting the | |
279 | # 'cray' toolset in 'user-config.jam' works correctly. | |
280 | ||
281 | feature.set-default toolset : cray ; | |
282 | ||
283 | # CCE is different from other compilers in that it optimizes, inlines, and | |
284 | # vectorizes by default. Boost.Build assumes that 'off' is the default for | |
285 | # all compilers. However, for CCE, 'off' and 'default' have different | |
286 | # meanings. For CCE, 'off' requires an additional command line argument to | |
287 | # turn the feature off. 'default' will not include an additional command | |
288 | # line argument, but will do optimization, inlining, and vectorizing at | |
289 | # whatever default level CCE uses. | |
290 | ||
291 | feature.extend optimization : default ; | |
292 | feature.extend inlining : default ; | |
293 | feature.extend vectorize : default ; | |
294 | ||
295 | ### | |
296 | ### Flags | |
297 | ### | |
298 | ||
299 | # Updating rules are named in a dotted hierarchy. For example: | |
300 | # | |
301 | # compile | |
302 | # \_ compile.c++ | |
303 | # \_ compile.c++.preprocess | |
304 | # \_ compile.c | |
305 | # \_ compile.c.preprocess | |
306 | # | |
307 | # This naming convention allows us to apply flags to multiple children in | |
308 | # the hierarchy. For example, if we apply a flag to 'compile.c++', that | |
309 | # flag is also applied to its child 'compile.c++.preprocess'. If we apply | |
310 | # a flag to 'compile', then that flag is applied to all children under | |
311 | # 'compile'. | |
312 | ||
313 | toolset.flags cray.compile OPTIONS <link>shared : -h pic ; | |
314 | ||
315 | toolset.flags cray.compile OPTIONS <optimization>default ; # Blank. | |
316 | toolset.flags cray.compile OPTIONS <optimization>off : -O 0 ; | |
317 | toolset.flags cray.compile OPTIONS <optimization>speed : -O 3 ; | |
318 | toolset.flags cray.compile OPTIONS <optimization>space ; # Blank. CCE does not optimize for space. | |
319 | ||
320 | toolset.flags cray.compile OPTIONS <inlining>default ; # Blank. | |
321 | toolset.flags cray.compile OPTIONS <inlining>off : -h ipa0 ; | |
322 | toolset.flags cray.compile OPTIONS <inlining>on ; # Blank. CCE does inlining by default. | |
323 | toolset.flags cray.compile OPTIONS <inlining>full : -h ipa5 ; | |
324 | ||
325 | toolset.flags cray.compile OPTIONS <vectorize>default ; # Blank. | |
326 | toolset.flags cray.compile OPTIONS <vectorize>off : -h vector0 ; | |
327 | toolset.flags cray.compile OPTIONS <vectorize>on ; # Blank. CCE vectorizes by default. | |
328 | toolset.flags cray.compile OPTIONS <vectorize>full : -h vector3 ; | |
329 | ||
330 | toolset.flags cray.link FINDLIBS-SA <threading>multi : rt ; # Not sure if this is correct. | |
331 | ||
332 | toolset.flags cray.link OPTIONS <link>shared : -h pic ; | |
333 | ||
334 | { | |
335 | # | |
336 | # Link flags copied from 'gcc.jam'. | |
337 | # | |
338 | ||
339 | local toolset = cray ; | |
340 | local generic-os = [ set.difference [ feature.values <target-os> ] : aix darwin vxworks solaris osf hpux ] ; | |
341 | # Strip the binary when no debugging is needed. We use --strip-all flag | |
342 | # as opposed to -s since icc (intel's compiler) is generally | |
343 | # option-compatible with and inherits from the gcc toolset, but does not | |
344 | # support -s. | |
345 | toolset.flags $(toolset).link OPTIONS <target-os>$(generic-os)/<strip>on : -Wl,--strip-all ; | |
346 | toolset.flags $(toolset).link RPATH <target-os>$(generic-os) : <dll-path> ; | |
347 | toolset.flags $(toolset).link RPATH_OPTION <target-os>$(generic-os) : -rpath ; | |
348 | toolset.flags $(toolset).link RPATH_LINK <target-os>$(generic-os) : <xdll-path> ; | |
349 | toolset.flags $(toolset).link START-GROUP <target-os>$(generic-os) : -Wl,--start-group ; | |
350 | toolset.flags $(toolset).link END-GROUP <target-os>$(generic-os) : -Wl,--end-group ; | |
351 | ||
352 | # gnu ld has the ability to change the search behaviour for libraries | |
353 | # referenced by the -l switch. These modifiers are -Bstatic and | |
354 | # -Bdynamic and change search for -l switches that follow them. The | |
355 | # following list shows the tried variants. Search stops at the first | |
356 | # variant that has a match. | |
357 | # | |
358 | # *nix: -Bstatic -lxxx | |
359 | # libxxx.a | |
360 | # | |
361 | # *nix: -Bdynamic -lxxx | |
362 | # libxxx.so | |
363 | # libxxx.a | |
364 | # | |
365 | # windows (mingw, cygwin) -Bstatic -lxxx | |
366 | # libxxx.a | |
367 | # xxx.lib | |
368 | # | |
369 | # windows (mingw, cygwin) -Bdynamic -lxxx | |
370 | # libxxx.dll.a | |
371 | # xxx.dll.a | |
372 | # libxxx.a | |
373 | # xxx.lib | |
374 | # cygxxx.dll (*) | |
375 | # libxxx.dll | |
376 | # xxx.dll | |
377 | # libxxx.a | |
378 | # | |
379 | # (*) This is for cygwin | |
380 | # Please note that -Bstatic and -Bdynamic are not a guarantee that a | |
381 | # static or dynamic lib indeed gets linked in. The switches only change | |
382 | # search patterns! | |
383 | ||
384 | # On *nix mixing shared libs with static runtime is not a good idea. | |
385 | toolset.flags $(toolset).link FINDLIBS-ST-PFX <target-os>$(generic-os)/<runtime-link>shared : -Wl,-Bstatic ; | |
386 | toolset.flags $(toolset).link FINDLIBS-SA-PFX <target-os>$(generic-os)/<runtime-link>shared : -Wl,-Bdynamic ; | |
387 | ||
388 | toolset.flags $(toolset).link HAVE_SONAME <target-os>$(generic-os) : "" ; | |
389 | toolset.flags $(toolset).link SONAME_OPTION <target-os>$(generic-os) : -h ; | |
390 | ||
391 | # See note [1] | |
392 | toolset.flags $(toolset).link OPTIONS <target-os>$(generic-os)/<runtime-link>static : -static ; | |
393 | ||
394 | # [1] | |
395 | # For <runtime-link>static we made sure there are no dynamic libraries in the | |
396 | # link. On HP-UX not all system libraries exist as archived libraries (for | |
397 | # example, there is no libunwind.a), so, on this platform, the -static option | |
398 | # cannot be specified. | |
399 | } | |
400 | ||
401 | # Flags for 'free' features ('free' features are features that do not have | |
402 | # a pre-defined set of values). | |
403 | ||
404 | toolset.flags cray.compile USER_OPTIONS <cflags> ; | |
405 | toolset.flags cray.compile.c++ USER_OPTIONS <cxxflags> ; | |
406 | toolset.flags cray.compile.asm USER_OPTIONS <asmflags> ; | |
407 | toolset.flags cray.compile DEFINES <define> ; | |
408 | toolset.flags cray.compile INCLUDES <include> ; | |
409 | ||
410 | toolset.flags cray.link USER_OPTIONS <linkflags> ; | |
411 | toolset.flags cray.link LINKPATH <library-path> ; | |
412 | toolset.flags cray.link FINDLIBS-ST <find-static-library> ; | |
413 | toolset.flags cray.link FINDLIBS-SA <find-shared-library> ; | |
414 | toolset.flags cray.link LIBRARIES <library-file> ; | |
415 | ||
416 | toolset.flags cray.archive AROPTIONS <archiveflags> ; | |
417 | ||
418 | ### | |
419 | ### Actions | |
420 | ### | |
421 | ||
422 | actions compile.c++ | |
423 | { | |
424 | "$(CONFIG_COMMAND_CXX)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -c -o "$(<)" "$(>)" $(DRIVER_OPTIONS) | |
425 | } | |
426 | ||
427 | actions compile.c | |
428 | { | |
429 | "$(CONFIG_COMMAND_C)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -c -o "$(<)" "$(>)" $(DRIVER_OPTIONS) | |
430 | } | |
431 | ||
432 | actions compile.asm | |
433 | { | |
434 | "$(CONFIG_COMMAND_CXX)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -c -o "$(<)" "$(>)" $(DRIVER_OPTIONS) | |
435 | } | |
436 | ||
437 | actions compile.c++.preprocess | |
438 | { | |
439 | "$(CONFIG_COMMAND_CXX)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -E "$(>)" >"$(<)" $(DRIVER_OPTIONS) | |
440 | } | |
441 | ||
442 | actions compile.c.preprocess | |
443 | { | |
444 | "$(CONFIG_COMMAND_C)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -E "$(>)" >"$(<)" $(DRIVER_OPTIONS) | |
445 | } | |
446 | ||
447 | # We don't want to invoke 'ld' (the linker) directly for 'link', since we | |
448 | # want to give the CCE compiler driver a chance to modify the command line | |
449 | # it passes to 'ld'. | |
450 | # | |
451 | # The question is: which CCE compiler driver do we use? The driver for C, | |
452 | # the driver for C++, or the driver for Fortran? | |
453 | # | |
454 | # Here are things that definitely do not work: | |
455 | # | |
456 | # - Using the driver for C doesn't work when linking C++ programs, because | |
457 | # things like 'std::cout' are not available in C, they are only | |
458 | # available in C++. | |
459 | # | |
460 | # We use the driver for C++ below since we are primarily interested in | |
461 | # compiling Boost, which is written in C++. Also, the C++ driver will | |
462 | # properly link C code as well. | |
463 | ||
464 | actions link bind LIBRARIES | |
465 | { | |
466 | "$(CONFIG_COMMAND_CXX)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) $(DRIVER_OPTIONS) | |
467 | } | |
468 | ||
469 | actions link.dll bind LIBRARIES | |
470 | { | |
471 | "$(CONFIG_COMMAND_CXX)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,$(RPATH) -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS) $(DRIVER_OPTIONS) | |
472 | } | |
473 | ||
474 | actions piecemeal archive | |
475 | { | |
476 | "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)" | |
477 | "$(.RANLIB)" "$(<)" | |
478 | } | |
479 | ||
480 | ### | |
481 | ### Updating rules | |
482 | ### | |
483 | ||
484 | # These are the actual updating rules that apply the associated actions | |
485 | # when called. | |
486 | ||
487 | rule compile.c++ ( targets * : sources * : properties * ) | |
488 | { | |
489 | compile-c++-procedure $(targets) : $(sources) : $(properties) ; | |
490 | } | |
491 | ||
492 | rule compile.c ( targets * : sources * : properties * ) | |
493 | { | |
494 | compile-c-procedure $(targets) : $(sources) : $(properties) ; | |
495 | } | |
496 | ||
497 | rule compile.asm ( targets * : sources * : properties * ) | |
498 | { | |
499 | compile-asm-procedure $(targets) : $(sources) : $(properties) ; | |
500 | } | |
501 | ||
502 | rule compile.c++.preprocess ( targets * : sources * : properties * ) | |
503 | { | |
504 | compile-c++-preprocess-procedure $(targets) : $(sources) : $(properties) ; | |
505 | } | |
506 | ||
507 | rule compile.c.preprocess ( targets * : sources * : properties * ) | |
508 | { | |
509 | compile-c-preprocess-procedure $(targets) : $(sources) : $(properties) ; | |
510 | } | |
511 | ||
512 | rule link ( targets * : sources * : properties * ) | |
513 | { | |
514 | link-procedure $(targets) : $(sources) : $(properties) ; | |
515 | } | |
516 | ||
517 | rule link.dll ( targets * : sources * : properties * ) | |
518 | { | |
519 | link-dll-procedure $(targets) : $(sources) : $(properties) ; | |
520 | } | |
521 | ||
522 | rule archive ( targets * : sources * : properties * ) | |
523 | { | |
524 | archive-procedure $(targets) : $(sources) : $(properties) ; | |
525 | } | |
526 | ||
527 | # These are the procedure portions of the updating rules. Calling the | |
528 | # procedure portion may modify the targets, but it will not apply actions | |
529 | # to the targets. This allows us to reuse the procedure portions of the | |
530 | # updating rules without applying the same actions to targets. | |
531 | ||
532 | rule compile-c++-procedure ( targets * : sources * : properties * ) | |
533 | { | |
534 | set-cxxstd-procedure $(targets) : $(sources) : $(properties) ; | |
535 | set-cxxstd-dialect-procedure $(targets) : $(sources) : $(properties) ; | |
536 | set-debug-symbols-procedure $(targets) : $(sources) : $(properties) ; | |
537 | add-space-procedure $(targets) : $(sources) : $(properties) ; | |
538 | debug-driver-procedure $(targets) : $(sources) : $(properties) ; | |
539 | } | |
540 | ||
541 | rule compile-c-procedure ( targets * : sources * : properties * ) | |
542 | { | |
543 | set-debug-symbols-procedure $(targets) : $(sources) : $(properties) ; | |
544 | add-space-procedure $(targets) : $(sources) : $(properties) ; | |
545 | debug-driver-procedure $(targets) : $(sources) : $(properties) ; | |
546 | } | |
547 | ||
548 | rule compile-asm-procedure ( targets * : sources * : properties * ) | |
549 | { | |
550 | compile-c++-procedure $(targets) : $(sources) : $(properties) ; | |
551 | } | |
552 | ||
553 | rule compile-c++-preprocess-procedure ( targets * : sources * : properties * ) | |
554 | { | |
555 | compile-c++-procedure $(targets) : $(sources) : $(properties) ; | |
556 | } | |
557 | ||
558 | rule compile-c-preprocess-procedure ( targets * : sources * : properties * ) | |
559 | { | |
560 | compile-c-procedure $(targets) : $(sources) : $(properties) ; | |
561 | } | |
562 | ||
563 | rule link-procedure ( targets * : sources * : properties * ) | |
564 | { | |
565 | set-cxxstd-procedure $(targets) : $(sources) : $(properties) ; | |
566 | set-cxxstd-dialect-procedure $(targets) : $(sources) : $(properties) ; | |
567 | gcc-link-procedure $(targets) : $(sources) : $(properties) ; | |
568 | debug-driver-procedure $(targets) : $(sources) : $(properties) ; | |
569 | ||
570 | # CCE driver command line flags for linking executables. | |
571 | ||
572 | local link = [ feature.get-values <link> : $(properties) ] ; | |
573 | switch $(link) | |
574 | { | |
575 | case shared : | |
576 | DRIVER_OPTIONS on $(<) += -dynamic ; | |
577 | case static : | |
578 | DRIVER_OPTIONS on $(<) += -static ; | |
579 | } | |
580 | ||
581 | # The link command line from the 'gcc' toolset includes: | |
582 | # | |
583 | # '$(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA)' | |
584 | # | |
585 | # The 'FINDLIBS-ST' and 'FINDLIBS-SA' variables are the libraries | |
586 | # specified by the '<find-static-library>' and '<find-shared-library>' | |
587 | # features, respectively. The 'FINDLIBS-ST-PFX' is typically | |
588 | # '-Wl,-Bstatic'. The 'FINDLIBS-SA-PFX' is typically '-Wl,-Bdynamic'. | |
589 | # | |
590 | # The '-Bstatic' and '-Bdynamic' flags passed to the linker tell the | |
591 | # linker how to link all of the following libraries. The flag is in effect | |
592 | # until it is overridden by another '-B' flag on the command line. | |
593 | # | |
594 | # So, it makes sense that the 'gcc' toolset includes these flags, so the | |
595 | # '<find-static-library>' and '<find-shared-library>' libraries are linked | |
596 | # properly. | |
597 | # | |
598 | # The last flag that is set ('-Bdynamic') affects the link type for any | |
599 | # other libraries on the command line. In the 'gcc' toolset, this is okay, | |
600 | # since there are no other libraries specified on the command line after | |
601 | # these flags. However, when the CCE compiler driver invokes the linker, | |
602 | # it adds additional libraries to the command line based on what modules | |
603 | # are loaded in the environment. So, the last '-B' flag on the CCE driver | |
604 | # command line affects the link type for all libraries that CCE | |
605 | # automatically appends. | |
606 | # | |
607 | # Therefore, we have to set the final '-B' flag to the link type we want | |
608 | # the CCE libraries to be linked with. Appending to the 'OPTIONS' variable | |
609 | # seems reasonable. | |
610 | ||
611 | local link = [ feature.get-values <link> : $(properties) ] ; | |
612 | switch $(link) | |
613 | { | |
614 | case shared : | |
615 | OPTIONS on $(<) += -Wl,-Bdynamic ; | |
616 | case static : | |
617 | OPTIONS on $(<) += -Wl,-Bstatic ; | |
618 | } | |
619 | } | |
620 | ||
621 | rule link-dll-procedure ( targets * : sources * : properties * ) | |
622 | { | |
623 | set-cxxstd-procedure $(targets) : $(sources) : $(properties) ; | |
624 | set-cxxstd-dialect-procedure $(targets) : $(sources) : $(properties) ; | |
625 | gcc-link-dll-procedure $(targets) : $(sources) : $(properties) ; | |
626 | debug-driver-procedure $(targets) : $(sources) : $(properties) ; | |
627 | ||
628 | # CCE driver command line flags for linking shared libraries. | |
629 | ||
630 | DRIVER_OPTIONS on $(<) += -shared ; | |
631 | } | |
632 | ||
633 | rule archive-procedure ( targets * : sources * : properties * ) | |
634 | { | |
635 | gcc-archive-procedure $(targets) : $(sources) : $(properties) ; | |
636 | debug-driver-procedure $(targets) : $(sources) : $(properties) ; | |
637 | } | |
638 | ||
639 | # Utility procedure rules intended to be called from updating rules. | |
640 | ||
641 | rule gcc-link-procedure ( targets * : sources * : properties * ) | |
642 | { | |
643 | ||
644 | # Copied from 'gcc.jam'. | |
645 | ||
646 | SPACE on $(targets) = " " ; | |
647 | # Serialize execution of the 'link' action, since running N links in | |
648 | # parallel is just slower. For now, serialize only gcc links, it might be a | |
649 | # good idea to serialize all links. | |
650 | JAM_SEMAPHORE on $(targets) = <s>gcc-link-semaphore ; | |
651 | gcc.quote-rpath $(targets) ; | |
652 | } | |
653 | ||
654 | rule gcc-link-dll-procedure ( targets * : sources * : properties * ) | |
655 | { | |
656 | ||
657 | # Copied from 'gcc.jam'. | |
658 | ||
659 | SPACE on $(targets) = " " ; | |
660 | JAM_SEMAPHORE on $(targets) = <s>gcc-link-semaphore ; | |
661 | gcc.quote-rpath $(targets) ; | |
662 | } | |
663 | ||
664 | rule gcc-archive-procedure ( targets * : sources * : properties * ) | |
665 | { | |
666 | ||
667 | # Copied from 'gcc.jam'. | |
668 | ||
669 | # Always remove archive and start again. Here is the rationale from | |
670 | # | |
671 | # Andre Hentz: | |
672 | # | |
673 | # I had a file, say a1.c, that was included into liba.a. I moved a1.c to | |
674 | # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd | |
675 | # errors. After some debugging I traced it back to the fact that a1.o was | |
676 | # *still* in liba.a | |
677 | # | |
678 | # Rene Rivera: | |
679 | # | |
680 | # Originally removing the archive was done by splicing an RM onto the | |
681 | # archive action. That makes archives fail to build on NT when they have | |
682 | # many files because it will no longer execute the action directly and blow | |
683 | # the line length limit. Instead we remove the file in a different action, | |
684 | # just before building the archive. | |
685 | # | |
686 | local clean.a = $(targets[1])(clean) ; | |
687 | TEMPORARY $(clean.a) ; | |
688 | NOCARE $(clean.a) ; | |
689 | LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ; | |
690 | DEPENDS $(clean.a) : $(sources) ; | |
691 | DEPENDS $(targets) : $(clean.a) ; | |
692 | common.RmTemps $(clean.a) : $(targets) ; | |
693 | } | |
694 | ||
695 | rule add-space-procedure ( targets * : sources * : properties * ) | |
696 | { | |
697 | SPACE on $(targets) = " " ; | |
698 | } | |
699 | ||
700 | rule set-cxxstd-procedure ( targets * : sources * : properties * ) | |
701 | { | |
702 | ||
703 | # Translate '<cxxstd>' into a standard recognized by CCE. | |
704 | ||
705 | local version = [ on $(targets[1]) return $(VERSION) ] ; | |
706 | ||
707 | local cxxstd = [ feature.get-values cxxstd : $(properties) ] ; | |
708 | local cray-cxxstd = ; | |
709 | ||
710 | local unsupported-values = 2a ; # I don't know what '2a' means. | |
711 | if $(cxxstd) && $(cxxstd) in $(unsupported-values) | |
712 | { | |
713 | ||
714 | log-warning cray : ignoring unsupported property '<cxxstd>$(cxxstd)' ; | |
715 | ||
716 | # Set to default value, or blank if default is unsupported. | |
717 | ||
718 | local default-value = [ get-default-feature-value cxxstd ] ; | |
719 | if $(default-value) in $(unsupported-values) | |
720 | { | |
721 | cxxstd = ; | |
722 | } | |
723 | else | |
724 | { | |
725 | cxxstd = $(default-value) ; | |
726 | } | |
727 | } | |
728 | ||
729 | switch $(cxxstd) | |
730 | { | |
731 | case 98 : cray-cxxstd = 03 ; | |
732 | case 03 : cray-cxxstd = 03 ; | |
733 | case 0x : cray-cxxstd = 11 ; | |
734 | case 11 : cray-cxxstd = 11 ; | |
735 | case 1y : cray-cxxstd = 14 ; | |
736 | case 14 : cray-cxxstd = 14 ; | |
737 | case 1z : cray-cxxstd = 17 ; | |
738 | case 17 : cray-cxxstd = 17 ; | |
739 | case latest : | |
740 | cray-cxxstd = [ latest-cray-cxxstd $(version) ] ; | |
741 | } | |
742 | ||
743 | # If the 'cray-cxxstd' is not supported by this compiler version, we just | |
744 | # let the command line fail. | |
745 | ||
746 | # If 'cxxstd' was blank, then 'cray-cxxstd' is also blank, and nothing is | |
747 | # added to the command line. The compiler just uses it's default C++ | |
748 | # standard. | |
749 | ||
750 | # Apply final options. | |
751 | local space = " " ; | |
752 | OPTIONS on $(targets) += -h$(space)std=c++$(cray-cxxstd) ; | |
753 | } | |
754 | ||
755 | rule set-cxxstd-dialect-procedure ( targets * : sources * : properties * ) | |
756 | { | |
757 | ||
758 | # Translate '<cxxstd-dialect>' into '-h [no]conform' and '-h [no]gnu' | |
759 | # options. | |
760 | ||
761 | local version = [ on $(targets[1]) return $(VERSION) ] ; | |
762 | ||
763 | local cxxstd-dialect = [ feature.get-values cxxstd-dialect : $(properties) ] ; | |
764 | local cray-conform = ; | |
765 | local cray-gnu = ; | |
766 | ||
767 | local unsupported-values = ms ; | |
768 | if $(cxxstd-dialect) && $(cxxstd-dialect) in $(unsupported-values) | |
769 | { | |
770 | ||
771 | log-warning cray : ignoring unsupported property '<cxxstd-dialect>$(cxxstd-dialect)' ; | |
772 | ||
773 | # Set to default value, or blank if default is unsupported. | |
774 | ||
775 | local default-value = [ get-default-feature-value cxxstd-dialect ] ; | |
776 | if $(default-value) in $(unsupported-values) | |
777 | { | |
778 | cxxstd-dialect = ; | |
779 | } | |
780 | else | |
781 | { | |
782 | cxxstd-dialect = $(default-value) ; | |
783 | } | |
784 | } | |
785 | ||
786 | switch $(cxxstd-dialect) | |
787 | { | |
788 | case gnu : cray-conform = noconform ; | |
789 | cray-gnu = gnu ; | |
790 | case iso : cray-conform = conform ; | |
791 | cray-gnu = nognu ; | |
792 | } | |
793 | ||
794 | if [ has-conform-option $(version) ] = false | |
795 | { | |
796 | # The '-h [no]conform' option is ignored in recent versions of CCE. | |
797 | cray-conform = ; | |
798 | } | |
799 | ||
800 | # If 'cxxstd-dialect' was blank, then 'cray-conform' and 'cray-gnu' are | |
801 | # also blank, and nothing is added to the command line. The compiler just | |
802 | # uses it's default C++ dialect. | |
803 | ||
804 | # Apply final options. | |
805 | local space = " " ; | |
806 | OPTIONS on $(targets) += -h$(space)$(cray-conform) | |
807 | -h$(space)$(cray-gnu) ; | |
808 | } | |
809 | ||
810 | rule set-debug-symbols-procedure ( targets * : sources * : properties * ) | |
811 | { | |
812 | ||
813 | local debug-symbols = [ feature.get-values <debug-symbols> : $(properties) ] ; | |
814 | if $(debug-symbols) = "on" | |
815 | { | |
816 | local optimization = [ feature.get-values <optimization> : $(properties) ] ; | |
817 | local debug-option = ; | |
818 | if $(optimization) = off | |
819 | { | |
820 | debug-option = 0 ; | |
821 | } | |
822 | else | |
823 | { | |
824 | debug-option = 3 ; | |
825 | } | |
826 | ||
827 | local space = " " ; | |
828 | OPTIONS on $(targets) += -G$(space)$(debug-option) ; | |
829 | } | |
830 | } | |
831 | ||
832 | rule debug-driver-procedure ( targets * : sources * : properties * ) | |
833 | { | |
834 | if $(.debug-driver) | |
835 | { | |
836 | ||
837 | # Passing '-vv' to the CCE driver causes it to output the command lines | |
838 | # for the underlying tools that it invokes. | |
839 | ||
840 | DRIVER_OPTIONS on $(<) += -vv ; | |
841 | } | |
842 | } | |
843 | ||
844 | ### | |
845 | ### Generators | |
846 | ### | |
847 | ||
848 | class cray-linking-generator : gcc-linking-generator | |
849 | { | |
850 | rule action-class ( ) | |
851 | { | |
852 | return action ; | |
853 | } | |
854 | } | |
855 | ||
856 | # We reuse some generator classes from the 'unix' toolset. Specifically, | |
857 | # we are reusing generators for the following updating actions: | |
858 | # | |
859 | # - 'archive' | |
860 | # - 'searched-lib-generator' | |
861 | # - 'prebuilt' | |
862 | # | |
863 | # Inheriting these generators is like using the same generator classes as | |
864 | # the 'unix' toolset, but pointing them to the 'cray' updating rules. | |
865 | ||
866 | toolset.inherit-generators cray : unix : unix.link unix.link.dll ; | |
867 | ||
868 | # The 'C-compiling-generator' class adds source paths to the '<include>' | |
869 | # property. | |
870 | ||
871 | generators.register [ new C-compiling-generator | |
872 | cray.compile.c++ | |
873 | : CPP | |
874 | : OBJ | |
875 | : <toolset>cray ] ; | |
876 | generators.register [ new C-compiling-generator | |
877 | cray.compile.c | |
878 | : C | |
879 | : OBJ | |
880 | : <toolset>cray ] ; | |
881 | generators.register [ new C-compiling-generator | |
882 | cray.compile.asm | |
883 | : ASM | |
884 | : OBJ | |
885 | : <toolset>cray ] ; | |
886 | generators.register [ new C-compiling-generator | |
887 | cray.compile.c++.preprocess | |
888 | : CPP | |
889 | : PREPROCESSED_CPP | |
890 | : <toolset>cray ] ; | |
891 | generators.register [ new C-compiling-generator | |
892 | cray.compile.c.preprocess | |
893 | : C | |
894 | : PREPROCESSED_C | |
895 | : <toolset>cray ] ; | |
896 | generators.register [ new cray-linking-generator | |
897 | cray.link | |
898 | : LIB OBJ | |
899 | : EXE | |
900 | : <toolset>cray ] ; | |
901 | generators.register [ new cray-linking-generator | |
902 | cray.link.dll | |
903 | : LIB OBJ | |
904 | : SHARED_LIB | |
905 | : <toolset>cray ] ; | |
906 | ||
907 | # Tell Boost.Build to prefer 'cray' generators over other valid | |
908 | # generators. This is used to resolve a tie when Boost.Build finds that | |
909 | # there is more than one viable generator for a particular build request. | |
7c673cae | 910 | |
7c673cae FG |
911 | generators.override cray.prebuilt : builtin.prebuilt ; |
912 | generators.override cray.searched-lib-generator : searched-lib-generator ; | |
913 | ||
92f5a8d4 TL |
914 | type.set-generated-target-suffix PREPROCESSED_CPP : <toolset>cray : i ; |
915 | type.set-generated-target-suffix PREPROCESSED_C : <toolset>cray : i ; | |
916 | ||
917 | ### | |
918 | ### Utility rules | |
919 | ### | |
920 | ||
921 | rule validate-command ( toolset command ) | |
922 | { | |
923 | local found-command = [ common.find-tool $(command) ] ; | |
924 | if $(found-command) && $(.debug-configuration) | |
925 | { | |
926 | log-notice $(toolset) : command '$(command)' found at [ common.get-absolute-tool-path $(found-command) ] ; | |
927 | } | |
928 | if ! $(found-command) | |
929 | { | |
930 | log-warning $(toolset) : command '$(command)' not found ; | |
931 | found-command = $(command) ; | |
932 | } | |
933 | return $(found-command) ; | |
934 | } | |
935 | ||
936 | local rule options-helper ( rule-or-module variable-name condition * : feature options * ) | |
937 | { | |
938 | toolset.flags $(rule-or-module) $(variable-name) $(condition) : [ feature.get-values $(feature) : $(options) ] : unchecked ; | |
939 | } | |
940 | ||
941 | rule handle-options ( | |
942 | toolset | |
943 | : toolset-condition * | |
944 | : command-c command-cxx command-fortran command-ar command-ranlib | |
945 | : options * | |
946 | ) | |
947 | { | |
948 | ||
949 | # Configures some common 'toolset.flags' options. In particular, this rule | |
950 | # sets the compiler command name to invoke. Inspired by | |
951 | # 'common.handle-options'. | |
7c673cae | 952 | |
92f5a8d4 TL |
953 | # We cannot use a single 'CONFIG_COMMAND' variable because each CCE driver |
954 | # can only handle a single source code language. Therefore, we have to | |
955 | # give actions a way to specify which driver they intend to use, and we | |
956 | # accomplish this by providing multiple 'CONFIG_COMMAND' variables to the | |
957 | # action. We cannot set the language through a flag in the 'OPTIONS' | |
958 | # variable the way the 'gcc' toolset does. | |
959 | ||
960 | toolset.flags $(toolset) CONFIG_COMMAND_C $(toolset-condition) : $(command-c) : unchecked ; | |
961 | toolset.flags $(toolset) CONFIG_COMMAND_CXX $(toolset-condition) : $(command-cxx) : unchecked ; | |
962 | toolset.flags $(toolset) CONFIG_COMMAND_FORTRAN $(toolset-condition) : $(command-fortran) : unchecked ; | |
963 | toolset.flags $(toolset).archive .AR $(toolset-condition) : $(command-ar) : unchecked ; | |
964 | toolset.flags $(toolset).archive .RANLIB $(toolset-condition) : $(command-ranlib) : unchecked ; | |
965 | ||
966 | # The following flags are applied to all targets built by this | |
967 | # configuration of this toolset. This particular configuration of this | |
968 | # toolset is identified by '$(toolset-condition)'. This allows the user to | |
969 | # specify 'options' in their 'using' statement, and those options will be | |
970 | # applied to all targets built by this configuration of this toolset. | |
971 | ||
972 | options-helper $(toolset).compile USER_OPTIONS $(toolset-condition) : <compileflags> $(options) ; | |
973 | options-helper $(toolset).compile USER_OPTIONS $(toolset-condition) : <cflags> $(options) ; | |
974 | options-helper $(toolset).compile.c++ USER_OPTIONS $(toolset-condition) : <cxxflags> $(options) ; | |
975 | options-helper $(toolset).compile.fortran USER_OPTIONS $(toolset-condition) : <fflags> $(options) ; | |
976 | options-helper $(toolset).compile.asm USER_OPTIONS $(toolset-condition) : <asmflags> $(options) ; | |
977 | options-helper $(toolset).compile DEFINES $(toolset-condition) : <define> $(options) ; | |
978 | options-helper $(toolset).compile INCLUDES $(toolset-condition) : <include> $(options) ; | |
979 | ||
980 | options-helper $(toolset).link USER_OPTIONS $(toolset-condition) : <linkflags> $(options) ; | |
981 | options-helper $(toolset).link LINKPATH $(toolset-condition) : <library-path> $(options) ; | |
982 | options-helper $(toolset).link FINDLIBS-ST $(toolset-condition) : <find-static-library> $(options) ; | |
983 | options-helper $(toolset).link FINDLIBS-SA $(toolset-condition) : <find-shared-library> $(options) ; | |
984 | options-helper $(toolset).link LIBRARIES $(toolset-condition) : <library-file> $(options) ; | |
985 | ||
986 | options-helper $(toolset).archive AROPTIONS $(toolset-condition) : <archiveflags> $(options) ; | |
987 | } | |
988 | ||
989 | rule latest-cray-cxxstd ( compiler-version ) | |
990 | { | |
991 | # Select latest 'cray-cxxstd' based on compiler version. | |
992 | ||
993 | local cray-cxxstd = 03 ; | |
994 | ||
995 | if $(compiler-version) >= [ numeric-version 8.6 ] | |
996 | { | |
997 | cray-cxxstd = 14 ; | |
998 | } | |
999 | ||
1000 | return $(cray-cxxstd) ; | |
1001 | } | |
1002 | ||
1003 | rule has-conform-option ( compiler-version ) | |
7c673cae | 1004 | { |
92f5a8d4 TL |
1005 | |
1006 | # Returns 'true' or 'false'. Returns empty list if the 'compiler-version' | |
1007 | # is not supported. | |
1008 | ||
1009 | local result = true ; | |
1010 | ||
1011 | if $(compiler-version) >= [ numeric-version 8.6 ] | |
7c673cae | 1012 | { |
92f5a8d4 TL |
1013 | result = false ; |
1014 | } | |
1015 | ||
1016 | return $(result) ; | |
1017 | } | |
1018 | ||
1019 | local rule justify-right ( pad-char elements * ) | |
1020 | { | |
1021 | ||
1022 | # Returns a list of 'elements' where each 'element' is at least 2 | |
1023 | # characters long. If an 'element' is less than two characters long, pads | |
1024 | # 'element' with 'pad-char' to make it 2 characters long. | |
7c673cae | 1025 | |
92f5a8d4 TL |
1026 | local result = ; |
1027 | local p = $(pad-char) ; | |
1028 | for local e in $(elements) | |
1029 | { | |
1030 | switch $(e) | |
7c673cae | 1031 | { |
92f5a8d4 TL |
1032 | case ?? : result += $(e) ; |
1033 | case ? : result += $(p)$(e) ; | |
1034 | case * : result += $(p)$(p) ; | |
1035 | } | |
1036 | } | |
1037 | return $(result) ; | |
1038 | } | |
7c673cae | 1039 | |
92f5a8d4 | 1040 | local rule list-justify-left ( pad-elem elements * ) |
7c673cae | 1041 | { |
92f5a8d4 TL |
1042 | |
1043 | # Add 'pad-elem' to 'elements' list until it has 4 elements. If 'elements' | |
1044 | # list already had 4 or more elements, returns the first 4 elements in | |
1045 | # 'elements' list. | |
1046 | ||
1047 | local tally = x ; | |
1048 | local result = ; | |
1049 | for local e in $(elements) | |
1050 | { | |
1051 | if $(tally) != xxxxx | |
1052 | { | |
1053 | result += $(e) ; | |
1054 | tally = $(tally)x ; | |
1055 | } | |
1056 | } | |
1057 | ||
1058 | while $(tally) != xxxxx | |
1059 | { | |
1060 | result += $(pad-elem) ; | |
1061 | tally = $(tally)x ; | |
1062 | } | |
1063 | ||
1064 | return $(result) ; | |
7c673cae FG |
1065 | } |
1066 | ||
92f5a8d4 TL |
1067 | local rule numeric-version ( dotted-version ) |
1068 | { | |
1069 | ||
1070 | # Returns a numeric representation of version that can be compared | |
1071 | # directly with comparison operators. | |
7c673cae | 1072 | |
92f5a8d4 TL |
1073 | local result = [ regex.split $(dotted-version) "[.]" ] ; |
1074 | result = [ list-justify-left 0 $(result) ] ; | |
1075 | result = [ justify-right 0 $(result) ] ; | |
1076 | result = $(result:J="") ; | |
1077 | ||
1078 | return $(result) ; | |
1079 | } | |
1080 | ||
1081 | local rule get-default-feature-value ( feature-name ) | |
7c673cae | 1082 | { |
92f5a8d4 TL |
1083 | local default-property = [ feature.defaults $(feature-name) ] ; |
1084 | local default-value = [ feature.get-values $(feature-name) : $(default-property) ] ; | |
1085 | return $(default-value) ; | |
7c673cae FG |
1086 | } |
1087 | ||
92f5a8d4 TL |
1088 | rule log ( log-level prefix ? : * ) |
1089 | { | |
1090 | for local message-arg in 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
1091 | { | |
1092 | local message = $($(message-arg)) ; | |
1093 | if $(message) | |
1094 | { | |
1095 | ECHO "$(log-level):" "$(prefix):" $(message) ; | |
1096 | } | |
1097 | } | |
1098 | } | |
7c673cae | 1099 | |
92f5a8d4 | 1100 | rule log-error ( prefix ? : * ) |
7c673cae | 1101 | { |
92f5a8d4 | 1102 | log error $(prefix) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) : $(17) : $(18) : $(19) : $(20) : $(21) : $(22) : $(23) : $(24) ; |
7c673cae FG |
1103 | } |
1104 | ||
92f5a8d4 TL |
1105 | rule log-warning ( prefix ? : * ) |
1106 | { | |
1107 | log warning $(prefix) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) : $(17) : $(18) : $(19) : $(20) : $(21) : $(22) : $(23) : $(24) ; | |
1108 | } | |
7c673cae | 1109 | |
92f5a8d4 | 1110 | rule log-notice ( prefix ? : * ) |
7c673cae | 1111 | { |
92f5a8d4 | 1112 | log notice $(prefix) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) : $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16) : $(17) : $(18) : $(19) : $(20) : $(21) : $(22) : $(23) : $(24) ; |
7c673cae FG |
1113 | } |
1114 | ||
92f5a8d4 | 1115 | rule __test__ ( ) |
7c673cae | 1116 | { |
92f5a8d4 TL |
1117 | import assert ; |
1118 | ||
1119 | assert.result 08060000 : numeric-version 8.6 ; | |
1120 | assert.result 08061500 : numeric-version 8.6.15 ; | |
1121 | assert.result 08061501 : numeric-version 8.6.15.1 ; | |
1122 | assert.result 08061501 : numeric-version 8.6.15.1.2 ; | |
1123 | ||
1124 | local a = [ numeric-version 8.6 ] ; | |
1125 | local b = [ numeric-version 8.5.9 ] ; | |
1126 | ||
1127 | # 'assert.equal x : y' forces the test to fail. It's like saying 'assert | |
1128 | # false'. | |
1129 | ||
1130 | if ! ( $(a) > $(b) ) | |
1131 | { | |
1132 | assert.equal x : y ; | |
1133 | } | |
1134 | ||
1135 | if ! ( $(b) < $(a) ) | |
1136 | { | |
1137 | assert.equal x : y ; | |
1138 | } | |
1139 | ||
1140 | if ! ( $(a) >= $(b) ) | |
1141 | { | |
1142 | assert.equal x : y ; | |
1143 | } | |
1144 | ||
1145 | if ! ( $(a) >= $(a) ) | |
1146 | { | |
1147 | assert.equal x : y ; | |
1148 | } | |
1149 | ||
1150 | if ! ( $(b) <= $(a) ) | |
1151 | { | |
1152 | assert.equal x : y ; | |
1153 | } | |
1154 | ||
1155 | if ! ( $(b) <= $(b) ) | |
1156 | { | |
1157 | assert.equal x : y ; | |
1158 | } | |
1159 | ||
1160 | if ! ( $(a) = $(a) ) | |
1161 | { | |
1162 | assert.equal x : y ; | |
1163 | } | |
1164 | ||
1165 | if ! ( $(a) != $(b) ) | |
1166 | { | |
1167 | assert.equal x : y ; | |
1168 | } | |
7c673cae | 1169 | } |