Brian Silverman | 9d8fa39 | 2018-08-04 17:09:24 -0700 | [diff] [blame^] | 1 | |
| 2 | [section:build_config Build Time Configuration] |
| 3 | |
| 4 | There are times when you want to control whether a build target gets built or not, based |
| 5 | on what features the compiler supports. For example, suppose you have a test file |
| 6 | "test_constexpr_128.cpp" which requires three key features in order to build: |
| 7 | |
| 8 | * The `constexpr` keyword as detected by BOOST_NO_CXX11_CONSTEXPR. |
| 9 | * User defined literals, as detected by BOOST_NO_CXX11_USER_DEFINED_LITERALS. |
| 10 | * The `__int128` data type, as detected by BOOST_HAS_INT128. |
| 11 | |
| 12 | Clearly we know that if these features are not supported by the compiler, then |
| 13 | there's simply no point in even trying to build the test program. The main advantages being: |
| 14 | |
| 15 | * Faster compile times - build configuration uses lightweight tests the results of which are also cached. |
| 16 | * Less noise in build output - there's no reason to be faced with pages of template |
| 17 | instantiation backtrace if we know the file can never compile anyway. |
| 18 | * Less noise in the online test results - the test will show up as blank, rather than as a fail |
| 19 | in the online test matrix. |
| 20 | * A better experience for end users building all of Boost, if those libraries which can not be built |
| 21 | for the current target compiler are simply skipped, rather than generating pages of error output. |
| 22 | |
| 23 | Returning to our example, the test case is probably executed in it's Jamfile via the "run" rule: |
| 24 | |
| 25 | run test_constexpr_128.cpp ; |
| 26 | |
| 27 | We now need to make this target conditional on the necessary features. |
| 28 | We can do that by first importing the necessary rule at the start of the Jamfile: |
| 29 | |
| 30 | import path-to-config-lib/checks/config : requires ; |
| 31 | |
| 32 | Assuming that the test case is in the usual directory: |
| 33 | |
| 34 | libs/yourlib/test |
| 35 | |
| 36 | then the import rule will actually be: |
| 37 | |
| 38 | import ../../config/checks/config : requires ; |
| 39 | |
| 40 | Then add a "requires" rule invocation to the requirements section of the target: |
| 41 | |
| 42 | run test_constexpr_128.cpp |
| 43 | : : : #requirements: |
| 44 | [ requires cxx11_constexpr cxx11_user_defined_literals int128 ] ; |
| 45 | |
| 46 | Notice that multiple arguments can be added to the requires rule, and that these are |
| 47 | always the same as the Boost.Config macro name, but in lower case and with the ['boost_no_] |
| 48 | or ['boost_has_] prefix removed. |
| 49 | |
| 50 | When building the above example, you will see at the start of the build process the results |
| 51 | of the configuration, for example GCC in C++11 mode gives: |
| 52 | |
| 53 | - Boost.Config Feature Check: int128 : yes |
| 54 | - Boost.Config Feature Check: cxx11_constexpr : yes |
| 55 | - Boost.Config Feature Check: cxx11_user_defined_literals : yes |
| 56 | |
| 57 | That's all there is to this handy feature, should at any time you be unsure of the feature-test |
| 58 | names you can pass to the "requires" rule, then search for the Boost.Config macro of interest in |
| 59 | libs/config/checks/Jamfiles.v2, and the name of the feature check will follow it. |
| 60 | |
| 61 | And finally, this feature is built around the Boost.Build built in rule ['check-target-builds] |
| 62 | which can be used to perform more generalized build-time feature testing. The checks in this |
| 63 | library are provided as a convenient shorthand without the need for you to write the test cases yourself. |
| 64 | |
| 65 | [endsect] |