WIP: cmake optional compile features
Summary
Compiler can now be set target-wise using the new function target_optional_compile_features
. Several features are already defined and required for dunecommon
library target. The preprocessor constants are unified to DUNE_HAVE_CXX_...
. Detected features are connected to a target by adding a compile definition.
Details
Features are simply identified by their name and a cmake file with that name in the new directory cmake/cxx_features
. The feature checks must be implemented as a function add_feature(TARGET SCOPE)
in that named file. In contrast to the old way of communicating detected compiler features, the new function target_optional_compile_features
sets a compile-definition to the passed target. This allows to specifically communicate these features by linking against that target.
Features are checked only once, in the module where the function target_optional_compile_features
is called on the library target. Dependent modules do not need check again for that feature. This guarantees that module A that has detected a feature and has set compile definition on its target library is compiled with these definitions and all dependent downstream modules linking (using) module A also get these definitions and thus are compiler with the same flags.
The add_feature
macros that test for a specific compiler or library feature may additionally set a higher standard requirement on the target if the feature requires it. This c++-standard requirement is thus also communicated by the target and transitively applies to all downstream modules using module A.
Examples
Write a new compiler feature
Simply put a new file with the name of the feature into the cmake/feature_tests
directory. This file must contain the function add_feature(<target> <scope>)
with target a regular cmake target the feature should be registered to. The registration is typically accomplished by
- setting other compiler feature
- adding a compile definition
- setting a higher c++ standard
For example, create the file cmake/feautre_tests/xyz.cmake
with the content
function (add_feature TARGET SCOPE)
message(STATUS "Looking for optional compiler feature XYZ")
# make the check whether feature is supported by the compiler
# -> setting the cache variable DUNE_HAVE_XYZ
if (DUNE_HAVE_XYZ)
target_compile_definitions(${TARGET} ${SCOPE} DUNE_HAVE_XYZ)
message(STATUS "Looking for optional compiler feature XYZ - found")
else ()
message(STATUS "Looking for optional compiler feature sXYZ - not found")
endif ()
endfunction (add_feature)
Apply feature check to target
Optional compiler feature do not stop the cmake configuration if not supported, but just register this feature in case it is supported. It should be added to a cmake target directly after the target is created, where you also add other requirements like package dependencies.
include(TargetOptionalCompileFeatures)
target_optional_compile_features(<target> PUBLIC xyz)
If a feature is added to the build dependencies of a target only (i.e. PRIVATE
) it needs to be clear that the corresponding compile definition should not be exported or used in a header file, since every other target using this header does not inherit this feature compile definition.
Note
This MR is build on top of !862 (merged)
Todo:
-
Check whether it is possible to put the compile definitions in the config.h
file without testing for the features again. -
Better naming for directories, to support other language features, like for CUDA. -
Cleanup list of features, i.e. remove feature checks on those that are supported by all supported compilers, especially clang-5 and g++-7.