Home | Libraries | People | FAQ | More |
The CXXD library offers support for build systems.
Sometimes during a build it is necessary to know whether or not a particular mod uses the Boost implementation or the C++ standard library implementation for the compiler being used during a build. This could be because, depending on the dual library implementation chosen, a library needs to be linked or an include path needs to be added or a define needs to be made or for any number of other practical build-type reasons.
CXXD offers support for the Boost Build system specifically or for other build systems in general. This topic explains that support.
CXXD has build-time support for Boost Build so that depending on whether a particular mod uses the Boost implementation or the C++ standard library implementation, a requirement or usage requirement can be set in a Boost Build rule. Among the useful built-in rules where this functionality can be used are the run, compile, link, exe, and lib rules; but any rule which allows the addition of requirements or usage requirements can be used.
CXXD implements this support by its own Boost Build rules, which can be used to conditionally set requirements depending on whether or not specific mods use the Boost implementation or the C++ standard implementation.
The first thing an end-user of CXXD needs to do to use this functionality is to import the CXXD Boost build support module. This module is in a CXXD subdirectory called 'checks' in a jam file called 'cxxd'. So to import the Boost build support module the the end-user adds to his own jamfile:
import path_to_cxxd_library/checks/cxxd ;
Within the 'cxxd' jam file are three different rules the end-user can use, all taking the same Boost Build parameters. These rules are:
Each rule takes, as a first parameter, a list of one or more names which identify mods. For the first two rules, 'cxxd.requires.boost' and 'cxxd.requires.std', these names are the the mods identifying a particular mod. As an example 'regex' identifies the regex mod. For the third rule above, 'cxxd.requires.specify', these names are also the mods identifying a particular CXXD_mod, but are followed by a comma ( ',' ) and then 0 to indicate Boost or 1 to indicate the C++ standard. As examples 'regex,0' identifies the regex mod with Boost chosen while 'tuple,1' identifies the tuple mod with the C++ standard chosen.
Essentially the first parameter of 'cxxd.requires.boost' is a shorthand for passing each mod followed by a comma ( ',' ) and then 0 in 'cxxd.requires.specify' while the first parameter of 'cxxd.requires.std' is a shorthand for passing each mod followed by a comma ( ',' ) and then 1 in 'cxxd.requires.specify'.
Each rule takes, as an optional second parameter, 0 or more Boost Build requirement or usage requirements.
Each rule takes, as an optional third parameter, 0 or more Boost Build requirement or usage requirements.
A Boost Build requirement or usage requirement is a Boost Build feature.
The way that the 'cxxd.requires.boost' rule works is that if each of the mods specified use its Boost library implementation, the Boost Build requirements or usage requirements specified by the optional second parameter is chosen; otherwise the Boost Build requirements or usage requirements specified by the optional third parameter is chosen.
The way that the 'cxxd.requires.std' rule works is that if each of the mods specified use its C++ standard library implementation, the Boost Build requirements or usage requirements specified by the optional second parameter is chosen; otherwise the Boost Build requirements or usage requirements specified by the optional third parameter is chosen.
The way that the 'cxxd.requires.specific' rule works is that if each of the mods specified use whichever implementation is chosen through the 0 or 1 addition, the Boost Build requirements or usage requirements specified by the optional second parameter is chosen; otherwise the Boost Build requirements or usage requirements specified by the optional third parameter is chosen. The 'cxxd.requires.specific' rule gives maximum flexibility in matching each mod with the dual library implementation chosen.
When we use any of these rules we invoke them as:
cxxd.requires.boost mod... : optional_requirements_may_be_empty : optional_requirements_may_be_empty ; cxxd.requires.std mod... : optional_requirements_may_be_empty : optional_requirements_may_be_empty ; cxxd.requires.specific mod,0-or-1... : optional_requirements_may_be_empty : optional_requirements_may_be_empty ;
To use the results of these rules in one's own rules you surround these rule invocations in Boost Build with brackets and spaces ( ' [ ' and ' ] ' ).
As an example, taken directly from the CXXD tests for the CXXD regex implementation, we have:
run test_regex.cpp : : : [ cxxd.requires.boost regex : <library>/boost/regex//boost_regex ] ;
This says that when we build the test regex example if the Boost regex implementation is being chosen we want to link in the Boost regex library. As you can see it isn't necessary to specify both optional requirements when invoking the rule. The exact same effect could be coded as:
run test_regex.cpp : : : [ cxxd.requires.std regex : : <library>/boost/regex//boost_regex ] ;
or as:
run test_regex.cpp : : : [ cxxd.requires.specific regex,0 : <library>/boost/regex//boost_regex ] ;
or even as:
run test_regex.cpp : : : [ cxxd.requires.specific regex,1 : : <library>/boost/regex//boost_regex ] ;
We can have more than one mod as our first parameter to any of our three rules, although this is a less common scenario. Let's make up an arbitrary case just to show how this works. Let's say that when compiling our source file 'my_source.cpp' if CXXD is choosing both the Boost bind and the Boost function implementations we want to define a macro called MY_MACRO to 1, else we define MY_MACRO to 0. Here is what our Boost Build code for this would be:
compile my_source.cpp : [ cxxd.requires.boost bind function : <define>MY_MACRO=1 : <define>MY_MACRO=0 ] ;
We could have more than one feature as our requirements, as in:
compile my_source.cpp : [ cxxd.requires.boost bind function : <define>MY_MACRO=1 <include>some_directory_path : <define>MY_MACRO=0 ] ;
We could have more than one invocation of cxxd.requires.boost, cxxd.requires.std, or cxxd.requires.specific in our requirements or usage requirements section of a rule, as in:
compile my_source.cpp : [ cxxd.requires.boost bind function : <define>MY_MACRO=1 <include>some_directory_path : <define>MY_MACRO=0 ] [ cxxd.requires.std regex : : <library>/boost/regex//boost_regex ] [ cxxd.requires.specific tuple,1 : <cxxflags>-someflag ] ;
With the 'cxxd.requires.specific' rule we can mix Boost and C++ standard implementations to set our requirements, as in:
compile my_source.cpp : [ cxxd.requires.specific array,1 hash,0 : <include>some_path : <define>some_macro=some_value ] ;
Here we are saying that if the array mod uses the C++ standard implementation and the hash mod uses the Boost implementation, add 'some_path' to the include paths, else define a macro called 'some_macro' to 'some_value'.