Setting C++ standard on INTERFACE libraries

I try to understand why setting the C++ standard properties on an interface library doesn’t work. I can’t find this documented or properly explained anywhere. CMake doesn’t seem to issue any warnings or errors.

add_library(CMakeTestLib INTERFACE)
set_target_properties(CMakeTestLib 
    PROPERTIES
        CXX_STANDARD 23
        CXX_STANDARD_REQUIRED ON
        CXX_EXTENSIONS OFF
)

# or
set_property(TARGET CMakeTestLib PROPERTY CXX_STANDARD 23)
set_property(TARGET CMakeTestLib PROPERTY CXX_STANDARD_REQUIRED ON)
set_property(TARGET CMakeTestLib PROPERTY CXX_EXTENSIONS OFF)

If I set the standard version via compile features, why aren’t there “compile features” to also turn off compiler extensions?:

target_compile_features(CMakeTestLib
  INTERFACE
    cxx_std_23
)

Then I need to go for a mixed solution or

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

According to the documentation

add_library( INTERFACE)

Add an Interface Library target that may specify usage requirements for dependents but does not compile sources and does not produce a library artifact on disk.

An interface library with no source files is not included as a target in the generated buildsystem. However, it may have properties set on it and it may be installed and exported. Typically, INTERFACE_* properties are populated on an interface target using the commands:

If I understand the above correctly I can use an interface library to define all my properties in a single consistent way and to apply them to all targets that link to the interface library transitively.
Is that so or am I “holding it wrongly”?

For interface libraries, I’m using:

target_compile_features(${TARGET_NAME} INTERFACE ${Standard})
set_target_properties(${TARGET_NAME} PROPERTIES INTERFACE_CXX_EXTENSIONS OFF)

And I don’t have any issues.

You’re saying that “it doesn’t work”. Can you detail in what way?

Regards,
A.

I can’t find any trace of such a property.

CMake doesn’t model language extensions through usage requirements at the moment, so I don’t think there’s any way of doing it today, sorry.

Hi,

I can’t recall where I found INTERFACE_CXX_EXTENSIONS.
Oddly enough, it’s mentioned in https://gitlab.kitware.com/cmake/cmake/-/issues/17183 by someone you know ;-).

I’ve juste made a test and replaced CXX_EXTENSIONS without any change in behavior. As stated in previous link, I’m beginning to suspect that this property is useless for headers-only libraries.

Regards

1 Like

I skimmed over the issue: https://gitlab.kitware.com/cmake/cmake/-/issues/17183

There is a comment proposing a policy to disable extensions:
https://gitlab.kitware.com/cmake/cmake/-/issues/17183#note_558723
I like that and it would be good if it is set by default.

Attempting this:

set_target_properties(CMakeTestLib 
    PROPERTIES
        INTERFACE_CXX_STANDARD 23
        INTERFACE_CXX_STANDARD_REQUIRED ON
        INTERFACE_CXX_EXTENSIONS OFF
)

still produces and doesn’t seem to report any errors (with GCC):

  FLAGS = -g -std=gnu++23

Obviously I’d like to have:

  FLAGS = -g -std=c++23

The last comment in this issue:
https://gitlab.kitware.com/cmake/cmake/-/issues/16495
explaince CXX_STANDARD properties better than the documentation (IMO):

the CXX_STANDARD property itself only affects how sources within that target are built. Since interface libraries have no sources it doesn’t matter. Transitive usage requirements are of the form INTERFACE_... where ... is the property on the dependent targets to extend. This only works for a specific set of properties, and CXX_STANDARD is not among them. The intended way to propagate C++ language requirements is with INTERFACE_COMPILE_FEATURES.

Yeah, I was saying what the property would be named to have the requested effect. Alas, no such property actually exists.