Proposal: target_compile_features evaluate features lazily
Background:
Generated by the discussion on: !6224 (closed)
CMake has a desire to remove the current logic where languages such as OBJC
, OBJCXX
, CUDA
, and HIP
will use the same language level as the closest matching 'classic' language if no explicit level is specified.
Currently an issue with this is that cxx_std_14
can be used to activate CUDA
, HIP
, or OBJCXX
standard level without requiring a enable_language([CUDA|HIP|OBJCXX]). This is problematic when trying to express INTERFACE targets that can be consumed by multiple languages. In addition this behavior doesn't exist for the <LANG>_STANDARD
property.
For example lets consider a header only library that can be C++ or CUDA but requires C++17, CUDA17 if used. This header library wants to express that if used from a particular language the compiler standard must be of a given level. The naive approach would be the following:
add_library(header_only INTERFACE)
target_compile_features(header_only INTERFACE cxx_std_17 cuda_std_17)
But this won't work as adding cxx_std_17
or cuda_std_17
enforces that the given language
has been enabled when target_compile_features
is called, instead of having each consuming
target only evaluate features that map to enabled languages.
Proposal:
target_compile_features
and the COMPILE_FEATURES
target property will ignore valid features that map to un-enabled languages.
project(example LANGUAGES NONE)
target_compile_features(header_only INTERFACE cxx_std_17 cuda_std_17) # valid
set_target_properties(standard_levls PROPERTIES COMPILE_FEATURES "cxx_std_11;cuda_std_11") # valid
target_compile_features(header_only INTERFACE invalid_feature) # still produces error
set_target_properties(standard_levls PROPERTIES COMPILE_FEATURES "here_be_garbage") # still produces error
This would be done by having cmStandardLevelResolver
only check if a feature is available if the associated language is enabled. The change would be isolated to CheckCompileFeaturesAvailable
and would look like:
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index 37ed4c130a..74b9d6fd54 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -385,10 +385,14 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable(
{
if (!this->CompileFeatureKnown(targetName, feature, lang, error)) {
return false;
}
+ if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) {
+ return true;
+ }
+
const char* features = this->CompileFeaturesAvailable(lang, error);
if (!features) {
return false;
}