Is it a CMake bug if setting C++ standard on a dependency is required?

In one of my projects, I recently removed `set(CMAKE_CXX_STANDARD 23)` from the top-level cmakelists, instead setting a compile feature on the appropriate targets.

My unit test executable that depends on Catch2 failed with some linker errors, something that looked like an ABI issue. Setting `set(CMAKE_CXX_STANDARD 23)` before adding Catch2 via FetchContent fixed the issue.

Does this indicate some sort of bug in CMake’s resolution of the C++ standard flags? Or is this a bug in Catch2’s CMake configuration?

But you’re specifying CMAKE_CXX_STANDARD on the command line. If you remove that, and just set the CXX_STANDARD property to 26 on your own targets, do the unit tests compile & link?

yes, it works with 23 and 26!

Only my CXX_MODULE has a linker problem wit GCC on my OSX, independently of Catch2!

bash-5.3$ make distclean
rm -rf build compile_commands.json
find . -name '*~' -delete

bash-5.3$ make build/compile_commands.json
cmake -S . -B build -G Ninja --log-level=VERBOSE -D CMAKE_BUILD_TYPE=Release \
	 -D CMAKE_CXX_STDLIB_MODULES_JSON=/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current/libstdc++.modules.json \
	 -D CMAKE_INSTALL_MESSAGE=LAZY \
	 -D BEMAN_USE_MODULES=YES \
	 -D BEMAN_USE_STD_MODULE=YES \
	 -D BEMAN_SCOPE_USE_DANIELA_ADVICE=YES \
	 -D CMAKE_SKIP_TEST_ALL_DEPENDENCY=NO \
	# FIXME -D CMAKE_CXX_STANDARD=26 -D CMAKE_CXX_EXTENSIONS=YES -D CMAKE_CXX_STANDARD_REQUIRED=YES \
	# XXX -D CMAKE_CXX_FLAGS='-fno-inline --coverage' \
	# XXX -D CMAKE_SKIP_INSTALL_RULES=YES # --fresh
-- The CXX compiler identification is GNU 15.2.0
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/local/bin/g++-15 - skipped
-- Detecting CXX compile features
CMake Warning (dev) at /Users/clausklein/.direnv/python-3.14/lib/python3.14/site-packages/cmake/data/share/cmake-4.2/Modules/Compiler/CMakeCommonCompilerMacros.cmake:248 (cmake_language):
  CMake's support for `import std;` in C++23 and newer is experimental.  It
  is meant only for experimentation and feedback to CMake developers.
Call Stack (most recent call first):
  /Users/clausklein/.direnv/python-3.14/lib/python3.14/site-packages/cmake/data/share/cmake-4.2/Modules/CMakeDetermineCompilerSupport.cmake:113 (cmake_create_cxx_import_std)
  /Users/clausklein/.direnv/python-3.14/lib/python3.14/site-packages/cmake/data/share/cmake-4.2/Modules/CMakeTestCXXCompiler.cmake:83 (CMAKE_DETERMINE_COMPILER_SUPPORT)
  CMakeLists.txt:7 (project)
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Detecting CXX compile features - done
-- CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=/usr/local/Cellar/gcc/15.2.0_1/include/c++/15;/usr/local/Cellar/gcc/15.2.0_1/include/c++/15/x86_64-apple-darwin23;/usr/local/Cellar/gcc/15.2.0_1/include/c++/15/backward;/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/x86_64-apple-darwin23/15/include;/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/x86_64-apple-darwin23/15/include-fixed;/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/usr/include;/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/System/Library/Frameworks
-- CMAKE_CXX_STDLIB_MODULES_JSON=/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current/libstdc++.modules.json
-- BEMAN_USE_MODULES=YES
-- BEMAN_USE_STD_MODULE=YES
-- CMAKE_CXX_COMPILER_IMPORT_STD=23;26
-- CMAKE_CXX_MODULE_STD=ON
-- BEMAN_HAS_IMPORT_STD=ON
-- CMAKE_CXX_SCAN_FOR_MODULES=ON
-- Compiler is: GNU version: 15.2.0
-- Cmake is: 4.2.3 modules scan: ON
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY - Success
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY - Success
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Success
-- GCC libstdc++ rpath: /usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current
-- Executing download step for catch2
Cloning into 'catch2-src'...
HEAD is now at 29c9844f v3.13.0
-- Executing update step for catch2
-- Already at requested tag: v3.13.0
-- Executing patch step for catch2
-- Performing Test HAVE_FLAG__ffile_prefix_map__Users_clausklein_Workspace_cpp_beman_project_scope_build__deps_catch2_src__
-- Performing Test HAVE_FLAG__ffile_prefix_map__Users_clausklein_Workspace_cpp_beman_project_scope_build__deps_catch2_src__ - Success
Tests to be built: scope_success;scope_exit;scope_fail;unique_resource;unique_resource_2
Examples to be built: scope_example;unique_resource;unique_resource-file
-- Configuring done (10.9s)
-- Generating done (0.1s)
-- Build files have been written to: /Users/clausklein/Workspace/cpp/beman-project/scope/build
bash-5.3$ make test -n
ninja -C build test
bash-5.3$ make
ln -sf build/compile_commands.json .
ninja -C build all all_verify_interface_header_sets
ninja: Entering directory `build'
[252/271] Linking CXX executable stagedir/bin/scope_module
FAILED: [code=1] stagedir/bin/scope_module 
: && /usr/local/bin/g++-15 -stdlib=libstdc++ -O3 -DNDEBUG -Wl,-search_paths_first -Wl,-headerpad_max_install_names -L/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current examples/CMakeFiles/scope_module.dir/scope-module.cpp.o -o stagedir/bin/scope_module  -Wl,-rpath,/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current  stagedir/lib/libbeman.scope.a && :
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
Undefined symbols for architecture x86_64:
  "initializer for module std", referenced from:
      __GLOBAL__sub_I_scope_module.cpp in scope-module.cpp.o
      initializer for module beman.scope in libbeman.scope.a[2](beman.scope.cppm.o)
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
[253/271] Linking CXX executable stagedir/bin/scope_example
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
[254/271] Linking CXX executable stagedir/bin/unique_resource
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
[262/271] Building CXX object _deps/catch2-build/src/CMakeFiles/Catch2.dir/catch2/matchers/catch_matchers_string.cpp.o
ninja: build stopped: subcommand failed.
make: *** [all] Error 1
bash-5.3$ 
```

?

that is OK:

bash-5.3$ cd build/
bash-5.3$ ninja lib
libCatch2.a       libCatch2Main.a   libbeman.scope.a  
bash-5.3$ ninja libCatch2.a libCatch2Main.a 
[2/2] Linking CXX static library stagedir/lib/libCatch2Main.a
bash-5.3$ ninja tests/all 
[1/6] Linking CXX executable stagedir/bin/test.module
FAILED: [code=1] stagedir/bin/test.module tests/test.module-b12d07c_tests.cmake /Users/clausklein/Workspace/cpp/beman-project/scope/build/tests/test.module-b12d07c_tests.cmake 
: && /usr/local/bin/g++-15 -stdlib=libstdc++ -O3 -DNDEBUG -Wl,-search_paths_first -Wl,-headerpad_max_install_names -L/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current tests/CMakeFiles/test.module.dir/module.test.cpp.o -o stagedir/bin/test.module  -Wl,-rpath,/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current  stagedir/lib/libCatch2Main.a  stagedir/lib/libbeman.scope.a  stagedir/lib/libCatch2.a && cd /Users/clausklein/Workspace/cpp/beman-project/scope/build/tests && /Users/clausklein/.direnv/python-3.14/lib/python3.14/site-packages/cmake/data/bin/cmake -D TEST_TARGET=test.module -D TEST_EXECUTABLE=/Users/clausklein/Workspace/cpp/beman-project/scope/build/stagedir/bin/test.module -D TEST_EXECUTOR= -D TEST_WORKING_DIR=/Users/clausklein/Workspace/cpp/beman-project/scope/build/tests -D TEST_SPEC= -D TEST_EXTRA_ARGS= -D "TEST_PROPERTIES=SKIP_RETURN_CODE;4" -D TEST_PREFIX= -D TEST_SUFFIX= -D TEST_LIST=test.module_TESTS -D TEST_REPORTER= -D TEST_OUTPUT_DIR= -D TEST_OUTPUT_PREFIX= -D TEST_OUTPUT_SUFFIX= -D TEST_DL_PATHS= -D TEST_DL_FRAMEWORK_PATHS= -D CTEST_FILE=/Users/clausklein/Workspace/cpp/beman-project/scope/build/tests/test.module-b12d07c_tests.cmake -D ADD_TAGS_AS_LABELS=FALSE -P /Users/clausklein/Workspace/cpp/beman-project/scope/build/_deps/catch2-src/extras/CatchAddTests.cmake
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
Undefined symbols for architecture x86_64:
  "initializer for module std", referenced from:
      __GLOBAL__sub_I_module.test.cpp in module.test.cpp.o
      initializer for module beman.scope in libbeman.scope.a[2](beman.scope.cppm.o)
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
[2/6] Linking CXX executable stagedir/bin/test.scope_exit
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
[3/6] Linking CXX executable stagedir/bin/test.unique_resource
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
[4/6] Linking CXX executable stagedir/bin/test.unique_resource_2
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
[5/6] Linking CXX executable stagedir/bin/test.scope_fail
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
[6/6] Linking CXX executable stagedir/bin/test.scope_success
ld: warning: duplicate -rpath '/usr/local/Cellar/gcc/15.2.0_1/lib/gcc/current' ignored
ninja: build stopped: subcommand failed.
bash-5.3$