From a42cbd59310ead575a20d14d688503a898590134 Mon Sep 17 00:00:00 2001 From: Edward Nolan Date: Thu, 5 Mar 2026 11:53:08 -0500 Subject: [PATCH 1/8] wip modules --- CMakeLists.txt | 10 ++++++++ .../beman/transform_view/transform_view.hpp | 4 +++- src/beman/transform_view/CMakeLists.txt | 24 +++++++++++++++++++ src/beman/transform_view/transform_view.cppm | 11 +++++++++ tests/beman/transform_view/CMakeLists.txt | 10 ++++++++ .../transform_view/module_smoke_test.test.cpp | 4 ++++ 6 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/beman/transform_view/CMakeLists.txt create mode 100644 src/beman/transform_view/transform_view.cppm create mode 100644 tests/beman/transform_view/module_smoke_test.test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 26ae1da..d2d7b35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 3.28...4.2) +# TODO: Set BEMAN_USE_MODULES if one of a particular set of compiler versions is being used + +if (BEMAN_USE_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") +endif() + project( beman.transform_view # CMake Project Name, which is also the name of the top-level # targets (e.g., library, executable, etc.). @@ -41,6 +48,9 @@ set_target_properties( ) add_subdirectory(include/beman/transform_view) +if (BEMAN_USE_MODULES) + add_subdirectory(src/beman/transform_view) +endif() include(CTest) diff --git a/include/beman/transform_view/transform_view.hpp b/include/beman/transform_view/transform_view.hpp index a159176..d0bc335 100644 --- a/include/beman/transform_view/transform_view.hpp +++ b/include/beman/transform_view/transform_view.hpp @@ -3,10 +3,12 @@ #ifndef BEMAN_TRANSFORM_VIEW_HPP #define BEMAN_TRANSFORM_VIEW_HPP +#ifndef BEMAN_HAS_MODULES #include #include #include #include +#endif namespace beman::transform_view { @@ -504,7 +506,7 @@ struct bind_back_t { private: using indices = std::index_sequence_for; - template + template static constexpr decltype(auto) call_impl(T&& this_, std::index_sequence, Args&&... args) { return ((T&&)this_) diff --git a/src/beman/transform_view/CMakeLists.txt b/src/beman/transform_view/CMakeLists.txt new file mode 100644 index 0000000..9d80d39 --- /dev/null +++ b/src/beman/transform_view/CMakeLists.txt @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +add_library(beman.transform_view.module STATIC) +add_library(beman::transform_view.module ALIAS beman.transform_view.module) + +target_sources( + beman.transform_view.module + PUBLIC FILE_SET CXX_MODULES FILES transform_view.cppm +) + +target_include_directories( + beman.transform_view.module + PUBLIC + ${PROJECT_SOURCE_DIR}/include +) + +target_compile_definitions( + beman.transform_view.module + PUBLIC BEMAN_HAS_MODULES) + +set_target_properties( + beman.transform_view.module + PROPERTIES CXX_MODULE_STD ON +) diff --git a/src/beman/transform_view/transform_view.cppm b/src/beman/transform_view/transform_view.cppm new file mode 100644 index 0000000..1afba56 --- /dev/null +++ b/src/beman/transform_view/transform_view.cppm @@ -0,0 +1,11 @@ +module; + +export module beman.transform_view; + +import std; + +extern "C++" { +export { + #include +} +} diff --git a/tests/beman/transform_view/CMakeLists.txt b/tests/beman/transform_view/CMakeLists.txt index 0747c5b..f5c8b4b 100644 --- a/tests/beman/transform_view/CMakeLists.txt +++ b/tests/beman/transform_view/CMakeLists.txt @@ -12,5 +12,15 @@ target_link_libraries( PRIVATE beman::transform_view GTest::gtest GTest::gtest_main ) +add_executable(beman.transform_view.tests.module_smoke_test) +target_sources( + beman.transform_view.tests.module_smoke_test + PRIVATE module_smoke_test.test.cpp +) +target_link_libraries( + beman.transform_view.tests.module_smoke_test + PRIVATE beman::transform_view.module +) + include(GoogleTest) gtest_discover_tests(beman.transform_view.tests.transform_view) diff --git a/tests/beman/transform_view/module_smoke_test.test.cpp b/tests/beman/transform_view/module_smoke_test.test.cpp new file mode 100644 index 0000000..3e063cd --- /dev/null +++ b/tests/beman/transform_view/module_smoke_test.test.cpp @@ -0,0 +1,4 @@ +import beman.transform_view; + +int main() { +} From ea2d9758c70346a942d2e693f264e224f66adff8 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Thu, 5 Mar 2026 23:15:38 +0100 Subject: [PATCH 2/8] Try to make it works with module --- .gitignore | 2 +- CMakeLists.txt | 37 +++++++++++++------ examples/CMakeLists.txt | 29 ++++++++++++++- examples/transform_view_direct_usage.cpp | 10 ++++- .../beman/transform_view/transform_view.hpp | 2 +- src/beman/transform_view/CMakeLists.txt | 20 +--------- src/beman/transform_view/transform_view.cppm | 13 +++++-- tests/beman/transform_view/CMakeLists.txt | 4 +- .../transform_view/module_smoke_test.test.cpp | 3 +- 9 files changed, 78 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index d293e3b..0d7e3bf 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ /.cache /compile_commands.json -/build +build/ # ignore emacs temp files *~ diff --git a/CMakeLists.txt b/CMakeLists.txt index d2d7b35..f11215f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,14 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.28...4.2) +cmake_minimum_required(VERSION 3.28...4.3) # TODO: Set BEMAN_USE_MODULES if one of a particular set of compiler versions is being used -if (BEMAN_USE_MODULES) - set(CMAKE_CXX_SCAN_FOR_MODULES ON) - set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") +if(BEMAN_USE_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) endif() project( @@ -37,10 +39,7 @@ include(infra/cmake/beman-install-library.cmake) add_library(beman.transform_view INTERFACE) add_library(beman::transform_view ALIAS beman.transform_view) -target_sources( - beman.transform_view - PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" -) +target_sources(beman.transform_view PUBLIC FILE_SET HEADERS BASE_DIRS include) set_target_properties( beman.transform_view @@ -48,16 +47,30 @@ set_target_properties( ) add_subdirectory(include/beman/transform_view) -if (BEMAN_USE_MODULES) + +if(BEMAN_USE_MODULES) + add_library(beman.transform_view_module STATIC) + add_library(beman::transform_view_module ALIAS beman.transform_view_module) + + if(BEMAN_USE_STD_MODULES) + target_compile_features(beman.transform_view_module PUBLIC cxx_std_23) + # XXX set_target_properties(beman.transform_view_module PROPERTIES CXX_MODULE_STD ON) + endif() + + target_sources( + beman.transform_view_module + PUBLIC FILE_SET HEADERS BASE_DIRS include + ) + add_subdirectory(src/beman/transform_view) endif() -include(CTest) +# NOT needed! include(CTest) +enable_testing() -beman_install_library(beman.transform_view TARGETS beman.transform_view) +beman_install_library(beman.transform_view TARGETS beman.transform_view beman.transform_view_module) if(BEMAN_TRANSFORM_VIEW_BUILD_TESTS) - enable_testing() add_subdirectory(tests/beman/transform_view) endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 112e633..318b34f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,4 +1,20 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +cmake_minimum_required(VERSION 3.28...4.3) + +# TODO: Set BEMAN_USE_MODULES if one of a particular set of compiler versions is being used + +if(BEMAN_USE_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +endif() + +project(beman.transform_view.example LANGUAGES CXX) + +if(PROJECT_IS_TOP_LEVEL) + find_package(beman.transform_view 0.1.0 EXACT REQUIRED) +endif() set(ALL_EXAMPLES transform_view_direct_usage) @@ -10,8 +26,19 @@ foreach(example ${ALL_EXAMPLES}) beman.transform_view.examples.${example} PRIVATE ${example}.cpp ) + if(BEMAN_USE_MODULES) + target_compile_features( + beman.transform_view.examples.${example} + PUBLIC cxx_std_23 + ) + # XXX set_target_properties(beman.transform_view.examples.${example} PROPERTIES CXX_MODULE_STD ON) + endif() target_link_libraries( beman.transform_view.examples.${example} - PRIVATE beman::transform_view + PRIVATE beman::transform_view_module + ) + add_test( + NAME beman.transform_view.examples.${example} + COMMAND beman.transform_view.examples.${example} ) endforeach() diff --git a/examples/transform_view_direct_usage.cpp b/examples/transform_view_direct_usage.cpp index ddb7f00..d05af6a 100644 --- a/examples/transform_view_direct_usage.cpp +++ b/examples/transform_view_direct_usage.cpp @@ -1,8 +1,14 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include - #include +#include +#include + +#ifdef BEMAN_HAS_MODULES +import beman.transform_view; +#else +#include +#endif namespace tv26 = beman::transform_view; diff --git a/include/beman/transform_view/transform_view.hpp b/include/beman/transform_view/transform_view.hpp index d0bc335..147719b 100644 --- a/include/beman/transform_view/transform_view.hpp +++ b/include/beman/transform_view/transform_view.hpp @@ -3,7 +3,7 @@ #ifndef BEMAN_TRANSFORM_VIEW_HPP #define BEMAN_TRANSFORM_VIEW_HPP -#ifndef BEMAN_HAS_MODULES +#ifndef BEMAN_HAS_STD_MODULES #include #include #include diff --git a/src/beman/transform_view/CMakeLists.txt b/src/beman/transform_view/CMakeLists.txt index 9d80d39..663ccfb 100644 --- a/src/beman/transform_view/CMakeLists.txt +++ b/src/beman/transform_view/CMakeLists.txt @@ -1,24 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -add_library(beman.transform_view.module STATIC) -add_library(beman::transform_view.module ALIAS beman.transform_view.module) - target_sources( - beman.transform_view.module + beman.transform_view_module PUBLIC FILE_SET CXX_MODULES FILES transform_view.cppm ) -target_include_directories( - beman.transform_view.module - PUBLIC - ${PROJECT_SOURCE_DIR}/include -) - -target_compile_definitions( - beman.transform_view.module - PUBLIC BEMAN_HAS_MODULES) - -set_target_properties( - beman.transform_view.module - PROPERTIES CXX_MODULE_STD ON -) +target_compile_definitions(beman.transform_view_module PUBLIC BEMAN_HAS_MODULES) diff --git a/src/beman/transform_view/transform_view.cppm b/src/beman/transform_view/transform_view.cppm index 1afba56..2437206 100644 --- a/src/beman/transform_view/transform_view.cppm +++ b/src/beman/transform_view/transform_view.cppm @@ -1,11 +1,18 @@ module; -export module beman.transform_view; - +#ifndef BEMAN_HAS_STD_MODULES +#include +#include +#include +#include +#else import std; +#endif + +export module beman.transform_view; extern "C++" { export { - #include +#include } } diff --git a/tests/beman/transform_view/CMakeLists.txt b/tests/beman/transform_view/CMakeLists.txt index f5c8b4b..4cf8352 100644 --- a/tests/beman/transform_view/CMakeLists.txt +++ b/tests/beman/transform_view/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -find_package(GTest REQUIRED) +find_package(GTest CONFIG REQUIRED) add_executable(beman.transform_view.tests.transform_view) target_sources( @@ -19,7 +19,7 @@ target_sources( ) target_link_libraries( beman.transform_view.tests.module_smoke_test - PRIVATE beman::transform_view.module + PRIVATE beman::transform_view_module ) include(GoogleTest) diff --git a/tests/beman/transform_view/module_smoke_test.test.cpp b/tests/beman/transform_view/module_smoke_test.test.cpp index 3e063cd..50c4830 100644 --- a/tests/beman/transform_view/module_smoke_test.test.cpp +++ b/tests/beman/transform_view/module_smoke_test.test.cpp @@ -1,4 +1,3 @@ import beman.transform_view; -int main() { -} +int main() {} From c9671936fc5b3367e8a2bc7dc6de9467a3c0fc96 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Thu, 5 Mar 2026 23:37:06 +0100 Subject: [PATCH 3/8] Set BEMAN_USE_MODULES in presets --- CMakePresets.json | 3 +++ examples/CMakeLists.txt | 13 +++++++++---- tests/beman/transform_view/CMakeLists.txt | 20 +++++++++++--------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index bd35911..81a99a2 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -7,6 +7,7 @@ "generator": "Ninja", "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { + "BEMAN_USE_MODULES": true, "CMAKE_CXX_STANDARD": "23", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "./infra/cmake/use-fetch-content.cmake" @@ -79,6 +80,7 @@ "_debug-base" ], "cacheVariables": { + "BEMAN_USE_MODULES": false, "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" } }, @@ -90,6 +92,7 @@ "_release-base" ], "cacheVariables": { + "BEMAN_USE_MODULES": false, "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" } }, diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 318b34f..688bb05 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -32,11 +32,16 @@ foreach(example ${ALL_EXAMPLES}) PUBLIC cxx_std_23 ) # XXX set_target_properties(beman.transform_view.examples.${example} PROPERTIES CXX_MODULE_STD ON) + target_link_libraries( + beman.transform_view.examples.${example} + PRIVATE beman::transform_view_module + ) + else() + target_link_libraries( + beman.transform_view.examples.${example} + PRIVATE beman::transform_view + ) endif() - target_link_libraries( - beman.transform_view.examples.${example} - PRIVATE beman::transform_view_module - ) add_test( NAME beman.transform_view.examples.${example} COMMAND beman.transform_view.examples.${example} diff --git a/tests/beman/transform_view/CMakeLists.txt b/tests/beman/transform_view/CMakeLists.txt index 4cf8352..f9eca79 100644 --- a/tests/beman/transform_view/CMakeLists.txt +++ b/tests/beman/transform_view/CMakeLists.txt @@ -12,15 +12,17 @@ target_link_libraries( PRIVATE beman::transform_view GTest::gtest GTest::gtest_main ) -add_executable(beman.transform_view.tests.module_smoke_test) -target_sources( - beman.transform_view.tests.module_smoke_test - PRIVATE module_smoke_test.test.cpp -) -target_link_libraries( - beman.transform_view.tests.module_smoke_test - PRIVATE beman::transform_view_module -) +if(BEMAN_USE_MODULES) + add_executable(beman.transform_view.tests.module_smoke_test) + target_sources( + beman.transform_view.tests.module_smoke_test + PRIVATE module_smoke_test.test.cpp + ) + target_link_libraries( + beman.transform_view.tests.module_smoke_test + PRIVATE beman::transform_view_module + ) +endif() include(GoogleTest) gtest_discover_tests(beman.transform_view.tests.transform_view) From 25e4cbad4690ca1461cb45e785d77fc500228a72 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Mar 2026 14:14:07 +0100 Subject: [PATCH 4/8] Make it works --- CMakeLists.txt | 36 +++-- CMakePresets.json | 5 +- cmake/cxx-modules-rules.cmake | 155 +++++++++++++++++++ cmake/prelude.cmake | 122 +++++++++++++++ examples/CMakeLists.txt | 32 ++-- examples/transform_view_direct_usage.cpp | 4 + infra/cmake/beman-install-library.cmake | 3 + src/beman/transform_view/transform_view.cppm | 2 +- 8 files changed, 334 insertions(+), 25 deletions(-) create mode 100644 cmake/cxx-modules-rules.cmake create mode 100644 cmake/prelude.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f11215f..856b5fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,15 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.28...4.3) +cmake_minimum_required(VERSION 3.30...4.3) -# TODO: Set BEMAN_USE_MODULES if one of a particular set of compiler versions is being used +include(./cmake/prelude.cmake) -if(BEMAN_USE_MODULES) - set(CMAKE_CXX_SCAN_FOR_MODULES ON) - set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD - "d0edc3af-4c50-42ea-a356-e2862fe7a444" - ) -endif() +# if(BEMAN_USE_MODULES) +# set(CMAKE_CXX_SCAN_FOR_MODULES ON) +# set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD +# "d0edc3af-4c50-42ea-a356-e2862fe7a444" +# ) +# endif() project( beman.transform_view # CMake Project Name, which is also the name of the top-level @@ -19,6 +19,9 @@ project( VERSION 0.1.0 ) +# Modules opt in only on compilers that support it: msvc, g++-15 and clang-20+ +include(./cmake/cxx-modules-rules.cmake) + # [CMAKE.SKIP_TESTS] option( BEMAN_TRANSFORM_VIEW_BUILD_TESTS @@ -51,10 +54,19 @@ add_subdirectory(include/beman/transform_view) if(BEMAN_USE_MODULES) add_library(beman.transform_view_module STATIC) add_library(beman::transform_view_module ALIAS beman.transform_view_module) - - if(BEMAN_USE_STD_MODULES) - target_compile_features(beman.transform_view_module PUBLIC cxx_std_23) - # XXX set_target_properties(beman.transform_view_module PROPERTIES CXX_MODULE_STD ON) + target_compile_features( + beman.transform_view_module + PUBLIC cxx_std_${CMAKE_CXX_STANDARD} + ) + if(BEMAN_USE_STD_MODULE) + target_compile_definitions( + beman.transform_view_module + PUBLIC BEMAN_HAS_IMPORT_STD + ) + set_target_properties( + beman.transform_view_module + PROPERTIES CXX_MODULE_STD ON + ) endif() target_sources( diff --git a/CMakePresets.json b/CMakePresets.json index 81a99a2..e13f76e 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -8,6 +8,7 @@ "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { "BEMAN_USE_MODULES": true, + "BEMAN_USE_STD_MODULE": true, "CMAKE_CXX_STANDARD": "23", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "./infra/cmake/use-fetch-content.cmake" @@ -58,7 +59,7 @@ "_debug-base" ], "cacheVariables": { - "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-toolchain.cmake" + "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-libc++-toolchain.cmake" } }, { @@ -69,7 +70,7 @@ "_release-base" ], "cacheVariables": { - "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-toolchain.cmake" + "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-libc++-toolchain.cmake" } }, { diff --git a/cmake/cxx-modules-rules.cmake b/cmake/cxx-modules-rules.cmake new file mode 100644 index 0000000..91939b3 --- /dev/null +++ b/cmake/cxx-modules-rules.cmake @@ -0,0 +1,155 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# A CMake language file to be included as the last step of all project() command calls. +# This file must be included/used as CMAKE_PROJECT_INCLUDE -> after project() +# + +# ---- The include guard applies within the current directory and below ---- +include_guard(DIRECTORY) + +if(NOT PROJECT_NAME) + message( + FATAL_ERROR + "This CMake file has to be included as the last step of all project() command calls!" + ) +endif() + +# Use modules? default NO! +if(NOT DEFINED CMAKE_CXX_SCAN_FOR_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES OFF) +endif() + +# Control whether the test target depends on the all target. +set(CMAKE_SKIP_TEST_ALL_DEPENDENCY OFF) + +# gersemi: off +option(CMAKE_EXPORT_COMPILE_COMMANDS "Prepare run-clang-tidy" ${PROJECT_IS_TOP_LEVEL}) +if(CMAKE_EXPORT_COMPILE_COMMANDS) + message( + STATUS + "CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}" + ) + set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) +endif() +# gersemi: on + +# Ensure non-empty default build type for single-config +get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(NOT isMultiConfig) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type") +endif() +set(CMAKE_DEBUG_POSTFIX _d) + +# ------------------------------------------------------------------------------ +# This property setting also needs to be consistent between the installed shared +# library and its consumer, otherwise most toolchains will once again reject the +# consumer's generated BMI. +# ------------------------------------------------------------------------------ +if(NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 23) +endif() + +# Neither of these two are technically needed, but they make the expectation clear +set(CMAKE_CXX_EXTENSIONS ON) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# NOTE: only with Ninja generator install of bmi files works yet! +if(CMAKE_GENERATOR MATCHES "Ninja") + if( + CMAKE_CXX_COMPILER_ID STREQUAL "Clang" + AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0 + ) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + + if(NOT LINUX) + string(APPEND CMAKE_CXX_MODULE_MAP_FLAG " -fmodules-reduced-bmi") + endif() + + add_compile_options($ENV{CXXFLAGS}) + add_link_options($ENV{CXXFLAGS}) + elseif( + CMAKE_CXX_COMPILER_ID STREQUAL "GNU" + AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0 + ) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + else() + set(CMAKE_CXX_SCAN_FOR_MODULES OFF) + endif() +endif() + +if(CMAKE_CXX_STDLIB_MODULES_JSON) + message( + STATUS + "CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON}" + ) +endif() + +if(NOT DEFINED CMAKE_CXX_MODULE_STD) + set(CMAKE_CXX_MODULE_STD OFF) +endif() + +if(CMAKE_CXX_STANDARD GREATER_EQUAL 20) + option(BEMAN_USE_MODULES "Build CXX_MODULES" ${CMAKE_CXX_SCAN_FOR_MODULES}) +endif() +message(STATUS "BEMAN_USE_MODULES=${BEMAN_USE_MODULES}") + +option( + BEMAN_USE_STD_MODULE + "Check if 'import std;' is possible with the toolchain?" + OFF +) +message(STATUS "BEMAN_USE_STD_MODULE=${BEMAN_USE_STD_MODULE}") + +if(BEMAN_USE_MODULES AND BEMAN_USE_STD_MODULE) + # ------------------------------------------------------------------------- + # Tell CMake that we explicitly want `import std`. + # This will initialize the property on all targets declared after this to 1 + # ------------------------------------------------------------------------- + message( + STATUS + "CMAKE_CXX_COMPILER_IMPORT_STD=${CMAKE_CXX_COMPILER_IMPORT_STD}" + ) + if(${CMAKE_CXX_STANDARD} IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD) + set(CMAKE_CXX_MODULE_STD ON) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + option( + BEMAN_HAS_IMPORT_STD + "Build with import std; is possible and used!" + ${CMAKE_CXX_MODULE_STD} + ) + message(STATUS "CMAKE_CXX_MODULE_STD=${CMAKE_CXX_MODULE_STD}") + else() + set(CMAKE_CXX_MODULE_STD OFF) + message(WARNING "CMAKE_CXX_MODULE_STD=${CMAKE_CXX_MODULE_STD}") + endif() + message(STATUS "BEMAN_HAS_IMPORT_STD=${BEMAN_HAS_IMPORT_STD}") +endif() + +if(NOT BEMAN_USE_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES OFF) +endif() +message(STATUS "CMAKE_CXX_SCAN_FOR_MODULES=${CMAKE_CXX_SCAN_FOR_MODULES}") + +# ------------------------------------------------------------------------------ +# Avoid creating CMAKE_..._OUTPUT_DIRECTORY as cache variables, they should not +# be under the control of the developer. They should be controlled by the +# project because parts of the project may make assumptions about the relative +# layout of the binaries. More importantly, leaving them as ordinary variables +# also means they can be unset within subdirectories where test executables are +# defined, allowing them to avoid being collected with the other main binaries +# and cluttering up that area. +# ------------------------------------------------------------------------------ +set(stageDir ${CMAKE_CURRENT_BINARY_DIR}/stagedir) +include(GNUInstallDirs) + +if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_BINDIR}) +endif() +if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_LIBDIR}) +endif() +if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_LIBDIR}) +endif() diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake new file mode 100644 index 0000000..e1572d4 --- /dev/null +++ b/cmake/prelude.cmake @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# This file must be included/used as CMAKE_PROJECT_TOP_LEVEL_INCLUDES -> before project() is called! +# + +# ---- The include guard applies globally to the whole build ---- +include_guard(GLOBAL) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message( + FATAL_ERROR + "In-source builds are not supported. " + "Please read the BUILDING document before trying to build this project. " + "You may need to delete 'CMakeCache.txt' and 'CMakeFiles/' first." + ) +endif() + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +# --------------------------------------------------------------------------- +if(NOT BEMAN_USE_STD_MODULE) + return() +endif() +# --------------------------------------------------------------------------- + +if(PROJECT_NAME) + message( + WARNING + "This CMake file has to be included before first project() command call!" + ) +endif() + +# gersemi: off +# --------------------------------------------------------------------------- +# check if import std; is supported by CMAKE_CXX_COMPILER +# --------------------------------------------------------------------------- +if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.3 AND CMAKE_VERSION VERSION_LESS 4.4) + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "451f2fe2-a8a2-47c3-bc32-94786d8fc91b") +elseif(CMAKE_VERSION VERSION_GREATER_EQUAL 4.2 AND CMAKE_VERSION VERSION_LESS 4.3) + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") +endif() +# gersemi: on + +# --------------------------------------------------------------------------- +# TODO(CK): Do we need this HACK still for linux too? +# --------------------------------------------------------------------------- +if(NOT APPLE) + return() +endif() + +# FIXME: clang++ we still needs to export CXX=clang++ +if("$ENV{CXX}" STREQUAL "" AND CMAKE_CXX_COMPILER) + message(WARNING "\$CXX is not set") + set(ENV{CXX} ${CMAKE_CXX_COMPILER}) +endif() + +# --------------------------------------------------------------------------- +# Workaround needed for CMAKE and clang++ to find the libc++.modules.json file +# --------------------------------------------------------------------------- +if( + CMAKE_VERSION VERSION_GREATER_EQUAL 4.2 + AND ("$ENV{CXX}" MATCHES "clang" OR CMAKE_CXX_COMPILER MATCHES "clang") +) + # NOTE: Always use libc++ + # see https://releases.llvm.org/19.1.0/projects/libcxx/docs/index.html + set(ENV{CXXFLAGS} -stdlib=libc++) + message(STATUS "CXXFLAGS=-stdlib=libc++") + + if(APPLE) + execute_process( + OUTPUT_VARIABLE LLVM_PREFIX + COMMAND brew --prefix llvm + COMMAND_ECHO STDOUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + file(REAL_PATH ${LLVM_PREFIX} LLVM_DIR) + set(LLVM_DIR ${LLVM_DIR} CACHE FILEPATH "") + + message(STATUS "LLVM_DIR=${LLVM_DIR}") + add_link_options(-L${LLVM_DIR}/lib/c++) + include_directories(SYSTEM ${LLVM_DIR}/include) + + # /usr/local/Cellar/llvm/21.1.8_1/lib/c++/libc++.modules.json + # "/usr/local/Cellar/llvm/21.1.8_1/share/libc++/v1/std.cppm", + set(CMAKE_CXX_STDLIB_MODULES_JSON + ${LLVM_DIR}/lib/c++/libc++.modules.json + ) + elseif(LINUX) + execute_process( + OUTPUT_VARIABLE LLVM_MODULES + COMMAND clang++ -print-file-name=libc++.modules.json + COMMAND_ECHO STDOUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT CMAKE_CXX_STDLIB_MODULES_JSON) + set(CMAKE_CXX_STDLIB_MODULES_JSON ${LLVM_MODULES}) + endif() + message( + STATUS + "CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON}" + ) + endif() + + if(EXISTS ${CMAKE_CXX_STDLIB_MODULES_JSON}) + message( + STATUS + "CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON}" + ) + # gersemi: off + set(CACHE{CMAKE_CXX_STDLIB_MODULES_JSON} + TYPE FILEPATH + HELP "Result of: clang++ -print-file-name=c++/libc++.modules.json" + VALUE ${CMAKE_CXX_STDLIB_MODULES_JSON} + ) + # gersemi: on + else() + message( + FATAL_ERROR + "File does NOT EXISTS! ${CMAKE_CXX_STDLIB_MODULES_JSON}" + ) + endif() +endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 688bb05..94cbb31 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,19 +1,26 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.28...4.3) -# TODO: Set BEMAN_USE_MODULES if one of a particular set of compiler versions is being used +cmake_minimum_required(VERSION 3.30...4.3) -if(BEMAN_USE_MODULES) - set(CMAKE_CXX_SCAN_FOR_MODULES ON) - set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD - "d0edc3af-4c50-42ea-a356-e2862fe7a444" - ) -endif() +include(../cmake/prelude.cmake) + +# if(BEMAN_USE_MODULES) +# set(CMAKE_CXX_SCAN_FOR_MODULES ON) +# set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD +# "d0edc3af-4c50-42ea-a356-e2862fe7a444" +# ) +# endif() project(beman.transform_view.example LANGUAGES CXX) if(PROJECT_IS_TOP_LEVEL) + include(../cmake/cxx-modules-rules.cmake) + find_package(beman.transform_view 0.1.0 EXACT REQUIRED) + + # XXX option(BEMAN_TRANSFORM_VIEW_IMPORT_STD "Use import std;" ${BEMAN_HAS_IMPORT_STD}) + + enable_testing() endif() set(ALL_EXAMPLES transform_view_direct_usage) @@ -29,9 +36,14 @@ foreach(example ${ALL_EXAMPLES}) if(BEMAN_USE_MODULES) target_compile_features( beman.transform_view.examples.${example} - PUBLIC cxx_std_23 + PUBLIC cxx_std_${CMAKE_CXX_STANDARD} ) - # XXX set_target_properties(beman.transform_view.examples.${example} PROPERTIES CXX_MODULE_STD ON) + if(BEMAN_USE_STD_MODULE) + set_target_properties( + beman.transform_view.examples.${example} + PROPERTIES CXX_MODULE_STD ON + ) + endif() target_link_libraries( beman.transform_view.examples.${example} PRIVATE beman::transform_view_module diff --git a/examples/transform_view_direct_usage.cpp b/examples/transform_view_direct_usage.cpp index d05af6a..af5cb51 100644 --- a/examples/transform_view_direct_usage.cpp +++ b/examples/transform_view_direct_usage.cpp @@ -1,8 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else #include #include #include +#endif #ifdef BEMAN_HAS_MODULES import beman.transform_view; diff --git a/infra/cmake/beman-install-library.cmake b/infra/cmake/beman-install-library.cmake index f8673f4..5fcf92f 100644 --- a/infra/cmake/beman-install-library.cmake +++ b/infra/cmake/beman-install-library.cmake @@ -260,8 +260,11 @@ function(beman_install_library name) FILE_SET ${_module_sets} DESTINATION "${BEMAN_DESTINATION}" COMPONENT "${install_component_name}_Development" + # There's currently no convention for this location CXX_MODULES_BMI COMPONENT "${install_component_name}_Development" + DESTINATION + ${_config_install_dir}/bmi-${CMAKE_CXX_COMPILER_ID}_$ ) else() install( diff --git a/src/beman/transform_view/transform_view.cppm b/src/beman/transform_view/transform_view.cppm index 2437206..a385c1b 100644 --- a/src/beman/transform_view/transform_view.cppm +++ b/src/beman/transform_view/transform_view.cppm @@ -1,6 +1,6 @@ module; -#ifndef BEMAN_HAS_STD_MODULES +#ifndef BEMAN_HAS_IMPORT_STD #include #include #include From 0418493778b519b06638f5fbff45030891958cde Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Mar 2026 21:28:27 +0100 Subject: [PATCH 5/8] Add find-install-test too --- CMakeLists.txt | 9 +- CMakePresets.json | 39 +++++- cmake/cxx-modules-rules.cmake | 14 +-- examples/CMakeLists.txt | 9 +- infra/cmake/beman-install-library.cmake | 146 ++++++++++------------ tests/beman/transform_view/CMakeLists.txt | 41 ++++++ 6 files changed, 147 insertions(+), 111 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 856b5fe..1f66d11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,13 +4,6 @@ cmake_minimum_required(VERSION 3.30...4.3) include(./cmake/prelude.cmake) -# if(BEMAN_USE_MODULES) -# set(CMAKE_CXX_SCAN_FOR_MODULES ON) -# set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD -# "d0edc3af-4c50-42ea-a356-e2862fe7a444" -# ) -# endif() - project( beman.transform_view # CMake Project Name, which is also the name of the top-level # targets (e.g., library, executable, etc.). @@ -58,7 +51,7 @@ if(BEMAN_USE_MODULES) beman.transform_view_module PUBLIC cxx_std_${CMAKE_CXX_STANDARD} ) - if(BEMAN_USE_STD_MODULE) + if(BEMAN_HAS_IMPORT_STD) target_compile_definitions( beman.transform_view_module PUBLIC BEMAN_HAS_IMPORT_STD diff --git a/CMakePresets.json b/CMakePresets.json index e13f76e..f216563 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -10,13 +10,28 @@ "BEMAN_USE_MODULES": true, "BEMAN_USE_STD_MODULE": true, "CMAKE_CXX_STANDARD": "23", - "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", - "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "./infra/cmake/use-fetch-content.cmake" + "CMAKE_CXX_EXTENSIONS": true, + "CMAKE_CXX_STANDARD_REQUIRED": true, + "CMAKE_EXPORT_COMPILE_COMMANDS": true, + "CMAKE_INSTALL_MESSAGE": "LAZY", + "CMAKE_SKIP_TEST_ALL_DEPENDENCY": false, + "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "infra/cmake/use-fetch-content.cmake" } }, { "name": "_debug-base", "hidden": true, + "warnings": { + "dev": true, + "deprecated": true, + "uninitialized": true, + "unusedCli": true, + "systemVars": false + }, + "errors": { + "dev": false, + "deprecated": false + }, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "BEMAN_BUILDSYS_SANITIZER": "MaxSan" @@ -60,6 +75,10 @@ ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-libc++-toolchain.cmake" + }, + "environment": { + "CXX": "clang++", + "CMAKE_CXX_FLAGS": "-stdlib=libc++" } }, { @@ -71,6 +90,10 @@ ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-libc++-toolchain.cmake" + }, + "environment": { + "CXX": "clang++", + "CMAKE_CXX_FLAGS": "-stdlib=libc++" } }, { @@ -81,6 +104,7 @@ "_debug-base" ], "cacheVariables": { + "BEMAN_USE_STD_MODULE": false, "BEMAN_USE_MODULES": false, "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" } @@ -93,6 +117,7 @@ "_release-base" ], "cacheVariables": { + "BEMAN_USE_STD_MODULE": false, "BEMAN_USE_MODULES": false, "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" } @@ -106,6 +131,11 @@ ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/msvc-toolchain.cmake" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" } }, { @@ -117,6 +147,11 @@ ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/msvc-toolchain.cmake" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" } } ], diff --git a/cmake/cxx-modules-rules.cmake b/cmake/cxx-modules-rules.cmake index 91939b3..458b3d6 100644 --- a/cmake/cxx-modules-rules.cmake +++ b/cmake/cxx-modules-rules.cmake @@ -86,10 +86,6 @@ if(CMAKE_CXX_STDLIB_MODULES_JSON) ) endif() -if(NOT DEFINED CMAKE_CXX_MODULE_STD) - set(CMAKE_CXX_MODULE_STD OFF) -endif() - if(CMAKE_CXX_STANDARD GREATER_EQUAL 20) option(BEMAN_USE_MODULES "Build CXX_MODULES" ${CMAKE_CXX_SCAN_FOR_MODULES}) endif() @@ -112,25 +108,23 @@ if(BEMAN_USE_MODULES AND BEMAN_USE_STD_MODULE) "CMAKE_CXX_COMPILER_IMPORT_STD=${CMAKE_CXX_COMPILER_IMPORT_STD}" ) if(${CMAKE_CXX_STANDARD} IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD) - set(CMAKE_CXX_MODULE_STD ON) set(CMAKE_CXX_SCAN_FOR_MODULES ON) option( BEMAN_HAS_IMPORT_STD "Build with import std; is possible and used!" - ${CMAKE_CXX_MODULE_STD} + ${BEMAN_USE_STD_MODULE} ) - message(STATUS "CMAKE_CXX_MODULE_STD=${CMAKE_CXX_MODULE_STD}") else() + set(BEMAN_HAS_IMPORT_STD OFF) set(CMAKE_CXX_MODULE_STD OFF) message(WARNING "CMAKE_CXX_MODULE_STD=${CMAKE_CXX_MODULE_STD}") endif() - message(STATUS "BEMAN_HAS_IMPORT_STD=${BEMAN_HAS_IMPORT_STD}") endif() if(NOT BEMAN_USE_MODULES) - set(CMAKE_CXX_SCAN_FOR_MODULES OFF) + set(BEMAN_HAS_IMPORT_STD OFF) endif() -message(STATUS "CMAKE_CXX_SCAN_FOR_MODULES=${CMAKE_CXX_SCAN_FOR_MODULES}") +message(STATUS "BEMAN_HAS_IMPORT_STD=${BEMAN_HAS_IMPORT_STD}") # ------------------------------------------------------------------------------ # Avoid creating CMAKE_..._OUTPUT_DIRECTORY as cache variables, they should not diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 94cbb31..c7baa32 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,13 +4,6 @@ cmake_minimum_required(VERSION 3.30...4.3) include(../cmake/prelude.cmake) -# if(BEMAN_USE_MODULES) -# set(CMAKE_CXX_SCAN_FOR_MODULES ON) -# set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD -# "d0edc3af-4c50-42ea-a356-e2862fe7a444" -# ) -# endif() - project(beman.transform_view.example LANGUAGES CXX) if(PROJECT_IS_TOP_LEVEL) @@ -38,7 +31,7 @@ foreach(example ${ALL_EXAMPLES}) beman.transform_view.examples.${example} PUBLIC cxx_std_${CMAKE_CXX_STANDARD} ) - if(BEMAN_USE_STD_MODULE) + if(BEMAN_HAS_IMPORT_STD) set_target_properties( beman.transform_view.examples.${example} PROPERTIES CXX_MODULE_STD ON diff --git a/infra/cmake/beman-install-library.cmake b/infra/cmake/beman-install-library.cmake index 5fcf92f..22224fc 100644 --- a/infra/cmake/beman-install-library.cmake +++ b/infra/cmake/beman-install-library.cmake @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +cmake_minimum_required(VERSION 3.30) + include_guard(GLOBAL) include(CMakePackageConfigHelpers) @@ -15,11 +17,11 @@ include(GNUInstallDirs) # ------ # beman_install_library( # TARGETS [ ...] -# [DEPENDENCY [] [EXACT]] -# [DEPENDENCY ...] +# [DEPENDENCIES [ ...]] # [NAMESPACE ] # [EXPORT_NAME ] # [DESTINATION ] +# [VERSION_SUFFIX] # ) # # Arguments: @@ -32,16 +34,11 @@ include(GNUInstallDirs) # TARGETS (required) # List of CMake targets to install. # -# DEPENDENCY (optional, repeatable) -# A dependency to add as a find_dependency() call in the generated config -# file. Each DEPENDENCY keyword starts a new entry; all tokens up to the -# next keyword are passed as arguments to find_dependency(). May be -# specified multiple times. -# -# Example: -# DEPENDENCY beman.inplace_vector 1.0.0 -# DEPENDENCY beman.scope 0.0.1 EXACT -# DEPENDENCY fmt +# DEPENDENCIES (optional) +# Semicolon-separated list, one dependency per entry. +# Each entry is a valid find_dependency() argument list. +# Note: you must use the bracket form for quoting if not only a package name is used! +# "[===[beman.inplace_vector 1.0.0]===] [===[beman.scope 0.0.1 EXACT]===] fmt" # # NAMESPACE (optional) # Namespace for exported targets. @@ -55,6 +52,9 @@ include(GNUInstallDirs) # The install destination for CXX_MODULES. # Defaults to ${CMAKE_INSTALL_LIBDIR}/cmake/${name}/modules. # +# VERSION_SUFFIX (optional) +# option to enable the versioning of install destinations +# # Brief # ----- # @@ -88,59 +88,16 @@ function(beman_install_library name) # ---------------------------- # Argument parsing # ---------------------------- - - # Pre-process ARGN to extract repeated DEPENDENCY entries, since - # cmake_parse_arguments does not support repeated keywords. - set(_known_keywords - TARGETS DEPENDENCY NAMESPACE EXPORT_NAME DESTINATION - ) - set(_dependencies "") - set(_filtered_args "") - set(_in_dep FALSE) - set(_current_dep "") - - foreach(_token ${ARGN}) - if(_token STREQUAL "DEPENDENCY") - # Flush previous dependency if any - if(_in_dep AND NOT "${_current_dep}" STREQUAL "") - list(APPEND _dependencies "${_current_dep}") - endif() - set(_in_dep TRUE) - set(_current_dep "") - elseif(_in_dep AND "${_token}" IN_LIST _known_keywords) - # Hit another keyword; flush current dep and pass token through - if(NOT "${_current_dep}" STREQUAL "") - list(APPEND _dependencies "${_current_dep}") - endif() - set(_in_dep FALSE) - set(_current_dep "") - list(APPEND _filtered_args "${_token}") - elseif(_in_dep) - # Accumulate tokens as space-separated find_dependency() args - if("${_current_dep}" STREQUAL "") - set(_current_dep "${_token}") - else() - string(APPEND _current_dep " ${_token}") - endif() - else() - list(APPEND _filtered_args "${_token}") - endif() - endforeach() - # Flush final dependency - if(_in_dep AND NOT "${_current_dep}" STREQUAL "") - list(APPEND _dependencies "${_current_dep}") - endif() - - set(options "") + set(options VERSION_SUFFIX) set(oneValueArgs NAMESPACE EXPORT_NAME DESTINATION) - set(multiValueArgs TARGETS) + set(multiValueArgs TARGETS DEPENDENCIES) cmake_parse_arguments( BEMAN "${options}" "${oneValueArgs}" "${multiValueArgs}" - ${_filtered_args} + ${ARGN} ) if(NOT BEMAN_TARGETS) @@ -158,7 +115,20 @@ function(beman_install_library name) return() endif() - set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}") + # gersemi: off + set(_version_suffix) + set(_include_install_dir) + set(_lib_install_dir) + set(_bin_install_dir) + # NOTE: If one of this variables is not set, the default DESTINATION is used! CK + if(BEMAN_VERSION_SUFFIX) + set(_version_suffix "-${PROJECT_VERSION}") + set(_include_install_dir DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/beman${_version_suffix}) + # set(_lib_install_dir DESTINATION ${CMAKE_INSTALL_LIBDIR}/beman${_version_suffix}) + # set(_bin_install_dir DESTINATION ${CMAKE_INSTALL_BINDIR}/beman${_version_suffix}) + endif() + set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}${_version_suffix}") + # gersemi: on # ---------------------------- # Defaults @@ -227,10 +197,10 @@ function(beman_install_library name) ) foreach(_install_header_set IN LISTS _available_header_sets) list( - APPEND - _install_header_set_args + APPEND _install_header_set_args FILE_SET "${_install_header_set}" + ${_include_install_dir} COMPONENT "${install_component_name}_Development" ) @@ -250,32 +220,37 @@ function(beman_install_library name) TARGETS "${_tgt}" EXPORT ${BEMAN_EXPORT_NAME} ARCHIVE + ${_lib_install_dir} COMPONENT "${install_component_name}_Development" LIBRARY + ${_lib_install_dir} COMPONENT "${install_component_name}_Runtime" NAMELINK_COMPONENT "${install_component_name}_Development" RUNTIME + ${_bin_install_dir} COMPONENT "${install_component_name}_Runtime" ${_install_header_set_args} FILE_SET ${_module_sets} DESTINATION "${BEMAN_DESTINATION}" COMPONENT "${install_component_name}_Development" - # There's currently no convention for this location + # NOTE: There's currently no convention for this location! CK CXX_MODULES_BMI + DESTINATION ${_config_install_dir}/bmi-${CMAKE_CXX_COMPILER_ID}_$ COMPONENT "${install_component_name}_Development" - DESTINATION - ${_config_install_dir}/bmi-${CMAKE_CXX_COMPILER_ID}_$ ) else() install( TARGETS "${_tgt}" EXPORT ${BEMAN_EXPORT_NAME} ARCHIVE + ${_lib_install_dir} COMPONENT "${install_component_name}_Development" LIBRARY + ${_lib_install_dir} COMPONENT "${install_component_name}_Runtime" NAMELINK_COMPONENT "${install_component_name}_Development" RUNTIME + ${_bin_install_dir} COMPONENT "${install_component_name}_Runtime" ${_install_header_set_args} ) @@ -297,42 +272,47 @@ function(beman_install_library name) # ---------------------------------------- # Config file installation logic - # - # Precedence (highest to lowest): - # 1. Per-package variable _INSTALL_CONFIG_FILE_PACKAGE - # 2. Allow-list BEMAN_INSTALL_CONFIG_FILE_PACKAGES (if defined) - # 3. Default: ON # ---------------------------------------- string(TOUPPER "${name}" _pkg_upper) string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") - set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") + option( + ${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE + "Enable creating and installing a CMake config-file package. Default: ON. Values: { ON, OFF }." + ON + ) - # Default: install config files - set(_install_config ON) + set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") - # If the allow-list is defined, only install for packages in the list - if(DEFINED BEMAN_INSTALL_CONFIG_FILE_PACKAGES) - if(NOT "${name}" IN_LIST BEMAN_INSTALL_CONFIG_FILE_PACKAGES) - set(_install_config OFF) - endif() + if(NOT DEFINED ${_pkg_var}) + set(${_pkg_var} + OFF + CACHE BOOL + "Install CMake package config files for ${name}" + ) endif() - # Per-package override takes highest precedence - if(DEFINED ${_pkg_var}) - set(_install_config ${${_pkg_var}}) + set(_install_config OFF) + + if(${_pkg_var}) + set(_install_config ON) + elseif(BEMAN_INSTALL_CONFIG_FILE_PACKAGES) + list(FIND BEMAN_INSTALL_CONFIG_FILE_PACKAGES "${name}" _idx) + if(NOT _idx EQUAL -1) + set(_install_config ON) + endif() endif() # ---------------------------------------- # expand dependencies # ---------------------------------------- set(_beman_find_deps "") - foreach(_dep IN LISTS _dependencies) + foreach(dep IN ITEMS ${BEMAN_DEPENDENCIES}) message( VERBOSE - "beman-install-library(${name}): Add find_dependency(${_dep})" + "beman-install-library(${name}): Add find_dependency(${dep})" ) - string(APPEND _beman_find_deps "find_dependency(${_dep})\n") + string(APPEND _beman_find_deps "find_dependency(${dep})\n") endforeach() set(BEMAN_FIND_DEPENDENCIES "${_beman_find_deps}") diff --git a/tests/beman/transform_view/CMakeLists.txt b/tests/beman/transform_view/CMakeLists.txt index f9eca79..c6f80ec 100644 --- a/tests/beman/transform_view/CMakeLists.txt +++ b/tests/beman/transform_view/CMakeLists.txt @@ -26,3 +26,44 @@ endif() include(GoogleTest) gtest_discover_tests(beman.transform_view.tests.transform_view) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + return() +endif() + +#====================================================================== +# NOTE: Only for Release build with enabled install rules useful! CK +#====================================================================== +if( + BEMAN_TRANSFORM_VIEW_INSTALL_CONFIG_FILE_PACKAGE + AND NOT CMAKE_SKIP_INSTALL_RULES +) + # test if the targets are usable from the install directory + add_test( + NAME install-to-stagedir + COMMAND + ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --prefix + ${CMAKE_BINARY_DIR}/stagedir --config $ + ) + add_test( + NAME find-package-test + COMMAND + ${CMAKE_CTEST_COMMAND} # --verbose + --output-on-failure -C $ # + --build-and-test "${CMAKE_SOURCE_DIR}/examples" + "${CMAKE_CURRENT_BINARY_DIR}/find-package-test" # + --build-generator ${CMAKE_GENERATOR} # + --build-makeprogram ${CMAKE_MAKE_PROGRAM} # + --build-options # + "-D BEMAN_USE_MODULES=${BEMAN_USE_MODULES}" + "-D BEMAN_USE_STD_MODULE=${BEMAN_USE_STD_MODULE}" + "-D CMAKE_BUILD_TYPE=$" + "-D CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" + "-D CMAKE_CXX_EXTENSIONS=${CMAKE_CXX_EXTENSIONS}" + "-D CMAKE_CXX_MODULE_STD=${CMAKE_CXX_MODULE_STD}" + "-D CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" + "-D CMAKE_CXX_STANDARD_REQUIRED=${CMAKE_CXX_STANDARD_REQUIRED}" + "-D CMAKE_PREFIX_PATH=${CMAKE_BINARY_DIR}/stagedir" + "-D CMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" + ) +endif() From bbf8cfe9d8015f7c3e58b68aa41fc2bc0f930f69 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Mar 2026 22:05:53 +0100 Subject: [PATCH 6/8] Only to show the problem --- CMakeLists.txt | 5 +++-- examples/CMakeLists.txt | 2 -- examples/transform_view_direct_usage.cpp | 3 ++- include/beman/transform_view/transform_view.hpp | 2 +- src/beman/transform_view/transform_view.cppm | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f66d11..e92fbaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ include(./cmake/cxx-modules-rules.cmake) option( BEMAN_TRANSFORM_VIEW_BUILD_TESTS "Enable building tests and test infrastructure. Default: ${PROJECT_IS_TOP_LEVEL}. Values: { ON, OFF }." - ${PROJECT_IS_TOP_LEVEL} + OFF #XXX ${PROJECT_IS_TOP_LEVEL} ) # [CMAKE.SKIP_EXAMPLES] @@ -73,7 +73,8 @@ endif() # NOT needed! include(CTest) enable_testing() -beman_install_library(beman.transform_view TARGETS beman.transform_view beman.transform_view_module) +#XXX beman_install_library(beman.transform_view TARGETS beman.transform_view beman.transform_view_module) +beman_install_library(beman.transform_view TARGETS beman.transform_view_module) if(BEMAN_TRANSFORM_VIEW_BUILD_TESTS) add_subdirectory(tests/beman/transform_view) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c7baa32..4b0c783 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -11,8 +11,6 @@ if(PROJECT_IS_TOP_LEVEL) find_package(beman.transform_view 0.1.0 EXACT REQUIRED) - # XXX option(BEMAN_TRANSFORM_VIEW_IMPORT_STD "Use import std;" ${BEMAN_HAS_IMPORT_STD}) - enable_testing() endif() diff --git a/examples/transform_view_direct_usage.cpp b/examples/transform_view_direct_usage.cpp index af5cb51..43564ae 100644 --- a/examples/transform_view_direct_usage.cpp +++ b/examples/transform_view_direct_usage.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifdef BEMAN_HAS_IMPORT_STD +#ifdef BEMAN_HAS_STD_MODULE import std; #else #include @@ -17,6 +17,7 @@ import beman.transform_view; namespace tv26 = beman::transform_view; int main() { + // TODO(CK): warning: C-style casts are discouraged; use static_cast auto to_lower = [](char c) { return char(c + 0x20); }; const std::string upper_str = "LOWER"; diff --git a/include/beman/transform_view/transform_view.hpp b/include/beman/transform_view/transform_view.hpp index 147719b..c551820 100644 --- a/include/beman/transform_view/transform_view.hpp +++ b/include/beman/transform_view/transform_view.hpp @@ -3,7 +3,7 @@ #ifndef BEMAN_TRANSFORM_VIEW_HPP #define BEMAN_TRANSFORM_VIEW_HPP -#ifndef BEMAN_HAS_STD_MODULES +#ifndef BEMAN_HAS_STD_MODULE #include #include #include diff --git a/src/beman/transform_view/transform_view.cppm b/src/beman/transform_view/transform_view.cppm index a385c1b..d0c403e 100644 --- a/src/beman/transform_view/transform_view.cppm +++ b/src/beman/transform_view/transform_view.cppm @@ -1,6 +1,6 @@ module; -#ifndef BEMAN_HAS_IMPORT_STD +#ifndef BEMAN_HAS_STD_MODULE #include #include #include From ed84681525f4ffd046a1e188240593929154ec11 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 9 Mar 2026 21:24:04 +0100 Subject: [PATCH 7/8] Make it works again --- CMakeLists.txt | 11 +++++++---- infra/cmake/beman-install-library.cmake | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e92fbaf..c27f60d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ include(./cmake/cxx-modules-rules.cmake) option( BEMAN_TRANSFORM_VIEW_BUILD_TESTS "Enable building tests and test infrastructure. Default: ${PROJECT_IS_TOP_LEVEL}. Values: { ON, OFF }." - OFF #XXX ${PROJECT_IS_TOP_LEVEL} + ${PROJECT_IS_TOP_LEVEL} ) # [CMAKE.SKIP_EXAMPLES] @@ -64,17 +64,20 @@ if(BEMAN_USE_MODULES) target_sources( beman.transform_view_module - PUBLIC FILE_SET HEADERS BASE_DIRS include + PUBLIC + FILE_SET HEADERS + BASE_DIRS include + FILES include/beman/transform_view/transform_view.hpp ) add_subdirectory(src/beman/transform_view) endif() +# NOTE: CTest.cmake creates a lot of unused target here! CK # NOT needed! include(CTest) enable_testing() -#XXX beman_install_library(beman.transform_view TARGETS beman.transform_view beman.transform_view_module) -beman_install_library(beman.transform_view TARGETS beman.transform_view_module) +beman_install_library(beman.transform_view TARGETS beman.transform_view beman.transform_view_module) if(BEMAN_TRANSFORM_VIEW_BUILD_TESTS) add_subdirectory(tests/beman/transform_view) diff --git a/infra/cmake/beman-install-library.cmake b/infra/cmake/beman-install-library.cmake index 22224fc..c5e3686 100644 --- a/infra/cmake/beman-install-library.cmake +++ b/infra/cmake/beman-install-library.cmake @@ -307,7 +307,7 @@ function(beman_install_library name) # expand dependencies # ---------------------------------------- set(_beman_find_deps "") - foreach(dep IN ITEMS ${BEMAN_DEPENDENCIES}) + foreach(dep IN LISTS BEMAN_DEPENDENCIES) message( VERBOSE "beman-install-library(${name}): Add find_dependency(${dep})" From 73f010a139d574828efad1939775f0d4321ff17f Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 9 Mar 2026 21:27:21 +0100 Subject: [PATCH 8/8] Set VERIFY_INTERFACE_HEADER_SETS only if ${PROJECT_IS_TOP_LEVEL} --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c27f60d..01c7ffa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ target_sources(beman.transform_view PUBLIC FILE_SET HEADERS BASE_DIRS include) set_target_properties( beman.transform_view - PROPERTIES VERIFY_INTERFACE_HEADER_SETS ON + PROPERTIES VERIFY_INTERFACE_HEADER_SETS ${PROJECT_IS_TOP_LEVEL} ) add_subdirectory(include/beman/transform_view)