Interface library CMAKE_CXX_STANDARD propagation to dependent targets in multi-config generators
0 reputation · 11 Apr 2020, 18:00 UTC
0 reputation · 11 Apr 2020, 18:00 UTC
An interface library declares CMAKE_CXX_STANDARD 17 and exposes compile features through INTERFACE_COMPILE_FEATURES. Dependent executables link against it. The goal is for every consumer to inherit the same C++ standard flag in both Debug and Release configurations when using Visual Studio or Xcode.
This assumes CMake 3.8 through 3.28. CMake evaluates CMAKE_CXX_STANDARD per configuration, but INTERFACE_COMPILE_FEATURES does not accept $CONFIG generator expressions. It is unclear whether the standard flag should vary by configuration or remain uniform across the build tree, and whether consumers can override the inherited standard without breaking feature propagation.
Should INTERFACE_COMPILE_FEATURES re-evaluate CMAKE_CXX_STANDARD independently for each configuration in a multi-config generator? Can a consuming target specify a different CMAKE_CXX_STANDARD while still linking the interface library? What is the supported mechanism to propagate configuration-dependent standard flags without duplicating explicit compile options?
35275 reputation · 11 Apr 2020, 23:08 UTC
When an interface library declares CMAKE_CXX_STANDARD 17 and exposes INTERFACE_COMPILE_FEATURES cxx_std_17, the way that standard flag reaches dependent targets in multi‑config generators such as Visual Studio and Xcode depends on CMake's property model. The following sections separate the established property behavior from the typical outcomes observed in practice.
CMAKE_CXX_STANDARD sets the CXX_STANDARD target property at the moment a target is created. Applying it to an interface library does not, by itself, generate a compile‑time flag that consumers inherit. Interface libraries do not compile source, so the variable has no direct effect on translation‑unit options.
INTERFACE_COMPILE_FEATURES records generator‑level feature tags (such as cxx_std_17). These tags are configuration‑independent; they do not accept $<CONFIG> expressions, and CMake does not re‑evaluate CXX_STANDARD separately for Debug and Release in the 3.8‑3.28 series. Consequently, a single interface library sets one minimum standard that applies across all build configurations.
A consumer target may set its own CMAKE_CXX_STANDARD (or CXX_STANDARD) before add_executable. CMake does not reject the link when the consumer's standard differs from the interface requirement. The effective standard for the consumer becomes the higher of its own request and the propagated INTERFACE_COMPILE_FEATURES. Mixing standards across translation units in the same executable can produce ODR or ABI violations that CMake does not diagnose, so consistency is recommended when possible.
To ensure every consumer inherits c++17 in both Debug and Release, keep INTERFACE_COMPILE_FEATURES(cxx_std_17) on the interface library once. Visual Studio and Xcode each translate this tag to their respective standard flags (/std:c++17 or -std=c++17) for all configurations. If a configuration‑dependent flag is required, add the option to INTERFACE_COMPILE_OPTIONS using compiler‑id–scoped generator expressions such as $ and $. This places the flag in the generated build only for the matching configuration, and linked consumers pick it up without repeating the option.
Diagnostic detail needed: Which compiler and generator are in use (MSVC, GCC, or Clang/Xcode) and whether the project requires a uniform standard across all configurations or intentional config‑specific divergence. This determines whether the single‑feature approach or the INTERFACE_COMPILE_OPTIONS strategy is the appropriate path.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.