mirror of
https://github.com/boostorg/build.git
synced 2026-02-15 13:02:11 +00:00
`ar s` seems to be widely supported for a very long time: - at least binutils 2.10 (June 2000) - at least Darwin 8.0 (April 2005) - since FreeBSD 3.0 (October 1998) Note: Most of other (non-widely used) toolsets do not call `ranlib` and do not call `ar` with `s` flag either. I have no idea if they are correct or not, so I am not touching them here.
1159 lines
40 KiB
Plaintext
1159 lines
40 KiB
Plaintext
# Copyright 2001 David Abrahams
|
|
# Copyright 2004, 2005 Markus Schoepflin
|
|
# Copyright 2011 John Maddock
|
|
# Copyright 2013, 2017-2018 Cray, Inc.
|
|
#
|
|
# Distributed under the Boost Software License, Version 1.0.
|
|
# (See accompanying file LICENSE.txt or copy at
|
|
# https://www.bfgroup.xyz/b2/LICENSE.txt)
|
|
|
|
# README.md
|
|
#
|
|
# This toolset is for the Cray Compiling Environment (CCE).
|
|
#
|
|
# The assembler, linker, and archiver are the same as those used in the
|
|
# `gcc` toolset. Therefore, there is some duplication of code between the
|
|
# `gcc` toolset and this toolset.
|
|
#
|
|
# # CCE Introduction
|
|
#
|
|
# Users want to compile and run massively parallel applications on Cray
|
|
# supercomputers. Typically, the user compiles code on a login node of the
|
|
# supercomputer and then runs the compiled program on multiple compute
|
|
# nodes using a batch control system. This means the user is almost always
|
|
# cross compiling.
|
|
#
|
|
# But, they're not just cross compiling. In order for a program to run on
|
|
# a Cray supercomputer it has to link to particular libraries. There are
|
|
# three general categories of libraries that user programs must link to:
|
|
#
|
|
# - Network libraries: Enable communication between processes on different
|
|
# compute nodes. Depends on the network hardware in the supercomputer.
|
|
# - Compute node libraries: Depends on the hardware on the targeted
|
|
# compute nodes.
|
|
# - Language extension libraries: Depends on the language extensions used
|
|
# by the program (e.g. OpenMP, Unified Parallel C, et cetera).
|
|
#
|
|
# Instead of forcing users to invoke the compiler with a bunch of
|
|
# libraries listed on the command line, CCE decides what libraries to link
|
|
# based on the environment. This is primarily controlled by loading and
|
|
# unloading modules (with the `module` command) to create a cross
|
|
# compiling and linking environment suitable for the particular hardware
|
|
# on the targeted Cray supercomputer.
|
|
#
|
|
# CCE compilers come in two parts: the compiler itself, and the compiler
|
|
# driver. Invoking a compiler directly is not supported. We must always
|
|
# invoke the compiler through a compiler driver: either `cc` for C code,
|
|
# `CC` for C++ code, or `ftn` for Fortran code. The compiler driver is
|
|
# responsible for gathering information from the environment and invoking
|
|
# the selected compiler with the appropriate command line options.
|
|
#
|
|
# For more information on CCE, search for Cray publication S-2529 on the
|
|
# Cray publications website (https://pubs.cray.com).
|
|
|
|
import "class" : new ;
|
|
import common ;
|
|
import feature ;
|
|
import gcc ;
|
|
import generators ;
|
|
import os ;
|
|
import regex ;
|
|
import set ;
|
|
import toolset ;
|
|
import type ;
|
|
import unix ;
|
|
|
|
###
|
|
### 'init'
|
|
###
|
|
|
|
rule init ( : : options * : requirements * )
|
|
{
|
|
|
|
# User cannot specify a 'version' in their 'using' statement. Compiler
|
|
# version is always controlled by loading and unloading modules in the
|
|
# user's environment.
|
|
|
|
# User cannot specify a 'command' in their 'using' statement. Using a
|
|
# single 'command' argument only makes sense when a single executable can
|
|
# compile different types of code (e.g. gcc will compile C or C++ based on
|
|
# the file name extensions). In CCE, you have to invoke one of the three
|
|
# compiler drivers: cc for C code, CC for C++ code, or ftn for Fortran
|
|
# code. Each compiler driver compiles a single type of source code. It is
|
|
# possible to let the user pass in three 'command' arguments, one for each
|
|
# driver, but that seems like more effort that it's worth.
|
|
|
|
local toolset = cray ;
|
|
|
|
check-prgenv-module $(toolset) ;
|
|
|
|
local command-c = [ validate-command $(toolset) cc ] ;
|
|
local command-cxx = [ validate-command $(toolset) CC ] ;
|
|
local command-fortran = [ validate-command $(toolset) ftn ] ;
|
|
|
|
# Archive builder.
|
|
local command-ar = [ validate-command $(toolset) ar ] ;
|
|
|
|
# The 'command' variables always have one element, but they may contain
|
|
# spaces (e.g. if 'command' is an absolute path and some path components
|
|
# have spaces).
|
|
|
|
local version = ;
|
|
local developer-build = ;
|
|
{
|
|
local version-string = [ SHELL "\"$(command-cxx)\" -VV 2>&1" ] ;
|
|
local version-components = [ MATCH "Version ([0-9]+).([0-9]+).([a-zA-Z0-9]+)" : $(version-string) ] ;
|
|
if ! [ MATCH "([0-9]+)" : $(version-components[3]) ]
|
|
{
|
|
|
|
# The last component of the version is not a series of digits. This means
|
|
# we're probably using a developer build of CCE (i.e. a compiler built by
|
|
# a Cray employee). Developer builds report versions like '8.7.x'.
|
|
|
|
developer-build = true ;
|
|
|
|
# We want to treat developer builds as though they are the highest
|
|
# possible patch version of the release. Effectively, we want to turn
|
|
# '8.7.x' into '8.7.99'.
|
|
|
|
version-components = $(version-components[1]) $(version-components[2]) 99 ;
|
|
|
|
}
|
|
|
|
version = $(version-components:J=.) ;
|
|
}
|
|
|
|
local build = ;
|
|
if $(developer-build)
|
|
{
|
|
|
|
# If this is a developer build, we want to add the build subfeature to the
|
|
# compiler.
|
|
|
|
local version-string = [ SHELL "\"$(command-cxx)\" -VV 2>&1" ] ;
|
|
build = [ MATCH "[(][0-9]+_([0-9a-fA-F]+)[)]" : $(version-string) ] ;
|
|
|
|
# Truncate build hash to 7 characters
|
|
build = [ MATCH "(.......)................................." : $(build) ] ;
|
|
}
|
|
|
|
# IMPORTANT: 'set-cray-feature-defaults' causes the B2 tests to
|
|
# fail. I tried using an 'init' argument called 'ignore-cray-defaults' and
|
|
# setting up 'test-config.jam' to pass 'ignore-cray-defaults' during
|
|
# testing, but I couldn't get the test to read my 'test-config.jam' file
|
|
# when running tests individually. So, I just comment out
|
|
# 'set-cray-feature-defaults' during testing.
|
|
|
|
set-cray-feature-defaults ;
|
|
|
|
{
|
|
|
|
# 'check-init-parameters' ensures that each time a toolset is initialized,
|
|
# it is initialized with a unique configuration. The return value is a
|
|
# B2 property condition which uniquely identifies this
|
|
# configured instance of this toolset. Typically, toolsets use the
|
|
# returned condition as the conditional in a 'toolset.flags' call to set
|
|
# flags specific to this configuration of this toolset.
|
|
|
|
local identifying-condition = [ common.check-init-parameters $(toolset) $(requirements) : version $(version) : build $(build) ] ;
|
|
|
|
# 'handle-options' uses 'toolset.flags' to set 'CONFIG_COMMAND' variables
|
|
# on targets when this toolset is used. The 'CONFIG_COMMAND' variables
|
|
# specify the commands to call for compiling. This would be more relevant
|
|
# if our 'init' rule had arguments that might affect the command that is
|
|
# invoked (e.g. in many toolsets 'version' affects the name of the
|
|
# compiler command). For now, we'll do this because it is a common pattern
|
|
# in toolsets, and we may need it in the future.
|
|
|
|
handle-options
|
|
$(toolset)
|
|
: $(identifying-condition)
|
|
: $(command-c) $(command-cxx) $(command-fortran) $(command-ar)
|
|
: $(options) ;
|
|
|
|
# Add compiler version to 'VERSION' variable on all targets. 'VERSION' is
|
|
# not used in any actions, but it is used in some updating rule
|
|
# procedures.
|
|
|
|
toolset.flags $(toolset) VERSION $(identifying-condition) : [ numeric-version $(version) ] ;
|
|
}
|
|
}
|
|
|
|
rule check-prgenv-module ( toolset )
|
|
{
|
|
|
|
local compiler = [ os.environ PE_ENV ] ;
|
|
compiler = $(compiler:L) ;
|
|
|
|
# We could check that environment variable CRAY_PRGENV$PE_ENV is set to
|
|
# "loaded", but this seems unnecessary and redundant.
|
|
|
|
local default-compiler = cray ;
|
|
|
|
if ! $(compiler)
|
|
{
|
|
log-warning $(toolset) : no PrgEnv module loaded
|
|
: falling back to PrgEnv-$(default-compiler)
|
|
: please load the PrgEnv-$(default-compiler) module next time ;
|
|
compiler = $(default-compiler) ;
|
|
}
|
|
|
|
if $(compiler) != $(default-compiler)
|
|
{
|
|
log-error $(toolset) : compiler '$(compiler)' not supported
|
|
: toolset initialization failed
|
|
: please load the PrgEnv-$(default-compiler) module next time ;
|
|
# Do not abort, as suggested by:
|
|
# https://www.bfgroup.xyz/b2/manual/release/index.html#bbv2.extending.toolset_modules.
|
|
}
|
|
}
|
|
|
|
rule set-cray-feature-defaults ( )
|
|
{
|
|
|
|
# CCE users expect that using the 'cray' toolset without any explicit
|
|
# options will give them the same result as invoking CCE without any
|
|
# explicit options. So, we set feature defaults to match the default CCE
|
|
# options.
|
|
#
|
|
# The decision to turn off <debug-symbols> by default was a tough one.
|
|
# When CCE produces debugging symbols, it disables all inlining. This
|
|
# causes a decrease in performance, which the user probably was not
|
|
# expecting since they thought they were compiling with default CCE
|
|
# options.
|
|
|
|
feature.set-default cxxstd-dialect : gnu ;
|
|
feature.set-default debug-symbols : off ;
|
|
feature.set-default optimization : default ;
|
|
feature.set-default inlining : default ;
|
|
feature.set-default vectorize : default ;
|
|
}
|
|
|
|
###
|
|
### Command line options
|
|
###
|
|
|
|
if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
|
|
{
|
|
|
|
# Check if '--debug-configuration' was passed on the command line. This is
|
|
# inspired by 'common.jam' and other modules.
|
|
|
|
# Variable names with a '.' prefix are intended to be globals.
|
|
#
|
|
# Refer to: CONTRIBUTING.adoc
|
|
|
|
# The Jam language uses dynamic scoping. Setting '.debug-configuration' in
|
|
# this module influences the behavior of methods called from this module.
|
|
|
|
.debug-configuration = true ;
|
|
}
|
|
|
|
if [ MATCH (--debug-driver) : [ modules.peek : ARGV ] ]
|
|
{
|
|
|
|
.debug-driver = true ;
|
|
}
|
|
|
|
###
|
|
### Features
|
|
###
|
|
|
|
feature.extend toolset : cray ;
|
|
|
|
# Typically, extending '<toolset>' with the value 'cray' would cause
|
|
# 'cray' to be the default '<toolset>' as long as it is the first value
|
|
# added to '<toolset>'. However, we already imported the 'gcc' toolset, so
|
|
# 'cray' is not the first value added to '<toolset>'. Therefore, we need
|
|
# to call 'feature.set-default'.
|
|
#
|
|
# If the build request specifies a '<toolset>' (e.g. on the command line),
|
|
# then the '<toolset>' feature default is ignored. However, if the 'cray'
|
|
# toolset is selected in 'user-config.jam' (e.g. with 'using cray ;'),
|
|
# then the build request will use the '<toolset>' feature default.
|
|
# Therefore, we must use 'feature.set-default' so that selecting the
|
|
# 'cray' toolset in 'user-config.jam' works correctly.
|
|
|
|
feature.set-default toolset : cray ;
|
|
|
|
# CCE is different from other compilers in that it optimizes, inlines, and
|
|
# vectorizes by default. B2 assumes that 'off' is the default for
|
|
# all compilers. However, for CCE, 'off' and 'default' have different
|
|
# meanings. For CCE, 'off' requires an additional command line argument to
|
|
# turn the feature off. 'default' will not include an additional command
|
|
# line argument, but will do optimization, inlining, and vectorizing at
|
|
# whatever default level CCE uses.
|
|
|
|
feature.extend optimization : default ;
|
|
feature.extend inlining : default ;
|
|
feature.extend vectorize : default ;
|
|
|
|
###
|
|
### Flags
|
|
###
|
|
|
|
# Updating rules are named in a dotted hierarchy. For example:
|
|
#
|
|
# compile
|
|
# \_ compile.c++
|
|
# \_ compile.c++.preprocess
|
|
# \_ compile.c
|
|
# \_ compile.c.preprocess
|
|
#
|
|
# This naming convention allows us to apply flags to multiple children in
|
|
# the hierarchy. For example, if we apply a flag to 'compile.c++', that
|
|
# flag is also applied to its child 'compile.c++.preprocess'. If we apply
|
|
# a flag to 'compile', then that flag is applied to all children under
|
|
# 'compile'.
|
|
|
|
toolset.flags cray.compile OPTIONS <link>shared : -h pic ;
|
|
|
|
toolset.flags cray.compile OPTIONS <optimization>default ; # Blank.
|
|
toolset.flags cray.compile OPTIONS <optimization>off : -O 0 ;
|
|
toolset.flags cray.compile OPTIONS <optimization>speed : -O 3 ;
|
|
toolset.flags cray.compile OPTIONS <optimization>space ; # Blank. CCE does not optimize for space.
|
|
|
|
toolset.flags cray.compile OPTIONS <inlining>default ; # Blank.
|
|
toolset.flags cray.compile OPTIONS <inlining>off : -h ipa0 ;
|
|
toolset.flags cray.compile OPTIONS <inlining>on ; # Blank. CCE does inlining by default.
|
|
toolset.flags cray.compile OPTIONS <inlining>full : -h ipa5 ;
|
|
|
|
toolset.flags cray.compile OPTIONS <vectorize>default ; # Blank.
|
|
toolset.flags cray.compile OPTIONS <vectorize>off : -h vector0 ;
|
|
toolset.flags cray.compile OPTIONS <vectorize>on ; # Blank. CCE vectorizes by default.
|
|
toolset.flags cray.compile OPTIONS <vectorize>full : -h vector3 ;
|
|
|
|
toolset.flags cray.link FINDLIBS-SA <threading>multi : rt ; # Not sure if this is correct.
|
|
|
|
toolset.flags cray.link OPTIONS <link>shared : -h pic ;
|
|
|
|
{
|
|
#
|
|
# Link flags copied from 'gcc.jam'.
|
|
#
|
|
|
|
local toolset = cray ;
|
|
local generic-os = [ set.difference [ feature.values <target-os> ] : aix darwin vxworks solaris osf hpux ] ;
|
|
# Strip the binary when no debugging is needed. We use --strip-all flag
|
|
# as opposed to -s since icc (intel's compiler) is generally
|
|
# option-compatible with and inherits from the gcc toolset, but does not
|
|
# support -s.
|
|
toolset.flags $(toolset).link OPTIONS <target-os>$(generic-os)/<strip>on : -Wl,--strip-all ;
|
|
toolset.flags $(toolset).link RPATH <target-os>$(generic-os) : <dll-path> ;
|
|
toolset.flags $(toolset).link RPATH_OPTION <target-os>$(generic-os) : -rpath ;
|
|
toolset.flags $(toolset).link RPATH_LINK <target-os>$(generic-os) : <xdll-path> ;
|
|
toolset.flags $(toolset).link START-GROUP <target-os>$(generic-os) : -Wl,--start-group ;
|
|
toolset.flags $(toolset).link END-GROUP <target-os>$(generic-os) : -Wl,--end-group ;
|
|
|
|
# gnu ld has the ability to change the search behaviour for libraries
|
|
# referenced by the -l switch. These modifiers are -Bstatic and
|
|
# -Bdynamic and change search for -l switches that follow them. The
|
|
# following list shows the tried variants. Search stops at the first
|
|
# variant that has a match.
|
|
#
|
|
# *nix: -Bstatic -lxxx
|
|
# libxxx.a
|
|
#
|
|
# *nix: -Bdynamic -lxxx
|
|
# libxxx.so
|
|
# libxxx.a
|
|
#
|
|
# windows (mingw, cygwin) -Bstatic -lxxx
|
|
# libxxx.a
|
|
# xxx.lib
|
|
#
|
|
# windows (mingw, cygwin) -Bdynamic -lxxx
|
|
# libxxx.dll.a
|
|
# xxx.dll.a
|
|
# libxxx.a
|
|
# xxx.lib
|
|
# cygxxx.dll (*)
|
|
# libxxx.dll
|
|
# xxx.dll
|
|
# libxxx.a
|
|
#
|
|
# (*) This is for cygwin
|
|
# Please note that -Bstatic and -Bdynamic are not a guarantee that a
|
|
# static or dynamic lib indeed gets linked in. The switches only change
|
|
# search patterns!
|
|
|
|
# On *nix mixing shared libs with static runtime is not a good idea.
|
|
toolset.flags $(toolset).link FINDLIBS-ST-PFX <target-os>$(generic-os)/<runtime-link>shared : -Wl,-Bstatic ;
|
|
toolset.flags $(toolset).link FINDLIBS-SA-PFX <target-os>$(generic-os)/<runtime-link>shared : -Wl,-Bdynamic ;
|
|
|
|
toolset.flags $(toolset).link HAVE_SONAME <target-os>$(generic-os) : "" ;
|
|
toolset.flags $(toolset).link SONAME_OPTION <target-os>$(generic-os) : -h ;
|
|
|
|
# See note [1]
|
|
toolset.flags $(toolset).link OPTIONS <target-os>$(generic-os)/<runtime-link>static : -static ;
|
|
|
|
# [1]
|
|
# For <runtime-link>static we made sure there are no dynamic libraries in the
|
|
# link. On HP-UX not all system libraries exist as archived libraries (for
|
|
# example, there is no libunwind.a), so, on this platform, the -static option
|
|
# cannot be specified.
|
|
}
|
|
|
|
# Flags for 'free' features ('free' features are features that do not have
|
|
# a pre-defined set of values).
|
|
|
|
toolset.flags cray.compile USER_OPTIONS <cflags> ;
|
|
toolset.flags cray.compile.c++ USER_OPTIONS <cxxflags> ;
|
|
toolset.flags cray.compile.asm USER_OPTIONS <asmflags> ;
|
|
toolset.flags cray.compile DEFINES <define> ;
|
|
toolset.flags cray.compile INCLUDES <include> ;
|
|
|
|
toolset.flags cray.link USER_OPTIONS <linkflags> ;
|
|
toolset.flags cray.link LINKPATH <library-path> ;
|
|
toolset.flags cray.link FINDLIBS-ST <find-static-library> ;
|
|
toolset.flags cray.link FINDLIBS-SA <find-shared-library> ;
|
|
toolset.flags cray.link LIBRARIES <library-file> ;
|
|
|
|
toolset.flags cray.archive AROPTIONS <archiveflags> ;
|
|
|
|
###
|
|
### Actions
|
|
###
|
|
|
|
actions compile.c++
|
|
{
|
|
"$(CONFIG_COMMAND_CXX)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -c -o "$(<)" "$(>)" $(DRIVER_OPTIONS)
|
|
}
|
|
|
|
actions compile.c
|
|
{
|
|
"$(CONFIG_COMMAND_C)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -c -o "$(<)" "$(>)" $(DRIVER_OPTIONS)
|
|
}
|
|
|
|
actions compile.asm
|
|
{
|
|
"$(CONFIG_COMMAND_CXX)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -c -o "$(<)" "$(>)" $(DRIVER_OPTIONS)
|
|
}
|
|
|
|
actions compile.c++.preprocess
|
|
{
|
|
"$(CONFIG_COMMAND_CXX)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -E "$(>)" >"$(<)" $(DRIVER_OPTIONS)
|
|
}
|
|
|
|
actions compile.c.preprocess
|
|
{
|
|
"$(CONFIG_COMMAND_C)" $(OPTIONS) $(USER_OPTIONS) -D$(SPACE)$(DEFINES) -I$(SPACE)"$(INCLUDES)" -E "$(>)" >"$(<)" $(DRIVER_OPTIONS)
|
|
}
|
|
|
|
# We don't want to invoke 'ld' (the linker) directly for 'link', since we
|
|
# want to give the CCE compiler driver a chance to modify the command line
|
|
# it passes to 'ld'.
|
|
#
|
|
# The question is: which CCE compiler driver do we use? The driver for C,
|
|
# the driver for C++, or the driver for Fortran?
|
|
#
|
|
# Here are things that definitely do not work:
|
|
#
|
|
# - Using the driver for C doesn't work when linking C++ programs, because
|
|
# things like 'std::cout' are not available in C, they are only
|
|
# available in C++.
|
|
#
|
|
# We use the driver for C++ below since we are primarily interested in
|
|
# compiling Boost, which is written in C++. Also, the C++ driver will
|
|
# properly link C code as well.
|
|
|
|
actions link bind LIBRARIES
|
|
{
|
|
"$(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)
|
|
}
|
|
|
|
actions link.dll bind LIBRARIES
|
|
{
|
|
"$(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)
|
|
}
|
|
|
|
actions piecemeal archive
|
|
{
|
|
"$(.AR)" $(AROPTIONS) rsc "$(<)" "$(>)"
|
|
}
|
|
|
|
###
|
|
### Updating rules
|
|
###
|
|
|
|
# These are the actual updating rules that apply the associated actions
|
|
# when called.
|
|
|
|
rule compile.c++ ( targets * : sources * : properties * )
|
|
{
|
|
compile-c++-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule compile.c ( targets * : sources * : properties * )
|
|
{
|
|
compile-c-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule compile.asm ( targets * : sources * : properties * )
|
|
{
|
|
compile-asm-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule compile.c++.preprocess ( targets * : sources * : properties * )
|
|
{
|
|
compile-c++-preprocess-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule compile.c.preprocess ( targets * : sources * : properties * )
|
|
{
|
|
compile-c-preprocess-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule link ( targets * : sources * : properties * )
|
|
{
|
|
link-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule link.dll ( targets * : sources * : properties * )
|
|
{
|
|
link-dll-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule archive ( targets * : sources * : properties * )
|
|
{
|
|
archive-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
# These are the procedure portions of the updating rules. Calling the
|
|
# procedure portion may modify the targets, but it will not apply actions
|
|
# to the targets. This allows us to reuse the procedure portions of the
|
|
# updating rules without applying the same actions to targets.
|
|
|
|
rule compile-c++-procedure ( targets * : sources * : properties * )
|
|
{
|
|
set-cxxstd-procedure $(targets) : $(sources) : $(properties) ;
|
|
set-cxxstd-dialect-procedure $(targets) : $(sources) : $(properties) ;
|
|
set-debug-symbols-procedure $(targets) : $(sources) : $(properties) ;
|
|
add-space-procedure $(targets) : $(sources) : $(properties) ;
|
|
debug-driver-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule compile-c-procedure ( targets * : sources * : properties * )
|
|
{
|
|
set-debug-symbols-procedure $(targets) : $(sources) : $(properties) ;
|
|
add-space-procedure $(targets) : $(sources) : $(properties) ;
|
|
debug-driver-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule compile-asm-procedure ( targets * : sources * : properties * )
|
|
{
|
|
compile-c++-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule compile-c++-preprocess-procedure ( targets * : sources * : properties * )
|
|
{
|
|
compile-c++-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule compile-c-preprocess-procedure ( targets * : sources * : properties * )
|
|
{
|
|
compile-c-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
rule link-procedure ( targets * : sources * : properties * )
|
|
{
|
|
set-cxxstd-procedure $(targets) : $(sources) : $(properties) ;
|
|
set-cxxstd-dialect-procedure $(targets) : $(sources) : $(properties) ;
|
|
gcc-link-procedure $(targets) : $(sources) : $(properties) ;
|
|
debug-driver-procedure $(targets) : $(sources) : $(properties) ;
|
|
|
|
# CCE driver command line flags for linking executables.
|
|
|
|
local link = [ feature.get-values <link> : $(properties) ] ;
|
|
switch $(link)
|
|
{
|
|
case shared :
|
|
DRIVER_OPTIONS on $(<) += -dynamic ;
|
|
case static :
|
|
DRIVER_OPTIONS on $(<) += -static ;
|
|
}
|
|
|
|
# The link command line from the 'gcc' toolset includes:
|
|
#
|
|
# '$(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA)'
|
|
#
|
|
# The 'FINDLIBS-ST' and 'FINDLIBS-SA' variables are the libraries
|
|
# specified by the '<find-static-library>' and '<find-shared-library>'
|
|
# features, respectively. The 'FINDLIBS-ST-PFX' is typically
|
|
# '-Wl,-Bstatic'. The 'FINDLIBS-SA-PFX' is typically '-Wl,-Bdynamic'.
|
|
#
|
|
# The '-Bstatic' and '-Bdynamic' flags passed to the linker tell the
|
|
# linker how to link all of the following libraries. The flag is in effect
|
|
# until it is overridden by another '-B' flag on the command line.
|
|
#
|
|
# So, it makes sense that the 'gcc' toolset includes these flags, so the
|
|
# '<find-static-library>' and '<find-shared-library>' libraries are linked
|
|
# properly.
|
|
#
|
|
# The last flag that is set ('-Bdynamic') affects the link type for any
|
|
# other libraries on the command line. In the 'gcc' toolset, this is okay,
|
|
# since there are no other libraries specified on the command line after
|
|
# these flags. However, when the CCE compiler driver invokes the linker,
|
|
# it adds additional libraries to the command line based on what modules
|
|
# are loaded in the environment. So, the last '-B' flag on the CCE driver
|
|
# command line affects the link type for all libraries that CCE
|
|
# automatically appends.
|
|
#
|
|
# Therefore, we have to set the final '-B' flag to the link type we want
|
|
# the CCE libraries to be linked with. Appending to the 'OPTIONS' variable
|
|
# seems reasonable.
|
|
|
|
local link = [ feature.get-values <link> : $(properties) ] ;
|
|
switch $(link)
|
|
{
|
|
case shared :
|
|
OPTIONS on $(<) += -Wl,-Bdynamic ;
|
|
case static :
|
|
OPTIONS on $(<) += -Wl,-Bstatic ;
|
|
}
|
|
}
|
|
|
|
rule link-dll-procedure ( targets * : sources * : properties * )
|
|
{
|
|
set-cxxstd-procedure $(targets) : $(sources) : $(properties) ;
|
|
set-cxxstd-dialect-procedure $(targets) : $(sources) : $(properties) ;
|
|
gcc-link-dll-procedure $(targets) : $(sources) : $(properties) ;
|
|
debug-driver-procedure $(targets) : $(sources) : $(properties) ;
|
|
|
|
# CCE driver command line flags for linking shared libraries.
|
|
|
|
DRIVER_OPTIONS on $(<) += -shared ;
|
|
}
|
|
|
|
rule archive-procedure ( targets * : sources * : properties * )
|
|
{
|
|
gcc-archive-procedure $(targets) : $(sources) : $(properties) ;
|
|
debug-driver-procedure $(targets) : $(sources) : $(properties) ;
|
|
}
|
|
|
|
# Utility procedure rules intended to be called from updating rules.
|
|
|
|
rule gcc-link-procedure ( targets * : sources * : properties * )
|
|
{
|
|
|
|
# Copied from 'gcc.jam'.
|
|
|
|
SPACE on $(targets) = " " ;
|
|
gcc.quote-rpath $(targets) ;
|
|
}
|
|
|
|
rule gcc-link-dll-procedure ( targets * : sources * : properties * )
|
|
{
|
|
|
|
# Copied from 'gcc.jam'.
|
|
|
|
SPACE on $(targets) = " " ;
|
|
gcc.quote-rpath $(targets) ;
|
|
}
|
|
|
|
rule gcc-archive-procedure ( targets * : sources * : properties * )
|
|
{
|
|
|
|
# Copied from 'gcc.jam'.
|
|
|
|
# Always remove archive and start again. Here is the rationale from
|
|
#
|
|
# Andre Hentz:
|
|
#
|
|
# I had a file, say a1.c, that was included into liba.a. I moved a1.c to
|
|
# a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd
|
|
# errors. After some debugging I traced it back to the fact that a1.o was
|
|
# *still* in liba.a
|
|
#
|
|
# Rene Rivera:
|
|
#
|
|
# Originally removing the archive was done by splicing an RM onto the
|
|
# archive action. That makes archives fail to build on NT when they have
|
|
# many files because it will no longer execute the action directly and blow
|
|
# the line length limit. Instead we remove the file in a different action,
|
|
# just before building the archive.
|
|
#
|
|
local clean.a = $(targets[1])(clean) ;
|
|
TEMPORARY $(clean.a) ;
|
|
NOCARE $(clean.a) ;
|
|
LOCATE on $(clean.a) = [ on $(targets[1]) return $(LOCATE) ] ;
|
|
DEPENDS $(clean.a) : $(sources) ;
|
|
DEPENDS $(targets) : $(clean.a) ;
|
|
common.RmTemps $(clean.a) : $(targets) ;
|
|
}
|
|
|
|
rule add-space-procedure ( targets * : sources * : properties * )
|
|
{
|
|
SPACE on $(targets) = " " ;
|
|
}
|
|
|
|
rule set-cxxstd-procedure ( targets * : sources * : properties * )
|
|
{
|
|
|
|
# Translate '<cxxstd>' into a standard recognized by CCE.
|
|
|
|
local version = [ on $(targets[1]) return $(VERSION) ] ;
|
|
|
|
local cxxstd = [ feature.get-values cxxstd : $(properties) ] ;
|
|
local cray-cxxstd = ;
|
|
|
|
local unsupported-values = 2a 20 ; # I don't know what '2a' means.
|
|
if $(cxxstd) && $(cxxstd) in $(unsupported-values)
|
|
{
|
|
|
|
log-warning cray : ignoring unsupported property '<cxxstd>$(cxxstd)' ;
|
|
|
|
# Set to default value, or blank if default is unsupported.
|
|
|
|
local default-value = [ get-default-feature-value cxxstd ] ;
|
|
if $(default-value) in $(unsupported-values)
|
|
{
|
|
cxxstd = ;
|
|
}
|
|
else
|
|
{
|
|
cxxstd = $(default-value) ;
|
|
}
|
|
}
|
|
|
|
switch $(cxxstd)
|
|
{
|
|
case 98 : cray-cxxstd = 03 ;
|
|
case 03 : cray-cxxstd = 03 ;
|
|
case 0x : cray-cxxstd = 11 ;
|
|
case 11 : cray-cxxstd = 11 ;
|
|
case 1y : cray-cxxstd = 14 ;
|
|
case 14 : cray-cxxstd = 14 ;
|
|
case 1z : cray-cxxstd = 17 ;
|
|
case 17 : cray-cxxstd = 17 ;
|
|
case latest :
|
|
cray-cxxstd = [ latest-cray-cxxstd $(version) ] ;
|
|
}
|
|
|
|
# If the 'cray-cxxstd' is not supported by this compiler version, we just
|
|
# let the command line fail.
|
|
|
|
# If 'cxxstd' was blank, then 'cray-cxxstd' is also blank, and nothing is
|
|
# added to the command line. The compiler just uses it's default C++
|
|
# standard.
|
|
|
|
# Apply final options.
|
|
local space = " " ;
|
|
OPTIONS on $(targets) += -h$(space)std=c++$(cray-cxxstd) ;
|
|
}
|
|
|
|
rule set-cxxstd-dialect-procedure ( targets * : sources * : properties * )
|
|
{
|
|
|
|
# Translate '<cxxstd-dialect>' into '-h [no]conform' and '-h [no]gnu'
|
|
# options.
|
|
|
|
local version = [ on $(targets[1]) return $(VERSION) ] ;
|
|
|
|
local cxxstd-dialect = [ feature.get-values cxxstd-dialect : $(properties) ] ;
|
|
local cray-conform = ;
|
|
local cray-gnu = ;
|
|
|
|
local unsupported-values = ms ;
|
|
if $(cxxstd-dialect) && $(cxxstd-dialect) in $(unsupported-values)
|
|
{
|
|
|
|
log-warning cray : ignoring unsupported property '<cxxstd-dialect>$(cxxstd-dialect)' ;
|
|
|
|
# Set to default value, or blank if default is unsupported.
|
|
|
|
local default-value = [ get-default-feature-value cxxstd-dialect ] ;
|
|
if $(default-value) in $(unsupported-values)
|
|
{
|
|
cxxstd-dialect = ;
|
|
}
|
|
else
|
|
{
|
|
cxxstd-dialect = $(default-value) ;
|
|
}
|
|
}
|
|
|
|
switch $(cxxstd-dialect)
|
|
{
|
|
case gnu : cray-conform = noconform ;
|
|
cray-gnu = gnu ;
|
|
case iso : cray-conform = conform ;
|
|
cray-gnu = nognu ;
|
|
}
|
|
|
|
if [ has-conform-option $(version) ] = false
|
|
{
|
|
# The '-h [no]conform' option is ignored in recent versions of CCE.
|
|
cray-conform = ;
|
|
}
|
|
|
|
# If 'cxxstd-dialect' was blank, then 'cray-conform' and 'cray-gnu' are
|
|
# also blank, and nothing is added to the command line. The compiler just
|
|
# uses it's default C++ dialect.
|
|
|
|
# Apply final options.
|
|
local space = " " ;
|
|
OPTIONS on $(targets) += -h$(space)$(cray-conform)
|
|
-h$(space)$(cray-gnu) ;
|
|
}
|
|
|
|
rule set-debug-symbols-procedure ( targets * : sources * : properties * )
|
|
{
|
|
|
|
local debug-symbols = [ feature.get-values <debug-symbols> : $(properties) ] ;
|
|
if $(debug-symbols) = "on"
|
|
{
|
|
local optimization = [ feature.get-values <optimization> : $(properties) ] ;
|
|
local debug-option = ;
|
|
if $(optimization) = off
|
|
{
|
|
debug-option = 0 ;
|
|
}
|
|
else
|
|
{
|
|
debug-option = 3 ;
|
|
}
|
|
|
|
local space = " " ;
|
|
OPTIONS on $(targets) += -G$(space)$(debug-option) ;
|
|
}
|
|
}
|
|
|
|
rule debug-driver-procedure ( targets * : sources * : properties * )
|
|
{
|
|
if $(.debug-driver)
|
|
{
|
|
|
|
# Passing '-vv' to the CCE driver causes it to output the command lines
|
|
# for the underlying tools that it invokes.
|
|
|
|
DRIVER_OPTIONS on $(<) += -vv ;
|
|
}
|
|
}
|
|
|
|
###
|
|
### Generators
|
|
###
|
|
|
|
class cray-linking-generator : gcc-linking-generator
|
|
{
|
|
rule action-class ( )
|
|
{
|
|
return action ;
|
|
}
|
|
}
|
|
|
|
# We reuse some generator classes from the 'unix' toolset. Specifically,
|
|
# we are reusing generators for the following updating actions:
|
|
#
|
|
# - 'archive'
|
|
# - 'searched-lib-generator'
|
|
# - 'prebuilt'
|
|
#
|
|
# Inheriting these generators is like using the same generator classes as
|
|
# the 'unix' toolset, but pointing them to the 'cray' updating rules.
|
|
|
|
toolset.inherit-generators cray : unix : unix.link unix.link.dll ;
|
|
|
|
# The 'C-compiling-generator' class adds source paths to the '<include>'
|
|
# property.
|
|
|
|
generators.register [ new C-compiling-generator
|
|
cray.compile.c++
|
|
: CPP
|
|
: OBJ
|
|
: <toolset>cray ] ;
|
|
generators.register [ new C-compiling-generator
|
|
cray.compile.c
|
|
: C
|
|
: OBJ
|
|
: <toolset>cray ] ;
|
|
generators.register [ new C-compiling-generator
|
|
cray.compile.asm
|
|
: ASM
|
|
: OBJ
|
|
: <toolset>cray ] ;
|
|
generators.register [ new C-compiling-generator
|
|
cray.compile.c++.preprocess
|
|
: CPP
|
|
: PREPROCESSED_CPP
|
|
: <toolset>cray ] ;
|
|
generators.register [ new C-compiling-generator
|
|
cray.compile.c.preprocess
|
|
: C
|
|
: PREPROCESSED_C
|
|
: <toolset>cray ] ;
|
|
generators.register [ new cray-linking-generator
|
|
cray.link
|
|
: LIB OBJ
|
|
: EXE
|
|
: <toolset>cray ] ;
|
|
generators.register [ new cray-linking-generator
|
|
cray.link.dll
|
|
: LIB OBJ
|
|
: SHARED_LIB
|
|
: <toolset>cray ] ;
|
|
|
|
# Tell B2 to prefer 'cray' generators over other valid
|
|
# generators. This is used to resolve a tie when B2 finds that
|
|
# there is more than one viable generator for a particular build request.
|
|
|
|
generators.override cray.prebuilt : builtin.prebuilt ;
|
|
generators.override cray.searched-lib-generator : searched-lib-generator ;
|
|
|
|
type.set-generated-target-suffix PREPROCESSED_CPP : <toolset>cray : i ;
|
|
type.set-generated-target-suffix PREPROCESSED_C : <toolset>cray : i ;
|
|
|
|
###
|
|
### Utility rules
|
|
###
|
|
|
|
rule validate-command ( toolset command )
|
|
{
|
|
local found-command = [ common.find-tool $(command) ] ;
|
|
if $(found-command) && $(.debug-configuration)
|
|
{
|
|
log-notice $(toolset) : command '$(command)' found at [ common.get-absolute-tool-path $(found-command) ] ;
|
|
}
|
|
if ! $(found-command)
|
|
{
|
|
log-warning $(toolset) : command '$(command)' not found ;
|
|
found-command = $(command) ;
|
|
}
|
|
return $(found-command) ;
|
|
}
|
|
|
|
local rule options-helper ( rule-or-module variable-name condition * : feature options * )
|
|
{
|
|
toolset.flags $(rule-or-module) $(variable-name) $(condition) : [ feature.get-values $(feature) : $(options) ] : unchecked ;
|
|
}
|
|
|
|
rule handle-options (
|
|
toolset
|
|
: toolset-condition *
|
|
: command-c command-cxx command-fortran command-ar
|
|
: options *
|
|
)
|
|
{
|
|
|
|
# Configures some common 'toolset.flags' options. In particular, this rule
|
|
# sets the compiler command name to invoke. Inspired by
|
|
# 'common.handle-options'.
|
|
|
|
# We cannot use a single 'CONFIG_COMMAND' variable because each CCE driver
|
|
# can only handle a single source code language. Therefore, we have to
|
|
# give actions a way to specify which driver they intend to use, and we
|
|
# accomplish this by providing multiple 'CONFIG_COMMAND' variables to the
|
|
# action. We cannot set the language through a flag in the 'OPTIONS'
|
|
# variable the way the 'gcc' toolset does.
|
|
|
|
toolset.flags $(toolset) CONFIG_COMMAND_C $(toolset-condition) : $(command-c) : unchecked ;
|
|
toolset.flags $(toolset) CONFIG_COMMAND_CXX $(toolset-condition) : $(command-cxx) : unchecked ;
|
|
toolset.flags $(toolset) CONFIG_COMMAND_FORTRAN $(toolset-condition) : $(command-fortran) : unchecked ;
|
|
toolset.flags $(toolset).archive .AR $(toolset-condition) : $(command-ar) : unchecked ;
|
|
|
|
# The following flags are applied to all targets built by this
|
|
# configuration of this toolset. This particular configuration of this
|
|
# toolset is identified by '$(toolset-condition)'. This allows the user to
|
|
# specify 'options' in their 'using' statement, and those options will be
|
|
# applied to all targets built by this configuration of this toolset.
|
|
|
|
options-helper $(toolset).compile USER_OPTIONS $(toolset-condition) : <compileflags> $(options) ;
|
|
options-helper $(toolset).compile USER_OPTIONS $(toolset-condition) : <cflags> $(options) ;
|
|
options-helper $(toolset).compile.c++ USER_OPTIONS $(toolset-condition) : <cxxflags> $(options) ;
|
|
options-helper $(toolset).compile.fortran USER_OPTIONS $(toolset-condition) : <fflags> $(options) ;
|
|
options-helper $(toolset).compile.asm USER_OPTIONS $(toolset-condition) : <asmflags> $(options) ;
|
|
options-helper $(toolset).compile DEFINES $(toolset-condition) : <define> $(options) ;
|
|
options-helper $(toolset).compile INCLUDES $(toolset-condition) : <include> $(options) ;
|
|
|
|
options-helper $(toolset).link USER_OPTIONS $(toolset-condition) : <linkflags> $(options) ;
|
|
options-helper $(toolset).link LINKPATH $(toolset-condition) : <library-path> $(options) ;
|
|
options-helper $(toolset).link FINDLIBS-ST $(toolset-condition) : <find-static-library> $(options) ;
|
|
options-helper $(toolset).link FINDLIBS-SA $(toolset-condition) : <find-shared-library> $(options) ;
|
|
options-helper $(toolset).link LIBRARIES $(toolset-condition) : <library-file> $(options) ;
|
|
|
|
options-helper $(toolset).archive AROPTIONS $(toolset-condition) : <archiveflags> $(options) ;
|
|
}
|
|
|
|
rule latest-cray-cxxstd ( compiler-version )
|
|
{
|
|
# Select latest 'cray-cxxstd' based on compiler version.
|
|
|
|
local cray-cxxstd = 03 ;
|
|
|
|
if $(compiler-version) >= [ numeric-version 8.6 ]
|
|
{
|
|
cray-cxxstd = 14 ;
|
|
}
|
|
|
|
return $(cray-cxxstd) ;
|
|
}
|
|
|
|
rule has-conform-option ( compiler-version )
|
|
{
|
|
|
|
# Returns 'true' or 'false'. Returns empty list if the 'compiler-version'
|
|
# is not supported.
|
|
|
|
local result = true ;
|
|
|
|
if $(compiler-version) >= [ numeric-version 8.6 ]
|
|
{
|
|
result = false ;
|
|
}
|
|
|
|
return $(result) ;
|
|
}
|
|
|
|
local rule justify-right ( pad-char elements * )
|
|
{
|
|
|
|
# Returns a list of 'elements' where each 'element' is at least 2
|
|
# characters long. If an 'element' is less than two characters long, pads
|
|
# 'element' with 'pad-char' to make it 2 characters long.
|
|
|
|
local result = ;
|
|
local p = $(pad-char) ;
|
|
for local e in $(elements)
|
|
{
|
|
switch $(e)
|
|
{
|
|
case ?? : result += $(e) ;
|
|
case ? : result += $(p)$(e) ;
|
|
case * : result += $(p)$(p) ;
|
|
}
|
|
}
|
|
return $(result) ;
|
|
}
|
|
|
|
local rule list-justify-left ( pad-elem elements * )
|
|
{
|
|
|
|
# Add 'pad-elem' to 'elements' list until it has 4 elements. If 'elements'
|
|
# list already had 4 or more elements, returns the first 4 elements in
|
|
# 'elements' list.
|
|
|
|
local tally = x ;
|
|
local result = ;
|
|
for local e in $(elements)
|
|
{
|
|
if $(tally) != xxxxx
|
|
{
|
|
result += $(e) ;
|
|
tally = $(tally)x ;
|
|
}
|
|
}
|
|
|
|
while $(tally) != xxxxx
|
|
{
|
|
result += $(pad-elem) ;
|
|
tally = $(tally)x ;
|
|
}
|
|
|
|
return $(result) ;
|
|
}
|
|
|
|
local rule numeric-version ( dotted-version )
|
|
{
|
|
|
|
# Returns a numeric representation of version that can be compared
|
|
# directly with comparison operators.
|
|
|
|
local result = [ regex.split $(dotted-version) "[.]" ] ;
|
|
result = [ list-justify-left 0 $(result) ] ;
|
|
result = [ justify-right 0 $(result) ] ;
|
|
result = $(result:J="") ;
|
|
|
|
return $(result) ;
|
|
}
|
|
|
|
local rule get-default-feature-value ( feature-name )
|
|
{
|
|
local default-property = [ feature.defaults $(feature-name) ] ;
|
|
local default-value = [ feature.get-values $(feature-name) : $(default-property) ] ;
|
|
return $(default-value) ;
|
|
}
|
|
|
|
rule log ( log-level prefix ? : * )
|
|
{
|
|
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
|
|
{
|
|
local message = $($(message-arg)) ;
|
|
if $(message)
|
|
{
|
|
ECHO "$(log-level):" "$(prefix):" $(message) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
rule log-error ( prefix ? : * )
|
|
{
|
|
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) ;
|
|
}
|
|
|
|
rule log-warning ( prefix ? : * )
|
|
{
|
|
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) ;
|
|
}
|
|
|
|
rule log-notice ( prefix ? : * )
|
|
{
|
|
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) ;
|
|
}
|
|
|
|
rule __test__ ( )
|
|
{
|
|
import assert ;
|
|
|
|
assert.result 08060000 : numeric-version 8.6 ;
|
|
assert.result 08061500 : numeric-version 8.6.15 ;
|
|
assert.result 08061501 : numeric-version 8.6.15.1 ;
|
|
assert.result 08061501 : numeric-version 8.6.15.1.2 ;
|
|
|
|
local a = [ numeric-version 8.6 ] ;
|
|
local b = [ numeric-version 8.5.9 ] ;
|
|
|
|
# 'assert.equal x : y' forces the test to fail. It's like saying 'assert
|
|
# false'.
|
|
|
|
if ! ( $(a) > $(b) )
|
|
{
|
|
assert.equal x : y ;
|
|
}
|
|
|
|
if ! ( $(b) < $(a) )
|
|
{
|
|
assert.equal x : y ;
|
|
}
|
|
|
|
if ! ( $(a) >= $(b) )
|
|
{
|
|
assert.equal x : y ;
|
|
}
|
|
|
|
if ! ( $(a) >= $(a) )
|
|
{
|
|
assert.equal x : y ;
|
|
}
|
|
|
|
if ! ( $(b) <= $(a) )
|
|
{
|
|
assert.equal x : y ;
|
|
}
|
|
|
|
if ! ( $(b) <= $(b) )
|
|
{
|
|
assert.equal x : y ;
|
|
}
|
|
|
|
if ! ( $(a) = $(a) )
|
|
{
|
|
assert.equal x : y ;
|
|
}
|
|
|
|
if ! ( $(a) != $(b) )
|
|
{
|
|
assert.equal x : y ;
|
|
}
|
|
}
|