From 04035cabfbedc938f9c11992a54a97c2b68b1f18 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Sun, 1 Feb 2026 23:56:45 +0100 Subject: [PATCH 01/22] Refactory beman-install-library.cmake --- CMakeLists.txt | 26 +- ...beman-install-library-config-package.cmake | 197 +++++++++++++++ cmake/beman-install-library-config.cmake | 40 +-- cmake/beman-install-library.cmake | 232 ++++++++++++++++++ cmake/beman-install-project-targets.cmake | 177 +++++++++++++ src/beman/execution/CMakeLists.txt | 8 +- 6 files changed, 648 insertions(+), 32 deletions(-) create mode 100644 cmake/beman-install-library-config-package.cmake create mode 100644 cmake/beman-install-library.cmake create mode 100644 cmake/beman-install-project-targets.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 095c67d2..6f1170f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,33 +26,32 @@ if(BEMAN_USE_MODULES) # CMake requires the language standard to be specified as compile feature # when a target provides C++23 modules and the target will be installed - add_library(beman.execution STATIC) - add_library(beman::execution ALIAS beman.execution) + add_library(${TARGET_PREFIX} STATIC) + add_library(beman::execution ALIAS ${TARGET_PREFIX}) target_compile_features( - beman.execution + ${TARGET_PREFIX} PUBLIC cxx_std_${CMAKE_CXX_STANDARD} ) include(GenerateExportHeader) - generate_export_header( - beman.execution - BASE_NAME beman.execution + ${TARGET_PREFIX} + BASE_NAME ${TARGET_PREFIX} EXPORT_FILE_NAME beman/execution/modules_export.hpp ) target_sources( - beman.execution + ${TARGET_PREFIX} PUBLIC FILE_SET HEADERS BASE_DIRS include ${CMAKE_CURRENT_BINARY_DIR} FILES ${CMAKE_CURRENT_BINARY_DIR}/beman/execution/modules_export.hpp ) - # FIXME: target_compile_definitions(beman.execution PUBLIC BEMAN_HAS_MODULES) + target_compile_definitions(${TARGET_PREFIX} PUBLIC BEMAN_HAS_MODULES) endif() if(BEMAN_USE_MODULES AND CMAKE_CXX_MODULE_STD) - target_compile_definitions(beman.execution PUBLIC BEMAN_HAS_IMPORT_STD) + target_compile_definitions(${TARGET_PREFIX} PUBLIC BEMAN_HAS_IMPORT_STD) else() message(WARNING "Missing support for CMAKE_CXX_MODULE_STD!") endif() @@ -72,9 +71,14 @@ option( add_subdirectory(src/beman/execution) +#=============================================================================== # NOTE: this must be done before tests! CK -include(./cmake/beman-install-library-config.cmake) -beman_install_library(${TARGET_PREFIX} headers) +# XXX include(./cmake/beman-install-library-config.cmake) +# XXX beman_install_library(${TARGET_PREFIX} INTERFACE) +# TODO: include(./cmake/beman-install-project-targets.cmake) +include(./cmake/beman-install-library.cmake) +beman_install_library(${TARGET_PREFIX} TARGETS ${TARGET_NAME} ${TARGET_PREFIX}) +#=============================================================================== if(BEMAN_EXECUTION_ENABLE_TESTING) enable_testing() diff --git a/cmake/beman-install-library-config-package.cmake b/cmake/beman-install-library-config-package.cmake new file mode 100644 index 00000000..7761ece8 --- /dev/null +++ b/cmake/beman-install-library-config-package.cmake @@ -0,0 +1,197 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +cmake_minimum_required(VERSION 4.0) + +include_guard(GLOBAL) + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +# beman_install_library +# ===================== +# +# Installs a library (or set of targets) along with headers, C++ modules, +# and optional CMake package configuration files. +# +# Usage: +# ------ +# beman_install_library( +# TARGETS target1 [target2 ...] +# [NAMESPACE ] +# [EXPORT_NAME ] +# [DESTINATION ] +# ) +# +# Arguments: +# ---------- +# name +# Logical package name (e.g. "beman.utility"). +# Used to derive config file names and cache variable prefixes. +# +# TARGETS (required) +# List of CMake targets to install. +# +# NAMESPACE (optional) +# Namespace for exported targets. +# Defaults to "beman::". +# +# EXPORT_NAME (optional) +# Name of the CMake export set. +# Defaults to "-targets". +# +# DESTINATION (optional) +# Base install destination. +# Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. +# +# Cache variables: +# ---------------- +# BEMAN_INSTALL_CONFIG_FILE_PACKAGES +# List of package names for which config files should be installed. +# +# _INSTALL_CONFIG_FILE_PACKAGE +# Per-package override to enable/disable config file installation. +# is the uppercased package name with dots replaced by underscores. +# +function(beman_install_library name) + # ---------------------------- + # Argument parsing + # ---------------------------- + set(options) + set(oneValueArgs NAMESPACE EXPORT_NAME DESTINATION) + set(multiValueArgs TARGETS) + + cmake_parse_arguments( + BEMAN + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" + ${ARGN} + ) + + if(NOT BEMAN_TARGETS) + message( + FATAL_ERROR + "beman_install_library(${name}): TARGETS must be specified" + ) + endif() + + # ---------------------------- + # Defaults + # ---------------------------- + if(NOT BEMAN_NAMESPACE) + set(BEMAN_NAMESPACE "beman::") + endif() + + if(NOT BEMAN_EXPORT_NAME) + set(BEMAN_EXPORT_NAME "${name}-targets") + endif() + + if(NOT BEMAN_DESTINATION) + set(BEMAN_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/beman/modules") + endif() + + if(CMAKE_SKIP_INSTALL_RULES) + message( + WARNING + "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" + ) + return() + endif() + + # ---------------------------------------- + # Install targets and headers (always) + # ---------------------------------------- + install( + TARGETS ${BEMAN_TARGETS} + EXPORT ${BEMAN_EXPORT_NAME} + ARCHIVE # DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY # DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} + FILE_SET + HEADERS # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + + # ---------------------------------------- + # Conditionally install C++ modules + # ---------------------------------------- + foreach(_tgt IN LISTS BEMAN_TARGETS) + if(NOT TARGET "${_tgt}") + message( + FATAL_ERROR + "beman_install_library(${name}): '${_tgt}' is not a target" + ) + endif() + + get_target_property(_module_sets "${_tgt}" CXX_MODULE_SETS) + + if(_module_sets) + install( + TARGETS "${_tgt}" + FILE_SET CXX_MODULES DESTINATION "${BEMAN_DESTINATION}" + ) + endif() + endforeach() + + # -------------------------------------------------- + # Export targets + # -------------------------------------------------- + install( + EXPORT ${BEMAN_EXPORT_NAME} + NAMESPACE ${BEMAN_NAMESPACE} + CXX_MODULES_DIRECTORY + cxx-modules + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${name} + ) + + # ---------------------------------------- + # Config file installation logic + # ---------------------------------------- + string(TOUPPER "${name}" _pkg_upper) + string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") + + set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") + + if(NOT DEFINED ${_pkg_var}) + set(${_pkg_var} + OFF + CACHE BOOL + "Install CMake package config files for ${name}" + ) + endif() + + 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() + + # ---------------------------------------- + # Generate + install config files + # ---------------------------------------- + if(_install_config) + set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}") + + configure_package_config_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${name}-config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" + INSTALL_DESTINATION ${_config_install_dir} + ) + + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion + ) + + install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" + DESTINATION ${_config_install_dir} + ) + endif() +endfunction() diff --git a/cmake/beman-install-library-config.cmake b/cmake/beman-install-library-config.cmake index 4ad27ff2..dc0aca2e 100644 --- a/cmake/beman-install-library-config.cmake +++ b/cmake/beman-install-library-config.cmake @@ -1,9 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +cmake_minimum_required(VERSION 4.0) + include_guard(GLOBAL) # This file defines the function `beman_install_library` which is used to -# install a library target and its headers, along with optional CMake -# configuration files. +# install a library target and its headers and modules, along with optional +# CMake configuration files. # # The function is designed to be reusable across different Beman libraries. @@ -11,13 +13,17 @@ function(beman_install_library name interface) # Usage # ----- # - # beman_install_library(NAME INTERFACE) + # beman_install_library(project_name TARGETS ... DESTINATION) # # Brief # ----- # - # This function installs the specified library target and its headers. - # It also handles the installation of the CMake configuration files if needed. + # This function installs the specified project TARGETS and its FILE_SET + # HEADERS to the default CMAKE install Destination. + # + # It also handles the installation of the CMake config package files if + # needed. If the given targets has FILE_SET CXX_MODULE, it will also + # installed to the given DESTINATION # # CMake variables # --------------- @@ -37,6 +43,7 @@ function(beman_install_library name interface) # replaced by underscores. # + # NOTE: in case of an interface only, the name is the project name! CK # if(NOT TARGET "${name}") # message(FATAL_ERROR "Target '${name}' does not exist.") # endif() @@ -58,14 +65,11 @@ function(beman_install_library name interface) "beman_install_library expects a name of the form 'beman.', got '${name}'" ) endif() - set(target_name "${name}") - # COMPONENT # Specify an installation component name with which the install rule is associated, # such as Runtime or Development. set(install_component_name "${name}") # TODO(CK): this is not common name! - set(export_name "${name}") set(package_name "${name}") list(GET name_parts -1 component_name) @@ -106,25 +110,27 @@ function(beman_install_library name interface) endif() if(interface AND TARGET "${target_name}_${interface}") + set(target "${target_name}_${interface}") + set_target_properties( - "${target_name}_${interface}" + "${target}" PROPERTIES EXPORT_NAME "${component_name}_${interface}" ) message( VERBOSE "beman-install-library: COMPONENT ${component_name} for TARGET '${name}_${interface}'" ) - list(APPEND target_list "${target_name}_${interface}") + list(APPEND target_list "${target}") get_target_property( INTERFACE_HEADER_SETS - ${target_name}_${interface} + ${target} INTERFACE_HEADER_SETS ) if(INTERFACE_HEADER_SETS) message( VERBOSE - "beman-install-library: '${target_name}_${interface}' has INTERFACE_HEADER_SETS=${INTERFACE_HEADER_SETS}" + "beman-install-library: '${target}' has INTERFACE_HEADER_SETS=${INTERFACE_HEADER_SETS}" ) set(__INSTALL_HEADER_SETS FILE_SET ${INTERFACE_HEADER_SETS}) endif() @@ -143,11 +149,11 @@ function(beman_install_library name interface) TARGETS ${target_list} COMPONENT "${install_component_name}" EXPORT "${export_name}" - FILE_SET HEADERS - ${__INSTALL_HEADER_SETS} - # FILE_SET CXX_MODULES - # DESTINATION ${package_install_dir}/modules - ${__INSTALL_CXX_MODULES} + # FILE_SET HEADERS + ${__INSTALL_HEADER_SETS} + # FILE_SET CXX_MODULES + # DESTINATION ${package_install_dir}/modules + ${__INSTALL_CXX_MODULES} # There's currently no convention for this location CXX_MODULES_BMI DESTINATION diff --git a/cmake/beman-install-library.cmake b/cmake/beman-install-library.cmake new file mode 100644 index 00000000..7cc85f49 --- /dev/null +++ b/cmake/beman-install-library.cmake @@ -0,0 +1,232 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +cmake_minimum_required(VERSION 4.0) + +include_guard(GLOBAL) + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +# beman_install_library +# ===================== +# +# Installs a library (or set of targets) along with headers, C++ modules, +# and optional CMake package configuration files. +# +# Usage: +# ------ +# beman_install_library( +# TARGETS target1 [target2 ...] +# [NAMESPACE ] +# [EXPORT_NAME ] +# [DESTINATION ] +# ) +# +# Arguments: +# ---------- +# name +# Logical package name (e.g. "beman.utility"). +# Used to derive config file names and cache variable prefixes. +# +# TARGETS (required) +# List of CMake targets to install. +# +# NAMESPACE (optional) +# Namespace for exported targets. +# Defaults to "beman::". +# +# EXPORT_NAME (optional) +# Name of the CMake export set. +# Defaults to "-targets". +# +# DESTINATION (optional) +# Base install destination. +# Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. +# +# Brief +# ----- +# +# This function installs the specified project TARGETS and its FILE_SET +# HEADERS to the default CMAKE install Destination. +# +# It also handles the installation of the CMake config package files if +# needed. If the given targets has FILE_SET CXX_MODULE, it will also +# installed to the given DESTINATION +# +# Cache variables: +# ---------------- +# BEMAN_INSTALL_CONFIG_FILE_PACKAGES +# List of package names for which config files should be installed. +# +# _INSTALL_CONFIG_FILE_PACKAGE +# Per-package override to enable/disable config file installation. +# is the uppercased package name with dots replaced by underscores. +# +function(beman_install_library name) + # ---------------------------- + # Argument parsing + # ---------------------------- + set(options) + set(oneValueArgs NAMESPACE EXPORT_NAME DESTINATION) + set(multiValueArgs TARGETS) + + cmake_parse_arguments( + BEMAN + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" + ${ARGN} + ) + + if(NOT BEMAN_TARGETS) + message( + FATAL_ERROR + "beman_install_library(${name}): TARGETS must be specified" + ) + endif() + + # ---------------------------- + # Defaults + # ---------------------------- + if(NOT BEMAN_NAMESPACE) + set(BEMAN_NAMESPACE "beman::") + endif() + + if(NOT BEMAN_EXPORT_NAME) + set(BEMAN_EXPORT_NAME "${name}-targets") + endif() + + if(NOT BEMAN_DESTINATION) + set(BEMAN_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/beman/modules") + endif() + + if(CMAKE_SKIP_INSTALL_RULES) + message( + WARNING + "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" + ) + return() + endif() + + # -------------------------------------------------- + # Install each target with all of its file sets + # -------------------------------------------------- + foreach(_tgt IN LISTS BEMAN_TARGETS) + if(NOT TARGET "${_tgt}") + message( + WARNING + "beman_install_library(${name}): '${_tgt}' is not a target" + ) + continue() + endif() + + # Given foo.bar, the component name is bar + string(REPLACE "." ";" name_parts "${_tgt}") + # fail if the name doesn't look like foo.bar + list(LENGTH name_parts name_parts_length) + if(NOT name_parts_length EQUAL 2) + message( + FATAL_ERROR + "beman_install_library(${name}): expects a name of the form 'beman.', got '${_tgt}'" + ) + endif() + list(GET name_parts -1 component_name) + set_target_properties( + "${_tgt}" + PROPERTIES EXPORT_NAME "${component_name}" + ) + message( + VERBOSE + "beman_install_library(${name}): COMPONENT ${component_name} for TARGET '${_tgt}'" + ) + + # Detect presence of C++ module file sets + get_target_property(_module_sets "${_tgt}" CXX_MODULE_SETS) + + if(_module_sets) + install( + TARGETS "${_tgt}" + EXPORT ${BEMAN_EXPORT_NAME} + ARCHIVE # DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY # DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} + FILE_SET + HEADERS # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILE_SET CXX_MODULES DESTINATION "${BEMAN_DESTINATION}" + ) + else() + install( + TARGETS "${_tgt}" + EXPORT ${BEMAN_EXPORT_NAME} + ARCHIVE # DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY # DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} + FILE_SET + HEADERS # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + endif() + endforeach() + + # -------------------------------------------------- + # Export targets + # -------------------------------------------------- + install( + EXPORT ${BEMAN_EXPORT_NAME} + NAMESPACE ${BEMAN_NAMESPACE} + CXX_MODULES_DIRECTORY + cxx-modules + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${name} + ) + + # ---------------------------------------- + # Config file installation logic + # ---------------------------------------- + string(TOUPPER "${name}" _pkg_upper) + string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") + + set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") + + if(NOT DEFINED ${_pkg_var}) + set(${_pkg_var} + OFF + CACHE BOOL + "Install CMake package config files for ${name}" + ) + endif() + + 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() + + # ---------------------------------------- + # Generate + install config files + # ---------------------------------------- + if(_install_config) + set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}") + + configure_package_config_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${name}-config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" + INSTALL_DESTINATION ${_config_install_dir} + ) + + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion + ) + + install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" + DESTINATION ${_config_install_dir} + ) + endif() +endfunction() diff --git a/cmake/beman-install-project-targets.cmake b/cmake/beman-install-project-targets.cmake new file mode 100644 index 00000000..3a2f9173 --- /dev/null +++ b/cmake/beman-install-project-targets.cmake @@ -0,0 +1,177 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +cmake_minimum_required(VERSION 4.0) + +include_guard(GLOBAL) + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +# beman_install_library +# ===================== +# +# Installs a library (or set of targets) along with headers, C++ modules, +# and optional CMake package configuration files. +# +# Usage: +# ------ +# beman_install_library( +# TARGETS target1 [target2 ...] +# [NAMESPACE ] +# [EXPORT_NAME ] +# [DESTINATION ] +# ) +# +# Arguments: +# ---------- +# name +# Logical package name (e.g. "beman.utility"). +# Used to derive config file names and cache variable prefixes. +# +# TARGETS (required) +# List of CMake targets to install. +# +# NAMESPACE (optional) +# Namespace for exported targets. +# Defaults to "beman::". +# +# EXPORT_NAME (optional) +# Name of the CMake export set. +# Defaults to "-targets". +# +# DESTINATION (optional) +# Base install destination. +# Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. +# +# Cache variables: +# ---------------- +# BEMAN_INSTALL_CONFIG_FILE_PACKAGES +# List of package names for which config files should be installed. +# +# _INSTALL_CONFIG_FILE_PACKAGE +# Per-package override to enable/disable config file installation. +# is the uppercased package name with dots replaced by underscores. +# +function(beman_install_library name) + # ---------------------------- + # Argument parsing + # ---------------------------- + set(options) + set(oneValueArgs NAMESPACE EXPORT_NAME DESTINATION) + set(multiValueArgs TARGETS) + + cmake_parse_arguments( + BEMAN + "${options}" + "${oneValueArgs}" + "${multiValueArgs}" + ${ARGN} + ) + + if(NOT BEMAN_TARGETS) + message( + FATAL_ERROR + "beman_install_library(${name}): TARGETS must be specified" + ) + endif() + + # ---------------------------- + # Defaults + # ---------------------------- + if(NOT BEMAN_NAMESPACE) + set(BEMAN_NAMESPACE "beman::") + endif() + + if(NOT BEMAN_EXPORT_NAME) + set(BEMAN_EXPORT_NAME "${name}-targets") + endif() + + if(NOT BEMAN_DESTINATION) + set(BEMAN_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/beman/modules") + endif() + + if(CMAKE_SKIP_INSTALL_RULES) + message( + WARNING + "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" + ) + return() + endif() + + # ---------------------------------------- + # Install targets and headers (always) + # ---------------------------------------- + install( + TARGETS ${BEMAN_TARGETS} + EXPORT ${BEMAN_EXPORT_NAME} + ARCHIVE # DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY # DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} + FILE_SET + HEADERS # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILE_SET CXX_MODULES DESTINATION "${BEMAN_DESTINATION}" + ) + + # -------------------------------------------------- + # Export targets + # -------------------------------------------------- + install( + EXPORT ${BEMAN_EXPORT_NAME} + NAMESPACE ${BEMAN_NAMESPACE} + CXX_MODULES_DIRECTORY + cxx-modules + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${name} + ) + + # ---------------------------------------- + # Config file installation logic + # ---------------------------------------- + string(TOUPPER "${name}" _pkg_upper) + string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") + + set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") + + if(NOT DEFINED ${_pkg_var}) + set(${_pkg_var} + OFF + CACHE BOOL + "Install CMake package config files for ${name}" + ) + endif() + + 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() + + # ---------------------------------------- + # Generate + install config files + # ---------------------------------------- + if(_install_config) + set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}") + + configure_package_config_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${name}-config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" + INSTALL_DESTINATION ${_config_install_dir} + ) + + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion + ) + + install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" + DESTINATION ${_config_install_dir} + ) + endif() +endfunction() diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt index 10774bac..6dce8a34 100644 --- a/src/beman/execution/CMakeLists.txt +++ b/src/beman/execution/CMakeLists.txt @@ -9,8 +9,8 @@ add_library(beman::execution_headers ALIAS ${TARGET_NAME}) target_sources( ${TARGET_NAME} PUBLIC - FILE_SET public_headers - TYPE HEADERS + FILE_SET # public_headers TYPE + HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include FILES ${PROJECT_SOURCE_DIR}/include/beman/execution/execution.hpp @@ -200,8 +200,8 @@ if(BEMAN_USE_MODULES) execution.cpp # TODO(CK): check if really needed! PUBLIC FILE_SET CXX_MODULES - BASE_DIRS ${PROJECT_SOURCE_DIR}/src/beman/execution - FILES ${PROJECT_SOURCE_DIR}/src/beman/execution/execution.cppm + BASE_DIRS ${CURRRENT_SOURCE_DIR} + FILES execution.cppm ) target_link_libraries(${TARGET_PREFIX} PUBLIC ${TARGET_NAME}) endif() From 20704e37d9073e7f06dc8758978d50e0946c7e00 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 2 Feb 2026 00:24:38 +0100 Subject: [PATCH 02/22] Add missing install option --- cmake/beman-install-library.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/beman-install-library.cmake b/cmake/beman-install-library.cmake index 7cc85f49..ef5dbd02 100644 --- a/cmake/beman-install-library.cmake +++ b/cmake/beman-install-library.cmake @@ -183,6 +183,12 @@ function(beman_install_library name) string(TOUPPER "${name}" _pkg_upper) string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") + option( + ${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE + "Enable creating and installing a CMake config-file package. Default: ON. Values: { ON, OFF }." + ON + ) + set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") if(NOT DEFINED ${_pkg_var}) From 8a30a5739b006eb19d62070169fcccb143897f06 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 2 Feb 2026 06:12:05 +0100 Subject: [PATCH 03/22] Include cpack too --- cmake/beman-install-library.cmake | 8 ++++++++ cmake/beman-install-project-targets.cmake | 24 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/cmake/beman-install-library.cmake b/cmake/beman-install-library.cmake index ef5dbd02..b04f7cfc 100644 --- a/cmake/beman-install-library.cmake +++ b/cmake/beman-install-library.cmake @@ -234,5 +234,13 @@ function(beman_install_library name) "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" DESTINATION ${_config_install_dir} ) + else() + message( + WARNING + "beman-install-library(${name}): Not installing a config package for '${name}'" + ) endif() endfunction() + +set(CPACK_GENERATOR TGZ) +include(CPack) diff --git a/cmake/beman-install-project-targets.cmake b/cmake/beman-install-project-targets.cmake index 3a2f9173..7533531e 100644 --- a/cmake/beman-install-project-targets.cmake +++ b/cmake/beman-install-project-targets.cmake @@ -42,6 +42,16 @@ include(GNUInstallDirs) # Base install destination. # Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. # +# Brief +# ----- +# +# This function installs the specified project TARGETS and its FILE_SET +# HEADERS to the default CMAKE install Destination. +# +# It also handles the installation of the CMake config package files if +# needed. If the given targets has FILE_SET CXX_MODULE, it will also +# installed to the given DESTINATION +# # Cache variables: # ---------------- # BEMAN_INSTALL_CONFIG_FILE_PACKAGES @@ -128,6 +138,12 @@ function(beman_install_library name) string(TOUPPER "${name}" _pkg_upper) string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") + option( + ${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE + "Enable creating and installing a CMake config-file package. Default: ON. Values: { ON, OFF }." + ON + ) + set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") if(NOT DEFINED ${_pkg_var}) @@ -173,5 +189,13 @@ function(beman_install_library name) "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" DESTINATION ${_config_install_dir} ) + else() + message( + WARNING + "beman-install-library(${name}): Not installing a config package for '${name}'" + ) endif() endfunction() + +set(CPACK_GENERATOR TGZ) +include(CPack) From ea36d7c55de880ce459f1ae245b26c4066f40f8d Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 2 Feb 2026 06:56:02 +0100 Subject: [PATCH 04/22] Fix: Not all CI workflow use newest cmake version --- cmake/beman-install-library-config-package.cmake | 2 +- cmake/beman-install-library-config.cmake | 2 +- cmake/beman-install-library.cmake | 2 +- cmake/beman-install-project-targets.cmake | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/beman-install-library-config-package.cmake b/cmake/beman-install-library-config-package.cmake index 7761ece8..cae72905 100644 --- a/cmake/beman-install-library-config-package.cmake +++ b/cmake/beman-install-library-config-package.cmake @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.0) +cmake_minimum_required(VERSION 3.30) include_guard(GLOBAL) diff --git a/cmake/beman-install-library-config.cmake b/cmake/beman-install-library-config.cmake index dc0aca2e..81e09da5 100644 --- a/cmake/beman-install-library-config.cmake +++ b/cmake/beman-install-library-config.cmake @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.0) +cmake_minimum_required(VERSION 3.30) include_guard(GLOBAL) diff --git a/cmake/beman-install-library.cmake b/cmake/beman-install-library.cmake index b04f7cfc..acfe65ca 100644 --- a/cmake/beman-install-library.cmake +++ b/cmake/beman-install-library.cmake @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.0) +cmake_minimum_required(VERSION 3.30) include_guard(GLOBAL) diff --git a/cmake/beman-install-project-targets.cmake b/cmake/beman-install-project-targets.cmake index 7533531e..73e01fc5 100644 --- a/cmake/beman-install-project-targets.cmake +++ b/cmake/beman-install-project-targets.cmake @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 4.0) +cmake_minimum_required(VERSION 3.30) include_guard(GLOBAL) From 7aafa44dc4122d105c395132d0ecdd1024c8c38d Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 2 Feb 2026 11:18:17 +0100 Subject: [PATCH 05/22] Fix: find-package-test is only useful for Release build --- infra/cmake/appleclang-toolchain.cmake | 4 ++-- infra/cmake/gnu-toolchain.cmake | 4 ++-- infra/cmake/llvm-toolchain.cmake | 4 ++-- infra/cmake/msvc-toolchain.cmake | 4 ++-- tests/beman/execution/CMakeLists.txt | 7 +++++++ 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/infra/cmake/appleclang-toolchain.cmake b/infra/cmake/appleclang-toolchain.cmake index 70ef548e..451c86b6 100644 --- a/infra/cmake/appleclang-toolchain.cmake +++ b/infra/cmake/appleclang-toolchain.cmake @@ -32,7 +32,7 @@ endif() set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") -set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") +set(RELEASE_FLAGS "-O3") set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") @@ -41,4 +41,4 @@ set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") # Add this dir to the module path so that `find_package(beman-install-library)` works -list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") +# NO! list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") diff --git a/infra/cmake/gnu-toolchain.cmake b/infra/cmake/gnu-toolchain.cmake index d3b9f92d..a946349d 100644 --- a/infra/cmake/gnu-toolchain.cmake +++ b/infra/cmake/gnu-toolchain.cmake @@ -29,7 +29,7 @@ endif() set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") -set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") +set(RELEASE_FLAGS "-O3") set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") @@ -38,4 +38,4 @@ set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") # Add this dir to the module path so that `find_package(beman-install-library)` works -list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") +# NO! list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") diff --git a/infra/cmake/llvm-toolchain.cmake b/infra/cmake/llvm-toolchain.cmake index f1623b7e..b0ca3bdb 100644 --- a/infra/cmake/llvm-toolchain.cmake +++ b/infra/cmake/llvm-toolchain.cmake @@ -29,7 +29,7 @@ endif() set(CMAKE_C_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG_INIT "${SANITIZER_FLAGS}") -set(RELEASE_FLAGS "-O3 ${SANITIZER_FLAGS}") +set(RELEASE_FLAGS "-O3") set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") @@ -38,4 +38,4 @@ set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") # Add this dir to the module path so that `find_package(beman-install-library)` works -list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") +# NO! list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") diff --git a/infra/cmake/msvc-toolchain.cmake b/infra/cmake/msvc-toolchain.cmake index bdc24de9..7bd82279 100644 --- a/infra/cmake/msvc-toolchain.cmake +++ b/infra/cmake/msvc-toolchain.cmake @@ -29,7 +29,7 @@ endif() set(CMAKE_CXX_FLAGS_DEBUG_INIT "/EHsc /permissive- ${SANITIZER_FLAGS}") set(CMAKE_C_FLAGS_DEBUG_INIT "/EHsc /permissive- ${SANITIZER_FLAGS}") -set(RELEASE_FLAGS "/EHsc /permissive- /O2 ${SANITIZER_FLAGS}") +set(RELEASE_FLAGS "/EHsc /permissive- /O2") set(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "${RELEASE_FLAGS}") @@ -38,4 +38,4 @@ set(CMAKE_C_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE_INIT "${RELEASE_FLAGS}") # Add this dir to the module path so that `find_package(beman-install-library)` works -list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") +# NO! list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}") diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index 65238e5c..35b07dea 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -122,6 +122,13 @@ foreach(test ${execution_tests}) add_test(NAME ${TEST_EXE} COMMAND $) endforeach() +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + return() +endif() + +#====================================================================== +# NOTE: Only for Release build with enabled install rules useful! CK +#====================================================================== if(BEMAN_EXECUTION_INSTALL_CONFIG_FILE_PACKAGE AND NOT CMAKE_SKIP_INSTALL_RULES) # test if the targets are usable from the install directory add_test( From 551555832853ee9706c527f5085bed820b9a1268 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 2 Feb 2026 11:43:43 +0100 Subject: [PATCH 06/22] Cleanup --- examples/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c68e6e17..958b6df0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -43,7 +43,6 @@ foreach(EXAMPLE ${EXAMPLES}) add_executable(${EXAMPLE_TARGET}) target_sources(${EXAMPLE_TARGET} PRIVATE ${EXAMPLE}.cpp) if(BEMAN_USE_MODULES) - # target_compile_definitions(${EXAMPLE_TARGET} PUBLIC BEMAN_HAS_MODULES) target_link_libraries(${EXAMPLE_TARGET} PRIVATE beman::execution) else() target_link_libraries( From 642135cbc8c881c77f8b827f6e98972529f620cf Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 2 Feb 2026 12:58:25 +0100 Subject: [PATCH 07/22] Feat: test Release.Dynamic on CI --- .github/workflows/ci_tests.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index d6b9c64f..351cb387 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -40,9 +40,9 @@ jobs: "tests": [ { "stdlibs": ["libstdc++"], "tests": [ - "Debug.Default", "Release.Default", - "Release.MaxSan", "Debug.Werror", - "Debug.Dynamic", "Debug.Coverage" + "Debug.Default", "Debug.Coverage", + "Debug.MaxSan", "Debug.Werror", + "Release.Default", "Release.Dynamic" ] } ] @@ -67,8 +67,8 @@ jobs: "tests": [ { "stdlibs": ["libc++"], "tests": [ - "Debug.Default", "Release.Default", "Release.MaxSan", - "Debug.Dynamic" + "Debug.Default", "Debug.MaxSan", + "Release.Default", "Release.Dynamic" ] } ] @@ -96,7 +96,10 @@ jobs: { "cxxversions": ["c++23"], "tests": [ { "stdlibs": ["stl"], - "tests": ["Debug.Default", "Release.Default", "Release.MaxSan"] + "tests": [ + "Debug.Default", "Debug.MaxSan", + "Release.Default", "Release.Dynamic" + ] } ] } From d6eb7d2e8d3342a0566346e6f0125de28429e657 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Mon, 2 Feb 2026 15:21:12 +0100 Subject: [PATCH 08/22] Add support named FILE_SET TYPE HEADERS --- CMakeLists.txt | 3 --- cmake/beman-install-library.cmake | 29 ++++++++++++++++++++++++----- src/beman/execution/CMakeLists.txt | 6 +++--- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f1170f1..55919c73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,9 +73,6 @@ add_subdirectory(src/beman/execution) #=============================================================================== # NOTE: this must be done before tests! CK -# XXX include(./cmake/beman-install-library-config.cmake) -# XXX beman_install_library(${TARGET_PREFIX} INTERFACE) -# TODO: include(./cmake/beman-install-project-targets.cmake) include(./cmake/beman-install-library.cmake) beman_install_library(${TARGET_PREFIX} TARGETS ${TARGET_NAME} ${TARGET_PREFIX}) #=============================================================================== diff --git a/cmake/beman-install-library.cmake b/cmake/beman-install-library.cmake index acfe65ca..848f6ff7 100644 --- a/cmake/beman-install-library.cmake +++ b/cmake/beman-install-library.cmake @@ -39,7 +39,7 @@ include(GNUInstallDirs) # Defaults to "-targets". # # DESTINATION (optional) -# Base install destination. +# The install destination for CXX_MODULES. # Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. # # Brief @@ -107,6 +107,8 @@ function(beman_install_library name) return() endif() + string(REPLACE "beman." "" install_component_name "${name}") + # -------------------------------------------------- # Install each target with all of its file sets # -------------------------------------------------- @@ -139,29 +141,44 @@ function(beman_install_library name) "beman_install_library(${name}): COMPONENT ${component_name} for TARGET '${_tgt}'" ) - # Detect presence of C++ module file sets - get_target_property(_module_sets "${_tgt}" CXX_MODULE_SETS) + # Get the list of interface header sets, exact one expected! + get_target_property(_header_sets ${_tgt} INTERFACE_HEADER_SETS) + if(_header_sets) + message( + VERBOSE + "beman-install-library(${name}): '${_tgt}' has INTERFACE_HEADER_SETS=${_header_sets}" + ) + # XXX set(__INSTALL_HEADER_SETS FILE_SET ${_header_sets}) + endif() + # Detect presence of C++ module file sets, exact one expected! + get_target_property(_module_sets "${_tgt}" CXX_MODULE_SETS) if(_module_sets) + message( + VERBOSE + "beman-install-library(${name}): '${_tgt}' has CXX_MODULE_SETS=${_module_sets}" + ) install( TARGETS "${_tgt}" + COMPONENT "${install_component_name}" EXPORT ${BEMAN_EXPORT_NAME} ARCHIVE # DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY # DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} FILE_SET - HEADERS # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ${_header_sets} # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILE_SET CXX_MODULES DESTINATION "${BEMAN_DESTINATION}" ) else() install( TARGETS "${_tgt}" + COMPONENT "${install_component_name}" EXPORT ${BEMAN_EXPORT_NAME} ARCHIVE # DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY # DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} FILE_SET - HEADERS # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ${_header_sets} # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) endif() endforeach() @@ -175,6 +192,7 @@ function(beman_install_library name) CXX_MODULES_DIRECTORY cxx-modules DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${name} + COMPONENT "${install_component_name}" ) # ---------------------------------------- @@ -233,6 +251,7 @@ function(beman_install_library name) "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" DESTINATION ${_config_install_dir} + COMPONENT "${install_component_name}" ) else() message( diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt index 6dce8a34..1558ca95 100644 --- a/src/beman/execution/CMakeLists.txt +++ b/src/beman/execution/CMakeLists.txt @@ -9,8 +9,8 @@ add_library(beman::execution_headers ALIAS ${TARGET_NAME}) target_sources( ${TARGET_NAME} PUBLIC - FILE_SET # public_headers TYPE - HEADERS + FILE_SET public_headers + TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include FILES ${PROJECT_SOURCE_DIR}/include/beman/execution/execution.hpp @@ -200,7 +200,7 @@ if(BEMAN_USE_MODULES) execution.cpp # TODO(CK): check if really needed! PUBLIC FILE_SET CXX_MODULES - BASE_DIRS ${CURRRENT_SOURCE_DIR} + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES execution.cppm ) target_link_libraries(${TARGET_PREFIX} PUBLIC ${TARGET_NAME}) From 7e9f98babcbc7bd54710d80885d48563b4f249dc Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Tue, 3 Feb 2026 18:31:40 +0100 Subject: [PATCH 09/22] Build with import std; --- Makefile | 16 +- ...beman-install-library-config-package.cmake | 31 ++- cmake/beman-install-library-config.cmake | 257 ------------------ cmake/beman-install-project-targets.cmake | 6 +- cmake/cxx-modules-rules.cmake | 2 +- 5 files changed, 46 insertions(+), 266 deletions(-) delete mode 100644 cmake/beman-install-library-config.cmake diff --git a/Makefile b/Makefile index 6549b0d8..23dddc01 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ SANITIZERS := run # SANITIZERS += asan # TODO: tsan msan # endif -.PHONY: default release debug doc run update check ce todo distclean clean codespell clang-tidy build test install all format unstage $(SANITIZERS) module build-module test-module +.PHONY: default release debug doc run update check ce todo distclean clean codespell clang-tidy build test install all format unstage $(SANITIZERS) module build-module test-module build-interface SYSROOT ?= TOOLCHAIN ?= @@ -99,7 +99,7 @@ endif # TODO: beman.execution.examples.modules # FIXME: beman.execution.execution-module.test beman.execution.stop-token-module.test -default: release +default: module all: $(SANITIZERS) @@ -116,7 +116,7 @@ doc: # ========================================================== # NOTE: cmake configure to only test without modules! CK # ========================================================== -build: +build build-interface: cmake -G Ninja -S $(SOURCEDIR) -B $(BUILD) $(TOOLCHAIN) $(SYSROOT) \ -D CMAKE_EXPORT_COMPILE_COMMANDS=ON \ -D CMAKE_SKIP_INSTALL_RULES=ON \ @@ -126,9 +126,11 @@ build: -D CMAKE_CXX_SCAN_FOR_MODULES=OFF \ -D BEMAN_USE_MODULES=OFF \ -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_SKIP_TEST_ALL_DEPENDENCY=OFF \ -D CMAKE_CXX_COMPILER=$(CXX) --log-level=VERBOSE - cmake --build $(BUILD) -# XXX --fresh -D CMAKE_CXX_FLAGS="$(CXX_FLAGS) $(SAN_FLAGS)" + # XXX --fresh -D CMAKE_CXX_FLAGS="$(CXX_FLAGS) $(SAN_FLAGS)" + cmake --build $(BUILD) --target all_verify_interface_header_sets + cmake --build $(BUILD) --target all # NOTE: without install, see CMAKE_SKIP_INSTALL_RULES! CK test: build @@ -137,13 +139,15 @@ test: build module build-module: cmake -G Ninja -S $(SOURCEDIR) -B $(BUILD) $(TOOLCHAIN) $(SYSROOT) \ -D CMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -D CMAKE_SKIP_INSTALL_RULES=ON \ + -D CMAKE_SKIP_INSTALL_RULES=OFF \ -D CMAKE_CXX_STANDARD=23 \ -D CMAKE_CXX_EXTENSIONS=ON \ -D CMAKE_CXX_STANDARD_REQUIRED=ON \ -D CMAKE_CXX_SCAN_FOR_MODULES=ON \ -D BEMAN_USE_MODULES=ON \ -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_INSTALL_MESSAGE=LAZY \ + -D CMAKE_BUILD_TYPE=Release \ -D CMAKE_CXX_COMPILER=$(CXX) --log-level=VERBOSE cmake --build $(BUILD) diff --git a/cmake/beman-install-library-config-package.cmake b/cmake/beman-install-library-config-package.cmake index cae72905..fcc2601c 100644 --- a/cmake/beman-install-library-config-package.cmake +++ b/cmake/beman-install-library-config-package.cmake @@ -39,9 +39,19 @@ include(GNUInstallDirs) # Defaults to "-targets". # # DESTINATION (optional) -# Base install destination. +# The install destination for CXX_MODULES. # Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. # +# Brief +# ----- +# +# This function installs the specified project TARGETS and its FILE_SET +# HEADERS to the default CMAKE install Destination. +# +# It also handles the installation of the CMake config package files if +# needed. If the given targets has FILE_SET CXX_MODULE, it will also +# installed to the given DESTINATION +# # Cache variables: # ---------------- # BEMAN_INSTALL_CONFIG_FILE_PACKAGES @@ -97,6 +107,8 @@ function(beman_install_library name) return() endif() + string(REPLACE "beman." "" install_component_name "${name}") + # ---------------------------------------- # Install targets and headers (always) # ---------------------------------------- @@ -121,6 +133,7 @@ function(beman_install_library name) ) endif() + # Detect presence of C++ module file sets, exact one expected! get_target_property(_module_sets "${_tgt}" CXX_MODULE_SETS) if(_module_sets) @@ -140,6 +153,7 @@ function(beman_install_library name) CXX_MODULES_DIRECTORY cxx-modules DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${name} + COMPONENT "${install_component_name}" ) # ---------------------------------------- @@ -148,6 +162,12 @@ function(beman_install_library name) string(TOUPPER "${name}" _pkg_upper) string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") + option( + ${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE + "Enable creating and installing a CMake config-file package. Default: ON. Values: { ON, OFF }." + ON + ) + set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") if(NOT DEFINED ${_pkg_var}) @@ -192,6 +212,15 @@ function(beman_install_library name) "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" DESTINATION ${_config_install_dir} + COMPONENT "${install_component_name}" + ) + else() + message( + WARNING + "beman-install-library(${name}): Not installing a config package for '${name}'" ) endif() endfunction() + +set(CPACK_GENERATOR TGZ) +include(CPack) diff --git a/cmake/beman-install-library-config.cmake b/cmake/beman-install-library-config.cmake deleted file mode 100644 index 81e09da5..00000000 --- a/cmake/beman-install-library-config.cmake +++ /dev/null @@ -1,257 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.30) - -include_guard(GLOBAL) - -# This file defines the function `beman_install_library` which is used to -# install a library target and its headers and modules, along with optional -# CMake configuration files. -# -# The function is designed to be reusable across different Beman libraries. - -function(beman_install_library name interface) - # Usage - # ----- - # - # beman_install_library(project_name TARGETS ... DESTINATION) - # - # Brief - # ----- - # - # This function installs the specified project TARGETS and its FILE_SET - # HEADERS to the default CMAKE install Destination. - # - # It also handles the installation of the CMake config package files if - # needed. If the given targets has FILE_SET CXX_MODULE, it will also - # installed to the given DESTINATION - # - # CMake variables - # --------------- - # - # Note that configuration of the installation is generally controlled by CMake - # cache variables so that they can be controlled by the user or tool running the - # `cmake` command. Neither `CMakeLists.txt` nor `*.cmake` files should set these - # variables directly. - # - # - BEMAN_INSTALL_CONFIG_FILE_PACKAGES: - # List of packages that require config file installation. - # If the package name is in this list, it will install the config file. - # - # - _INSTALL_CONFIG_FILE_PACKAGE: - # Boolean to control config file installation for the specific library. - # The prefix `` is the uppercased name of the library with dots - # replaced by underscores. - # - - # NOTE: in case of an interface only, the name is the project name! CK - # if(NOT TARGET "${name}") - # message(FATAL_ERROR "Target '${name}' does not exist.") - # endif() - - # if(NOT ARGN STREQUAL "") - # message( - # FATAL_ERROR - # "beman_install_library does not accept extra arguments: ${ARGN}" - # ) - # endif() - - # Given foo.bar, the component name is bar - string(REPLACE "." ";" name_parts "${name}") - # fail if the name doesn't look like foo.bar - list(LENGTH name_parts name_parts_length) - if(NOT name_parts_length EQUAL 2) - message( - FATAL_ERROR - "beman_install_library expects a name of the form 'beman.', got '${name}'" - ) - endif() - set(target_name "${name}") - # COMPONENT - # Specify an installation component name with which the install rule is associated, - # such as Runtime or Development. - set(install_component_name "${name}") # TODO(CK): this is not common name! - set(export_name "${name}") - set(package_name "${name}") - list(GET name_parts -1 component_name) - - include(GNUInstallDirs) - - set(package_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${package_name}") - - set(target_list) - if(TARGET "${target_name}") - set_target_properties( - "${target_name}" - PROPERTIES EXPORT_NAME "${component_name}" - ) - message( - VERBOSE - "beman-install-library: COMPONENT ${component_name} for TARGET '${target_name}'" - ) - list(APPEND target_list "${target_name}") - - get_target_property( - INTERFACE_CXX_MODULE_SETS - ${target_name} - INTERFACE_CXX_MODULE_SETS - ) - if(INTERFACE_CXX_MODULE_SETS) - message( - VERBOSE - "beman-install-library: '${target_name}' has INTERFACE_CXX_MODULE_SETS=${INTERFACE_CXX_MODULE_SETS}" - ) - set(__INSTALL_CXX_MODULES - FILE_SET - ${INTERFACE_CXX_MODULE_SETS} - DESTINATION - ${package_install_dir}/modules - ) - endif() - endif() - - if(interface AND TARGET "${target_name}_${interface}") - set(target "${target_name}_${interface}") - - set_target_properties( - "${target}" - PROPERTIES EXPORT_NAME "${component_name}_${interface}" - ) - message( - VERBOSE - "beman-install-library: COMPONENT ${component_name} for TARGET '${name}_${interface}'" - ) - list(APPEND target_list "${target}") - - get_target_property( - INTERFACE_HEADER_SETS - ${target} - INTERFACE_HEADER_SETS - ) - if(INTERFACE_HEADER_SETS) - message( - VERBOSE - "beman-install-library: '${target}' has INTERFACE_HEADER_SETS=${INTERFACE_HEADER_SETS}" - ) - set(__INSTALL_HEADER_SETS FILE_SET ${INTERFACE_HEADER_SETS}) - endif() - endif() - - if(CMAKE_SKIP_INSTALL_RULES) - message( - WARNING - "beman-install-library: not installing targets '${target_list}' due to CMAKE_SKIP_INSTALL_RULES" - ) - return() - endif() - - # ============================================================ - install( - TARGETS ${target_list} - COMPONENT "${install_component_name}" - EXPORT "${export_name}" - # FILE_SET HEADERS - ${__INSTALL_HEADER_SETS} - # FILE_SET CXX_MODULES - # DESTINATION ${package_install_dir}/modules - ${__INSTALL_CXX_MODULES} - # There's currently no convention for this location - CXX_MODULES_BMI - DESTINATION - ${package_install_dir}/bmi-${CMAKE_CXX_COMPILER_ID}_$ - ) - # ============================================================ - - # Determine the prefix for project-specific variables - string(TOUPPER "${name}" project_prefix) - string(REPLACE "." "_" project_prefix "${project_prefix}") - - option( - ${project_prefix}_INSTALL_CONFIG_FILE_PACKAGE - "Enable creating and installing a CMake config-file package. Default: ON. Values: { ON, OFF }." - ON - ) - - # By default, install the config package - set(install_config_package ON) - - # Turn OFF installation of config package by default if, - # in order of precedence: - # 1. The specific package variable is set to OFF - # 2. The package name is not in the list of packages to install config files - if(DEFINED BEMAN_INSTALL_CONFIG_FILE_PACKAGES) - if( - NOT "${install_component_name}" - IN_LIST - BEMAN_INSTALL_CONFIG_FILE_PACKAGES - ) - set(install_config_package OFF) - endif() - endif() - if(DEFINED ${project_prefix}_INSTALL_CONFIG_FILE_PACKAGE) - set(install_config_package - ${${project_prefix}_INSTALL_CONFIG_FILE_PACKAGE} - ) - endif() - - if(install_config_package) - message( - VERBOSE - "beman-install-library: Export cmake config to ${package_install_dir} for '${name}'" - ) - - include(CMakePackageConfigHelpers) - - find_file( - config_file_template - NAMES "${package_name}-config.cmake.in" - PATHS "${PROJECT_SOURCE_DIR}/cmake" - NO_DEFAULT_PATH - NO_CACHE - REQUIRED - ) - set(config_package_file - "${CMAKE_CURRENT_BINARY_DIR}/${package_name}-config.cmake" - ) - configure_package_config_file( - "${config_file_template}" - "${config_package_file}" - INSTALL_DESTINATION "${package_install_dir}" - PATH_VARS PROJECT_NAME PROJECT_VERSION - ) - - set(config_version_file - "${CMAKE_CURRENT_BINARY_DIR}/${package_name}-config-version.cmake" - ) - write_basic_package_version_file( - "${config_version_file}" - VERSION "${PROJECT_VERSION}" - COMPATIBILITY ExactVersion - ) - - install( - FILES "${config_package_file}" "${config_version_file}" - DESTINATION "${package_install_dir}" - COMPONENT "${install_component_name}" - ) - - # NOTE: must be same value as ${TARGETS_EXPORT_NAME}.cmake! CK - set(config_targets_file "${package_name}-targets.cmake") - install( - EXPORT "${export_name}" - DESTINATION "${package_install_dir}" - NAMESPACE beman:: - FILE "${config_targets_file}" - CXX_MODULES_DIRECTORY - cxx-modules - COMPONENT "${install_component_name}" - ) - else() - message( - WARNING - "beman-install-library: Not installing a config package for '${name}'" - ) - endif() -endfunction() - -set(CPACK_GENERATOR TGZ) -include(CPack) diff --git a/cmake/beman-install-project-targets.cmake b/cmake/beman-install-project-targets.cmake index 73e01fc5..41969b3a 100644 --- a/cmake/beman-install-project-targets.cmake +++ b/cmake/beman-install-project-targets.cmake @@ -39,7 +39,7 @@ include(GNUInstallDirs) # Defaults to "-targets". # # DESTINATION (optional) -# Base install destination. +# The install destination for CXX_MODULES. # Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. # # Brief @@ -107,6 +107,8 @@ function(beman_install_library name) return() endif() + string(REPLACE "beman." "" install_component_name "${name}") + # ---------------------------------------- # Install targets and headers (always) # ---------------------------------------- @@ -130,6 +132,7 @@ function(beman_install_library name) CXX_MODULES_DIRECTORY cxx-modules DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${name} + COMPONENT "${install_component_name}" ) # ---------------------------------------- @@ -188,6 +191,7 @@ function(beman_install_library name) "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" DESTINATION ${_config_install_dir} + COMPONENT "${install_component_name}" ) else() message( diff --git a/cmake/cxx-modules-rules.cmake b/cmake/cxx-modules-rules.cmake index 498131d1..6b081a5a 100644 --- a/cmake/cxx-modules-rules.cmake +++ b/cmake/cxx-modules-rules.cmake @@ -92,7 +92,7 @@ endif() option( BEMAN_USE_STD_MODULE "Check if 'import std;' is possible with the toolchain?" - OFF + ON ) message(STATUS "BEMAN_USE_STD_MODULE=${BEMAN_USE_STD_MODULE}") From 41ffe74c59b921cfa585a3ecf376c94716988086 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Thu, 5 Feb 2026 13:52:29 +0100 Subject: [PATCH 10/22] Add cmake/README file rm old cmake modules (was only experimental code!) --- CMakeLists.txt | 9 +- cmake/Config.cmake.in | 10 + cmake/README.md | 260 ++++++++++++++++++ ...beman-install-library-config-package.cmake | 226 --------------- cmake/beman-install-library.cmake | 50 +++- cmake/beman-install-project-targets.cmake | 205 -------------- cmake/beman.execution-config.cmake.in | 7 - cmake/cxx-modules-rules.cmake | 1 + cmake/prelude.cmake | 1 + 9 files changed, 315 insertions(+), 454 deletions(-) create mode 100644 cmake/Config.cmake.in create mode 100644 cmake/README.md delete mode 100644 cmake/beman-install-library-config-package.cmake delete mode 100644 cmake/beman-install-project-targets.cmake delete mode 100644 cmake/beman.execution-config.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 55919c73..5907ee0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,12 +74,15 @@ add_subdirectory(src/beman/execution) #=============================================================================== # NOTE: this must be done before tests! CK include(./cmake/beman-install-library.cmake) -beman_install_library(${TARGET_PREFIX} TARGETS ${TARGET_NAME} ${TARGET_PREFIX}) +beman_install_library(${TARGET_PREFIX} TARGETS ${TARGET_NAME} ${TARGET_PREFIX} + # FIXME: DEPENDENCIES [===[beman.inplace_vector 1.0.0]===] [===[beman.scope 0.0.1 EXACT]===] fmt + # TODO(CK): XXX OR XXX DEPENDENCIES "beman.inplace_vector 1.0.0;beman.scope 0.0.1 EXACT" +) #=============================================================================== -if(BEMAN_EXECUTION_ENABLE_TESTING) - enable_testing() +enable_testing() +if(BEMAN_EXECUTION_ENABLE_TESTING) add_subdirectory(tests/beman/execution) endif() diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in new file mode 100644 index 00000000..6a965772 --- /dev/null +++ b/cmake/Config.cmake.in @@ -0,0 +1,10 @@ +# cmake/Config.cmake.in -*-makefile-*- +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +include(CMakeFindDependencyMacro) + +@PACKAGE_INIT@ + +include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake) + +check_required_components(@PROJECT_NAME@) diff --git a/cmake/README.md b/cmake/README.md new file mode 100644 index 00000000..7b5a8106 --- /dev/null +++ b/cmake/README.md @@ -0,0 +1,260 @@ + + +# Create and install an interface library and the `CXX_MODULE` if possible + +To be able to compile a project with and without MODULES, the project needs at least 2 targets: + +- an interface library (header only) with one `PUBLIC FILE_SET HEADERS` +- a library (static and/or dynamic) with one `PUBLIC FILE_SET CXX_MODULE` + + +## NEW CMAKE modules intended to be in infra/cmake: + +- prelude.cmake +- cxx-modules-rules.cmake +- beman-install-library.cmake +- Config.cmake.in + + +## NEW added related CMake options: + + * BEMAN_USE_MODULES:BOOL=ON + * BEMAN_USE_STD_MODULE:BOOL=OFF + * BEMAN_HAS_IMPORT_STD::BOOL=${CMAKE_CXX_SCAN_FOR_MODULES} # only if toolchain supports it. + +### The recommended usage in CMake code + +```cmake +if(CMAKE_CXX_STANDARD GREATER_EQUAL 20) + option(BEMAN_USE_MODULES "Build CXX_MODULES" ${CMAKE_CXX_SCAN_FOR_MODULES}) +endif() +if(BEMAN_USE_MODULES) + target_compile_definitions(beman.execution PUBLIC BEMAN_HAS_MODULES) +endif() + +BEMAN_USE_STD_MODULE:BOOL=ON +# -> "Check if 'import std;' is possible with the toolchain?" + +if(BEMAN_USE_MODULES AND CMAKE_CXX_MODULE_STD) + target_compile_definitions(beman.execution PUBLIC BEMAN_HAS_IMPORT_STD) +endif() +``` + + +### beman_install_library + +Installs a library (or set of targets) along with headers, C++ modules, +and optional CMake package configuration files. + +#### Usage: + + beman_install_library( + TARGETS target1 [target2 ...] + DEPENDENCIES dependency1 [dependency2 ...] + [NAMESPACE ] + [EXPORT_NAME ] + [DESTINATION ] + ) + +#### Arguments: + +name + Logical package name (e.g. "beman.utility"). + Used to derive config file names and cache variable prefixes. + +TARGETS (required) + List of CMake targets to install. + +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. + Defaults to "beman::". + +EXPORT_NAME (optional) + Name of the CMake export set. + Defaults to "-targets". + +DESTINATION (optional) + The install destination for CXX_MODULES. + Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. + +#### Brief + +This function installs the specified project TARGETS and its FILE_SET +HEADERS to the default CMAKE install Destination. + +It also handles the installation of the CMake config package files if +needed. If the given targets has FILE_SET CXX_MODULE, it will also +installed to the given DESTINATION + +#### Cache variables: + +BEMAN_INSTALL_CONFIG_FILE_PACKAGES + List of package names for which config files should be installed. + +_INSTALL_CONFIG_FILE_PACKAGE + Per-package override to enable/disable config file installation. + is the uppercased package name with dots replaced by underscores. + + +## The possible usage in CMakeLists.txt + + include(./cmake/prelude.cmake) + project(beman.execution VERSION 0.2.0 LANGUAGES CXX) + include(./cmake/cxx-modules-rules.cmake) + + # NOTE: this must be done before tests! CK + include(beman-install-library) + beman_install_library(${PROJECT_NAME} TARGETS ${PROJECT_NAME} beman.exemplar_headers # + # TODO(add): DEPENDENCIES [===[beman.inplace_vector 1.0.0]===] [===[beman.scope 0.0.1 EXACT]===] fmt + ) + + +## Possible cmake config output + +```bash +bash-5.3$ make test-module +cmake -G Ninja -S /Users/clausklein/Workspace/cpp/beman-project/execution26 -B build/Darwin/default \ + -D CMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -D CMAKE_SKIP_INSTALL_RULES=OFF \ + -D CMAKE_CXX_STANDARD=23 \ + -D CMAKE_CXX_EXTENSIONS=ON \ + -D CMAKE_CXX_STANDARD_REQUIRED=ON \ + -D CMAKE_CXX_SCAN_FOR_MODULES=ON \ + -D BEMAN_USE_MODULES=ON \ + -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_INSTALL_MESSAGE=LAZY \ + -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_CXX_COMPILER=clang++ --log-level=VERBOSE +-- use ccache +-- CXXFLAGS=-stdlib=libc++ +'brew' '--prefix' 'llvm' +-- LLVM_DIR=/usr/local/Cellar/llvm/21.1.8 +-- CMAKE_CXX_STDLIB_MODULES_JSON=/usr/local/Cellar/llvm/21.1.8/lib/c++/libc++.modules.json +-- CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=/usr/local/Cellar/llvm/21.1.8/include/c++/v1;/usr/local/Cellar/llvm/21.1.8/lib/clang/21/include;/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/usr/include +-- CMAKE_CXX_STDLIB_MODULES_JSON=/usr/local/Cellar/llvm/21.1.8/lib/c++/libc++.modules.json +-- BEMAN_USE_STD_MODULE=ON +-- CMAKE_CXX_COMPILER_IMPORT_STD=23;26 +-- CMAKE_CXX_MODULE_STD=ON +-- BEMAN_HAS_IMPORT_STD=ON +-- BEMAN_USE_MODULES=ON +-- CMAKE_CXX_SCAN_FOR_MODULES=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 +-- beman_install_library(beman.execution): COMPONENT execution_headers for TARGET 'beman.execution_headers' +-- beman-install-library(beman.execution): 'beman.execution_headers' has INTERFACE_HEADER_SETS=public_headers +-- beman_install_library(beman.execution): COMPONENT execution for TARGET 'beman.execution' +-- beman-install-library(beman.execution): 'beman.execution' has INTERFACE_HEADER_SETS=HEADERS +-- beman-install-library(beman.execution): 'beman.execution' has CXX_MODULE_SETS=CXX_MODULES +-- Configuring done (3.1s) +CMake Warning (dev) in CMakeLists.txt: + CMake's support for `import std;` in C++23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +-- Generating done (0.4s) +-- Build files have been written to: /Users/clausklein/Workspace/cpp/beman-project/execution26/build/Darwin/default +bash-5.3$ +``` + + +## Possible cmake export config package + +```bash +cmake --install build/Darwin/default --prefix $PWD/stagedir + +bash-5.3$ cd stagedir/ +bash-5.3$ tree lib/ +lib/ +├── cmake +│   └── beman.execution +│   ├── beman.execution-config-version.cmake +│   ├── beman.execution-config.cmake +│   ├── beman.execution-targets-debug.cmake +│   ├── beman.execution-targets-relwithdebinfo.cmake +│   ├── beman.execution-targets.cmake +│   ├── bmi-GNU_Debug +│   │   └── beman.execution.gcm +│   ├── bmi-GNU_RelWithDebInfo +│   │   └── beman.execution.gcm +│   ├── cxx-modules +│   │   ├── cxx-modules-beman.execution-Debug.cmake +│   │   ├── cxx-modules-beman.execution-RelWithDebInfo.cmake +│   │   ├── cxx-modules-beman.execution.cmake +│   │   ├── target-execution-Debug.cmake +│   │   └── target-execution-RelWithDebInfo.cmake +│   └── modules +│   └── execution.cppm +├── libbeman.execution.a +└── libbeman.execution_d.a + +7 directories, 15 files +bash-5.3$ +``` + + +## The recommended usage in implementation + +```cpp +// identity.cppm +module; + +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#endif + +export module beman.exemplar; + +export namespace beman::exemplar { +struct __is_transparent; + +struct identity { + template + constexpr T&& operator()(T&& t) const noexcept { + return std::forward(t); + } + + using is_transparent = __is_transparent; +}; +} // namespace beman::exemplar +``` + + +## The possible usage in user code + +```cpp +// example-usage.cpp + +#ifdef BEMAN_HAS_IMPORT_STD +import std; +#else +#include +#endif + +#ifdef BEMAN_HAS_MODULES +import beman.exemplar; +#else +#include +#endif + +int main() { + beman::exemplar::identity id; + + int x = 42; + int y = id(x); // y == 42 + + std::cout << y << '\n'; + return 0; +} +``` diff --git a/cmake/beman-install-library-config-package.cmake b/cmake/beman-install-library-config-package.cmake deleted file mode 100644 index fcc2601c..00000000 --- a/cmake/beman-install-library-config-package.cmake +++ /dev/null @@ -1,226 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.30) - -include_guard(GLOBAL) - -include(CMakePackageConfigHelpers) -include(GNUInstallDirs) - -# beman_install_library -# ===================== -# -# Installs a library (or set of targets) along with headers, C++ modules, -# and optional CMake package configuration files. -# -# Usage: -# ------ -# beman_install_library( -# TARGETS target1 [target2 ...] -# [NAMESPACE ] -# [EXPORT_NAME ] -# [DESTINATION ] -# ) -# -# Arguments: -# ---------- -# name -# Logical package name (e.g. "beman.utility"). -# Used to derive config file names and cache variable prefixes. -# -# TARGETS (required) -# List of CMake targets to install. -# -# NAMESPACE (optional) -# Namespace for exported targets. -# Defaults to "beman::". -# -# EXPORT_NAME (optional) -# Name of the CMake export set. -# Defaults to "-targets". -# -# DESTINATION (optional) -# The install destination for CXX_MODULES. -# Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. -# -# Brief -# ----- -# -# This function installs the specified project TARGETS and its FILE_SET -# HEADERS to the default CMAKE install Destination. -# -# It also handles the installation of the CMake config package files if -# needed. If the given targets has FILE_SET CXX_MODULE, it will also -# installed to the given DESTINATION -# -# Cache variables: -# ---------------- -# BEMAN_INSTALL_CONFIG_FILE_PACKAGES -# List of package names for which config files should be installed. -# -# _INSTALL_CONFIG_FILE_PACKAGE -# Per-package override to enable/disable config file installation. -# is the uppercased package name with dots replaced by underscores. -# -function(beman_install_library name) - # ---------------------------- - # Argument parsing - # ---------------------------- - set(options) - set(oneValueArgs NAMESPACE EXPORT_NAME DESTINATION) - set(multiValueArgs TARGETS) - - cmake_parse_arguments( - BEMAN - "${options}" - "${oneValueArgs}" - "${multiValueArgs}" - ${ARGN} - ) - - if(NOT BEMAN_TARGETS) - message( - FATAL_ERROR - "beman_install_library(${name}): TARGETS must be specified" - ) - endif() - - # ---------------------------- - # Defaults - # ---------------------------- - if(NOT BEMAN_NAMESPACE) - set(BEMAN_NAMESPACE "beman::") - endif() - - if(NOT BEMAN_EXPORT_NAME) - set(BEMAN_EXPORT_NAME "${name}-targets") - endif() - - if(NOT BEMAN_DESTINATION) - set(BEMAN_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/beman/modules") - endif() - - if(CMAKE_SKIP_INSTALL_RULES) - message( - WARNING - "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" - ) - return() - endif() - - string(REPLACE "beman." "" install_component_name "${name}") - - # ---------------------------------------- - # Install targets and headers (always) - # ---------------------------------------- - install( - TARGETS ${BEMAN_TARGETS} - EXPORT ${BEMAN_EXPORT_NAME} - ARCHIVE # DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY # DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} - FILE_SET - HEADERS # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) - - # ---------------------------------------- - # Conditionally install C++ modules - # ---------------------------------------- - foreach(_tgt IN LISTS BEMAN_TARGETS) - if(NOT TARGET "${_tgt}") - message( - FATAL_ERROR - "beman_install_library(${name}): '${_tgt}' is not a target" - ) - endif() - - # Detect presence of C++ module file sets, exact one expected! - get_target_property(_module_sets "${_tgt}" CXX_MODULE_SETS) - - if(_module_sets) - install( - TARGETS "${_tgt}" - FILE_SET CXX_MODULES DESTINATION "${BEMAN_DESTINATION}" - ) - endif() - endforeach() - - # -------------------------------------------------- - # Export targets - # -------------------------------------------------- - install( - EXPORT ${BEMAN_EXPORT_NAME} - NAMESPACE ${BEMAN_NAMESPACE} - CXX_MODULES_DIRECTORY - cxx-modules - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${name} - COMPONENT "${install_component_name}" - ) - - # ---------------------------------------- - # Config file installation logic - # ---------------------------------------- - string(TOUPPER "${name}" _pkg_upper) - string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") - - option( - ${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE - "Enable creating and installing a CMake config-file package. Default: ON. Values: { ON, OFF }." - ON - ) - - set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") - - if(NOT DEFINED ${_pkg_var}) - set(${_pkg_var} - OFF - CACHE BOOL - "Install CMake package config files for ${name}" - ) - endif() - - 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() - - # ---------------------------------------- - # Generate + install config files - # ---------------------------------------- - if(_install_config) - set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}") - - configure_package_config_file( - "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${name}-config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" - INSTALL_DESTINATION ${_config_install_dir} - ) - - write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion - ) - - install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" - DESTINATION ${_config_install_dir} - COMPONENT "${install_component_name}" - ) - else() - message( - WARNING - "beman-install-library(${name}): Not installing a config package for '${name}'" - ) - endif() -endfunction() - -set(CPACK_GENERATOR TGZ) -include(CPack) diff --git a/cmake/beman-install-library.cmake b/cmake/beman-install-library.cmake index 848f6ff7..a73f4fc7 100644 --- a/cmake/beman-install-library.cmake +++ b/cmake/beman-install-library.cmake @@ -1,4 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + cmake_minimum_required(VERSION 3.30) include_guard(GLOBAL) @@ -16,6 +17,7 @@ include(GNUInstallDirs) # ------ # beman_install_library( # TARGETS target1 [target2 ...] +# DEPENDENCIES dependency1 [dependency2 ...] # [NAMESPACE ] # [EXPORT_NAME ] # [DESTINATION ] @@ -30,6 +32,12 @@ include(GNUInstallDirs) # TARGETS (required) # List of CMake targets to install. # +# 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. # Defaults to "beman::". @@ -67,7 +75,7 @@ function(beman_install_library name) # ---------------------------- set(options) set(oneValueArgs NAMESPACE EXPORT_NAME DESTINATION) - set(multiValueArgs TARGETS) + set(multiValueArgs TARGETS DEPENDENCIES) cmake_parse_arguments( BEMAN @@ -84,6 +92,16 @@ function(beman_install_library name) ) endif() + if(CMAKE_SKIP_INSTALL_RULES) + message( + WARNING + "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" + ) + return() + endif() + + set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}") + # ---------------------------- # Defaults # ---------------------------- @@ -96,15 +114,8 @@ function(beman_install_library name) endif() if(NOT BEMAN_DESTINATION) - set(BEMAN_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/beman/modules") - endif() - - if(CMAKE_SKIP_INSTALL_RULES) - message( - WARNING - "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" - ) - return() + # XXX set(BEMAN_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/beman/modules") + set(BEMAN_DESTINATION "${_config_install_dir}/modules") endif() string(REPLACE "beman." "" install_component_name "${name}") @@ -149,6 +160,8 @@ function(beman_install_library name) "beman-install-library(${name}): '${_tgt}' has INTERFACE_HEADER_SETS=${_header_sets}" ) # XXX set(__INSTALL_HEADER_SETS FILE_SET ${_header_sets}) + else() + set(_header_sets HEADERS) # Note: empty FILE_SET in this case! CK endif() # Detect presence of C++ module file sets, exact one expected! @@ -168,6 +181,9 @@ function(beman_install_library name) FILE_SET ${_header_sets} # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILE_SET CXX_MODULES DESTINATION "${BEMAN_DESTINATION}" + # NOTE: There's currently no convention for this location! CK + CXX_MODULES_BMI + # TODO(CK): DESTINATION ${_config_install_dir}/bmi-${CMAKE_CXX_COMPILER_ID}_$ ) else() install( @@ -228,14 +244,22 @@ function(beman_install_library name) endif() endif() + # ---------------------------------------- + # expand dependencies + # ---------------------------------------- + set(_beman_find_deps "") + foreach(dep IN ITEMS ${BEMAN_DEPENDENCIES}) + message(VERBOSE "Add find_dependency(${dep})") + string(APPEND _beman_find_deps "find_dependency(${dep})\n") + endforeach() + set(BEMAN_FIND_DEPENDENCIES "${_beman_find_deps}") + # ---------------------------------------- # Generate + install config files # ---------------------------------------- if(_install_config) - set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}") - configure_package_config_file( - "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${name}-config.cmake.in" + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" INSTALL_DESTINATION ${_config_install_dir} ) diff --git a/cmake/beman-install-project-targets.cmake b/cmake/beman-install-project-targets.cmake deleted file mode 100644 index 41969b3a..00000000 --- a/cmake/beman-install-project-targets.cmake +++ /dev/null @@ -1,205 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.30) - -include_guard(GLOBAL) - -include(CMakePackageConfigHelpers) -include(GNUInstallDirs) - -# beman_install_library -# ===================== -# -# Installs a library (or set of targets) along with headers, C++ modules, -# and optional CMake package configuration files. -# -# Usage: -# ------ -# beman_install_library( -# TARGETS target1 [target2 ...] -# [NAMESPACE ] -# [EXPORT_NAME ] -# [DESTINATION ] -# ) -# -# Arguments: -# ---------- -# name -# Logical package name (e.g. "beman.utility"). -# Used to derive config file names and cache variable prefixes. -# -# TARGETS (required) -# List of CMake targets to install. -# -# NAMESPACE (optional) -# Namespace for exported targets. -# Defaults to "beman::". -# -# EXPORT_NAME (optional) -# Name of the CMake export set. -# Defaults to "-targets". -# -# DESTINATION (optional) -# The install destination for CXX_MODULES. -# Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. -# -# Brief -# ----- -# -# This function installs the specified project TARGETS and its FILE_SET -# HEADERS to the default CMAKE install Destination. -# -# It also handles the installation of the CMake config package files if -# needed. If the given targets has FILE_SET CXX_MODULE, it will also -# installed to the given DESTINATION -# -# Cache variables: -# ---------------- -# BEMAN_INSTALL_CONFIG_FILE_PACKAGES -# List of package names for which config files should be installed. -# -# _INSTALL_CONFIG_FILE_PACKAGE -# Per-package override to enable/disable config file installation. -# is the uppercased package name with dots replaced by underscores. -# -function(beman_install_library name) - # ---------------------------- - # Argument parsing - # ---------------------------- - set(options) - set(oneValueArgs NAMESPACE EXPORT_NAME DESTINATION) - set(multiValueArgs TARGETS) - - cmake_parse_arguments( - BEMAN - "${options}" - "${oneValueArgs}" - "${multiValueArgs}" - ${ARGN} - ) - - if(NOT BEMAN_TARGETS) - message( - FATAL_ERROR - "beman_install_library(${name}): TARGETS must be specified" - ) - endif() - - # ---------------------------- - # Defaults - # ---------------------------- - if(NOT BEMAN_NAMESPACE) - set(BEMAN_NAMESPACE "beman::") - endif() - - if(NOT BEMAN_EXPORT_NAME) - set(BEMAN_EXPORT_NAME "${name}-targets") - endif() - - if(NOT BEMAN_DESTINATION) - set(BEMAN_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/beman/modules") - endif() - - if(CMAKE_SKIP_INSTALL_RULES) - message( - WARNING - "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" - ) - return() - endif() - - string(REPLACE "beman." "" install_component_name "${name}") - - # ---------------------------------------- - # Install targets and headers (always) - # ---------------------------------------- - install( - TARGETS ${BEMAN_TARGETS} - EXPORT ${BEMAN_EXPORT_NAME} - ARCHIVE # DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY # DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} - FILE_SET - HEADERS # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILE_SET CXX_MODULES DESTINATION "${BEMAN_DESTINATION}" - ) - - # -------------------------------------------------- - # Export targets - # -------------------------------------------------- - install( - EXPORT ${BEMAN_EXPORT_NAME} - NAMESPACE ${BEMAN_NAMESPACE} - CXX_MODULES_DIRECTORY - cxx-modules - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${name} - COMPONENT "${install_component_name}" - ) - - # ---------------------------------------- - # Config file installation logic - # ---------------------------------------- - string(TOUPPER "${name}" _pkg_upper) - string(REPLACE "." "_" _pkg_prefix "${_pkg_upper}") - - option( - ${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE - "Enable creating and installing a CMake config-file package. Default: ON. Values: { ON, OFF }." - ON - ) - - set(_pkg_var "${_pkg_prefix}_INSTALL_CONFIG_FILE_PACKAGE") - - if(NOT DEFINED ${_pkg_var}) - set(${_pkg_var} - OFF - CACHE BOOL - "Install CMake package config files for ${name}" - ) - endif() - - 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() - - # ---------------------------------------- - # Generate + install config files - # ---------------------------------------- - if(_install_config) - set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${name}") - - configure_package_config_file( - "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${name}-config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" - INSTALL_DESTINATION ${_config_install_dir} - ) - - write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion - ) - - install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/${name}-config-version.cmake" - DESTINATION ${_config_install_dir} - COMPONENT "${install_component_name}" - ) - else() - message( - WARNING - "beman-install-library(${name}): Not installing a config package for '${name}'" - ) - endif() -endfunction() - -set(CPACK_GENERATOR TGZ) -include(CPack) diff --git a/cmake/beman.execution-config.cmake.in b/cmake/beman.execution-config.cmake.in deleted file mode 100644 index 40463a38..00000000 --- a/cmake/beman.execution-config.cmake.in +++ /dev/null @@ -1,7 +0,0 @@ -# cmake/Config.cmake.in -*-makefile-*- -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -@PACKAGE_INIT@ - -include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") -check_required_components("@TARGET_LIBRARY@") diff --git a/cmake/cxx-modules-rules.cmake b/cmake/cxx-modules-rules.cmake index 6b081a5a..23a0ec2e 100644 --- a/cmake/cxx-modules-rules.cmake +++ b/cmake/cxx-modules-rules.cmake @@ -1,3 +1,4 @@ +# 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() diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake index c7b86338..36c4fc68 100644 --- a/cmake/prelude.cmake +++ b/cmake/prelude.cmake @@ -1,3 +1,4 @@ +# 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! # From 0693da81f450154999a9e9e49a27c5c3b10cc71b Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Thu, 5 Feb 2026 14:22:43 +0100 Subject: [PATCH 11/22] Update cmake/README.md --- cmake/README.md | 62 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/cmake/README.md b/cmake/README.md index 7b5a8106..954e3e3d 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -104,15 +104,61 @@ BEMAN_INSTALL_CONFIG_FILE_PACKAGES ## The possible usage in CMakeLists.txt - include(./cmake/prelude.cmake) - project(beman.execution VERSION 0.2.0 LANGUAGES CXX) - include(./cmake/cxx-modules-rules.cmake) - - # NOTE: this must be done before tests! CK - include(beman-install-library) - beman_install_library(${PROJECT_NAME} TARGETS ${PROJECT_NAME} beman.exemplar_headers # - # TODO(add): DEPENDENCIES [===[beman.inplace_vector 1.0.0]===] [===[beman.scope 0.0.1 EXACT]===] fmt +```cmake +cmake_minimum_required(VERSION 3.30...4.2) + +include(./cmake/prelude.cmake) +project(beman.execution VERSION 0.2.0 LANGUAGES CXX) +include(./cmake/cxx-modules-rules.cmake) + +set(TARGET_PREFIX ${PROJECT_NAME}) + +#=============================================================================== +if(BEMAN_USE_MODULES) + set(CMAKE_CXX_VISIBILITY_PRESET hidden) + set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) + + # CMake requires the language standard to be specified as compile feature + # when a target provides C++23 modules and the target will be installed + add_library(${TARGET_PREFIX} STATIC) + add_library(beman::execution ALIAS ${TARGET_PREFIX}) + target_compile_features( + ${TARGET_PREFIX} + PUBLIC cxx_std_${CMAKE_CXX_STANDARD} + ) + + include(GenerateExportHeader) + generate_export_header( + ${TARGET_PREFIX} + BASE_NAME ${TARGET_PREFIX} + EXPORT_FILE_NAME beman/execution/modules_export.hpp + ) + target_sources( + ${TARGET_PREFIX} + PUBLIC + FILE_SET HEADERS + BASE_DIRS include ${CMAKE_CURRENT_BINARY_DIR} + FILES + ${CMAKE_CURRENT_BINARY_DIR}/beman/execution/modules_export.hpp ) + target_compile_definitions(${TARGET_PREFIX} PUBLIC BEMAN_HAS_MODULES) +endif() + +if(BEMAN_USE_MODULES AND CMAKE_CXX_MODULE_STD) + target_compile_definitions(${TARGET_PREFIX} PUBLIC BEMAN_HAS_IMPORT_STD) +else() + message(WARNING "Missing support for CMAKE_CXX_MODULE_STD!") +endif() +#=============================================================================== + +# ... + +# NOTE: this must be done before tests! CK +include(beman-install-library) +beman_install_library(${PROJECT_NAME} TARGETS ${TARGET_PREFIX} beman.exemplar_headers # + # TODO(add): DEPENDENCIES [===[beman.inplace_vector 1.0.0]===] [===[beman.scope 0.0.1 EXACT]===] fmt +) +``` ## Possible cmake config output From 55533be48ad061179690df1b4451e473ecf9af21 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Thu, 5 Feb 2026 18:14:03 +0100 Subject: [PATCH 12/22] Reformat README.md --- cmake/README.md | 151 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 116 insertions(+), 35 deletions(-) diff --git a/cmake/README.md b/cmake/README.md index 954e3e3d..f5a44b64 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -1,22 +1,58 @@ -# Create and install an interface library and the `CXX_MODULE` if possible +# CMake Support for Header-Only Libraries and C++ Modules -To be able to compile a project with and without MODULES, the project needs at least 2 targets: +This directory provides a small set of CMake helper modules that make it easier +to **build and install a library that works both with and without C++20 +modules**. -- an interface library (header only) with one `PUBLIC FILE_SET HEADERS` -- a library (static and/or dynamic) with one `PUBLIC FILE_SET CXX_MODULE` +The helpers wrap CMake’s evolving support for `FILE_SET CXX_MODULE` and package +installation so that: +- consumers can use the library in **classic header-only mode**, or -## NEW CMAKE modules intended to be in infra/cmake: +- consumers with a compatible toolchain can use **C++ modules**, including + optional `import std;` support. -- prelude.cmake -- cxx-modules-rules.cmake -- beman-install-library.cmake -- Config.cmake.in +The goal is to keep project `CMakeLists.txt` files readable while hiding most of +the platform- and compiler-specific complexity. +--- -## NEW added related CMake options: +## Motivation + +Today, supporting C++ modules often requires duplicating targets and custom +install logic: + +- one target for headers only, +- another target that owns module interface units, +- conditional logic depending on compiler and CMake version, +- non-trivial install/export rules. + +The helpers in this directory centralize that logic and provide a single, +consistent API for projects that want to offer both usage models. + +--- + +## Provided CMake Modules + +The following modules are expected to live in `infra/cmake`: + +- `prelude.cmake` + Common project setup and option handling. + +- `cxx-modules-rules.cmake` + Compiler and CMake feature checks related to C++ modules. + +- `beman-install-library.cmake` + High-level helper to install libraries, headers, module interface units, and CMake package files. + +- `Config.cmake.in` + Template used to generate the `Config.cmake` file for consumers. + +--- + +## New Configuration Options * BEMAN_USE_MODULES:BOOL=ON * BEMAN_USE_STD_MODULE:BOOL=OFF @@ -40,50 +76,58 @@ if(BEMAN_USE_MODULES AND CMAKE_CXX_MODULE_STD) endif() ``` +Typical projects will only toggle `BEMAN_USE_MODULES`; the remaining options are +detected automatically. -### beman_install_library +--- -Installs a library (or set of targets) along with headers, C++ modules, -and optional CMake package configuration files. +## Installing a Library -#### Usage: +Installation is handled by the `beman_install_library()` helper. - beman_install_library( +### Function Signature + +```cmake +beman_install_library( + name TARGETS target1 [target2 ...] - DEPENDENCIES dependency1 [dependency2 ...] + [DEPENDENCIES dep1 [dep2 ...]] [NAMESPACE ] [EXPORT_NAME ] - [DESTINATION ] - ) + [DESTINATION ] +) +``` -#### Arguments: +### Arguments -name +- **name** Logical package name (e.g. "beman.utility"). Used to derive config file names and cache variable prefixes. -TARGETS (required) - List of CMake targets to install. +- **TARGETS** + Targets to install and export. -DEPENDENCIES (optional) +- **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" + 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! -NAMESPACE (optional) - Namespace for exported targets. + `"[===[beman.inplace_vector 1.0.0]===] [===[beman.scope 0.0.1 EXACT]===] fmt"` + +- **NAMESPACE (optional)** + Namespace for imported targets. Defaults to "beman::". -EXPORT_NAME (optional) - Name of the CMake export set. +- **EXPORT_NAME (optional)** + Name of the generated CMake export set. Defaults to "-targets". -DESTINATION (optional) - The install destination for CXX_MODULES. - Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. +- **DESTINATION (optional)** + Installation directory for C++ module interface units. + Defaults to `${CMAKE_INSTALL_INCLUDEDIR}/beman/modules`. -#### Brief +The helper installs: This function installs the specified project TARGETS and its FILE_SET HEADERS to the default CMAKE install Destination. @@ -92,7 +136,7 @@ It also handles the installation of the CMake config package files if needed. If the given targets has FILE_SET CXX_MODULE, it will also installed to the given DESTINATION -#### Cache variables: +- ***Used Cache variables** BEMAN_INSTALL_CONFIG_FILE_PACKAGES List of package names for which config files should be installed. @@ -101,6 +145,7 @@ BEMAN_INSTALL_CONFIG_FILE_PACKAGES Per-package override to enable/disable config file installation. is the uppercased package name with dots replaced by underscores. +--- ## The possible usage in CMakeLists.txt @@ -160,9 +205,13 @@ beman_install_library(${PROJECT_NAME} TARGETS ${TARGET_PREFIX} beman.exemplar_he ) ``` +--- ## Possible cmake config output +**NOTE:** Exact output depend on the build host, used toolchain, and +whether module support is enabled and supported. + ```bash bash-5.3$ make test-module cmake -G Ninja -S /Users/clausklein/Workspace/cpp/beman-project/execution26 -B build/Darwin/default \ @@ -212,9 +261,13 @@ This warning is for project developers. Use -Wno-dev to suppress it. bash-5.3$ ``` +--- ## Possible cmake export config package +**NOTE:** Exact contents depend on the build host, used toolchain, and +whether module support is enabled. + ```bash cmake --install build/Darwin/default --prefix $PWD/stagedir @@ -247,6 +300,7 @@ lib/ bash-5.3$ ``` +--- ## The recommended usage in implementation @@ -276,6 +330,7 @@ struct identity { } // namespace beman::exemplar ``` +--- ## The possible usage in user code @@ -304,3 +359,29 @@ int main() { return 0; } ``` + +--- + +## Notes on CMake and Modules + +- `FILE_SET CXX_MODULE` support is still evolving and depends on the compiler + and CMake version. + +- Not all toolchains support installing or consuming prebuilt module interface + units yet. + +- These helpers aim to provide a pragmatic, forward-compatible structure rather + than a final standard solution. + +--- + +## Summary + +The helpers in this directory provide a structured way to: + +- build header-only and module-based libraries side by side, +- hide compiler- and platform-specific complexity, +- install and export targets in a consistent, consumer-friendly way. + +They are intended for projects that want to experiment with C++ modules today +while remaining usable on traditional toolchains. From 58340c950bf8cf9bb403358b45e736fcd768c15e Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Thu, 5 Feb 2026 21:50:43 +0100 Subject: [PATCH 13/22] Fix types after review --- cmake/README.md | 13 ++++++------- cmake/beman-install-library.cmake | 12 +++++------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/cmake/README.md b/cmake/README.md index f5a44b64..130e8ac9 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -88,8 +88,7 @@ Installation is handled by the `beman_install_library()` helper. ### Function Signature ```cmake -beman_install_library( - name +beman_install_library(name TARGETS target1 [target2 ...] [DEPENDENCIES dep1 [dep2 ...]] [NAMESPACE ] @@ -129,19 +128,19 @@ beman_install_library( The helper installs: -This function installs the specified project TARGETS and its FILE_SET -HEADERS to the default CMAKE install Destination. +This function installs the specified project TARGETS and its `FILE_SET +HEADERS` to the default CMAKE install destination. It also handles the installation of the CMake config package files if -needed. If the given targets has FILE_SET CXX_MODULE, it will also +needed. If the given targets has `FILE_SET CXX_MODULE`, it will also installed to the given DESTINATION - ***Used Cache variables** -BEMAN_INSTALL_CONFIG_FILE_PACKAGES +`BEMAN_INSTALL_CONFIG_FILE_PACKAGES` List of package names for which config files should be installed. -_INSTALL_CONFIG_FILE_PACKAGE +`_INSTALL_CONFIG_FILE_PACKAGE` Per-package override to enable/disable config file installation. is the uppercased package name with dots replaced by underscores. diff --git a/cmake/beman-install-library.cmake b/cmake/beman-install-library.cmake index a73f4fc7..4b8290f9 100644 --- a/cmake/beman-install-library.cmake +++ b/cmake/beman-install-library.cmake @@ -16,8 +16,8 @@ include(GNUInstallDirs) # Usage: # ------ # beman_install_library( -# TARGETS target1 [target2 ...] -# DEPENDENCIES dependency1 [dependency2 ...] +# TARGETS [ ...] +# [DEPENDENCIES [ ...]] # [NAMESPACE ] # [EXPORT_NAME ] # [DESTINATION ] @@ -48,13 +48,13 @@ include(GNUInstallDirs) # # DESTINATION (optional) # The install destination for CXX_MODULES. -# Defaults to CMAKE_INSTALL_INCLUDEDIR/beman/modules. +# Defaults to ${CMAKE_INSTALL_LIBDIR}/cmake/${name}/modules. # # Brief # ----- # # This function installs the specified project TARGETS and its FILE_SET -# HEADERS to the default CMAKE install Destination. +# HEADERS to the default CMAKE install destination. # # It also handles the installation of the CMake config package files if # needed. If the given targets has FILE_SET CXX_MODULE, it will also @@ -114,7 +114,6 @@ function(beman_install_library name) endif() if(NOT BEMAN_DESTINATION) - # XXX set(BEMAN_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/beman/modules") set(BEMAN_DESTINATION "${_config_install_dir}/modules") endif() @@ -159,7 +158,6 @@ function(beman_install_library name) VERBOSE "beman-install-library(${name}): '${_tgt}' has INTERFACE_HEADER_SETS=${_header_sets}" ) - # XXX set(__INSTALL_HEADER_SETS FILE_SET ${_header_sets}) else() set(_header_sets HEADERS) # Note: empty FILE_SET in this case! CK endif() @@ -180,7 +178,7 @@ function(beman_install_library name) RUNTIME # DESTINATION ${CMAKE_INSTALL_BINDIR} FILE_SET ${_header_sets} # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILE_SET CXX_MODULES DESTINATION "${BEMAN_DESTINATION}" + FILE_SET ${_module_sets} DESTINATION "${BEMAN_DESTINATION}" # NOTE: There's currently no convention for this location! CK CXX_MODULES_BMI # TODO(CK): DESTINATION ${_config_install_dir}/bmi-${CMAKE_CXX_COMPILER_ID}_$ From 0b0543ef2ddd63adb12dc05822ba985d5d2db078 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Thu, 5 Feb 2026 22:16:07 +0100 Subject: [PATCH 14/22] More review items --- cmake/README.md | 2 +- cmake/prelude.cmake | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/cmake/README.md b/cmake/README.md index 130e8ac9..3ddfb5ac 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -48,7 +48,7 @@ The following modules are expected to live in `infra/cmake`: High-level helper to install libraries, headers, module interface units, and CMake package files. - `Config.cmake.in` - Template used to generate the `Config.cmake` file for consumers. + Template used to generate the `-config.cmake` file for consumers. --- diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake index 36c4fc68..465d6027 100644 --- a/cmake/prelude.cmake +++ b/cmake/prelude.cmake @@ -22,19 +22,9 @@ if(PROJECT_NAME) ) endif() -# gersemi: off -# --------------------------------------------------------------------------- -# use ccache if found -# --------------------------------------------------------------------------- -find_program(CCACHE_EXECUTABLE "ccache" HINTS /usr/local/bin /opt/local/bin) -if(CCACHE_EXECUTABLE) - message(STATUS "use ccache") - set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache") - set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache") -endif() - list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) +# gersemi: off # --------------------------------------------------------------------------- # check if import std; is supported by CMAKE_CXX_COMPILER # --------------------------------------------------------------------------- @@ -43,6 +33,10 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.2) endif() # gersemi: on +if(NOT APPLE) + return() +endif() + # FIXME: on APPLE with clang++ still needs to export CXX=clang++ if("$ENV{CXX}" STREQUAL "" AND CMAKE_CXX_COMPILER) message(WARNING "\$CXX is not set") From 82a366014f010dbbfd00bcde96828529bf2ce51b Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Feb 2026 09:26:36 +0100 Subject: [PATCH 15/22] The final cleanup --- cmake/README.md | 14 ++++++++------ cmake/prelude.cmake | 14 +++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/cmake/README.md b/cmake/README.md index 3ddfb5ac..6c7e2723 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -89,8 +89,8 @@ Installation is handled by the `beman_install_library()` helper. ```cmake beman_install_library(name - TARGETS target1 [target2 ...] - [DEPENDENCIES dep1 [dep2 ...]] + TARGETS [ ...] + [DEPENDENCIES [ ...]] [NAMESPACE ] [EXPORT_NAME ] [DESTINATION ] @@ -126,13 +126,11 @@ beman_install_library(name Installation directory for C++ module interface units. Defaults to `${CMAKE_INSTALL_INCLUDEDIR}/beman/modules`. -The helper installs: - This function installs the specified project TARGETS and its `FILE_SET -HEADERS` to the default CMAKE install destination. +TYPE HEADERS` to the default CMAKE install destination. It also handles the installation of the CMake config package files if -needed. If the given targets has `FILE_SET CXX_MODULE`, it will also +needed. If the given targets has `FILE_SET TYPE CXX_MODULE`, it will also installed to the given DESTINATION - ***Used Cache variables** @@ -144,6 +142,10 @@ installed to the given DESTINATION Per-package override to enable/disable config file installation. is the uppercased package name with dots replaced by underscores. +### Caveats + +**Only one `FILE_SET of each TYPE` is supported to install with this function yet!** + --- ## The possible usage in CMakeLists.txt diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake index 465d6027..53c1e402 100644 --- a/cmake/prelude.cmake +++ b/cmake/prelude.cmake @@ -17,7 +17,7 @@ endif() if(PROJECT_NAME) message( - FATAL_ERROR + WARNING "This CMake file has to be included before first project() command call!" ) endif() @@ -38,10 +38,10 @@ if(NOT APPLE) endif() # FIXME: on APPLE with clang++ 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() +# 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 @@ -52,8 +52,8 @@ if( ) # 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++") + # FIXME: set(ENV{CXXFLAGS} -stdlib=libc++) + # message(STATUS "CXXFLAGS=-stdlib=libc++") if(APPLE) execute_process( From 65ceb34a05f1bbc2a0e934f72eeb6092799c9fdc Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Feb 2026 12:18:19 +0100 Subject: [PATCH 16/22] Revert: CXX and CXXFLAGS are still needed for llvm on UNIX --- cmake/prelude.cmake | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake index 53c1e402..b121b261 100644 --- a/cmake/prelude.cmake +++ b/cmake/prelude.cmake @@ -33,15 +33,16 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.2) endif() # gersemi: on -if(NOT APPLE) - return() -endif() +# TODO(CK): not yet! +## if(NOT APPLE) +## return() +## endif() -# FIXME: on APPLE with clang++ 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() +# 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 @@ -52,8 +53,8 @@ if( ) # NOTE: Always use libc++ # see https://releases.llvm.org/19.1.0/projects/libcxx/docs/index.html - # FIXME: set(ENV{CXXFLAGS} -stdlib=libc++) - # message(STATUS "CXXFLAGS=-stdlib=libc++") + set(ENV{CXXFLAGS} -stdlib=libc++) + message(STATUS "CXXFLAGS=-stdlib=libc++") if(APPLE) execute_process( @@ -102,7 +103,7 @@ if( # gersemi: on else() message( - WARNING + FATAL_ERROR "File does NOT EXISTS! ${CMAKE_CXX_STDLIB_MODULES_JSON}" ) endif() From 16d72c726df58b8269f985393777163f1f4cdddd Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Feb 2026 12:51:59 +0100 Subject: [PATCH 17/22] Revert to BEMAN_USE_STD_MODULE=OFF --- cmake/cxx-modules-rules.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/cxx-modules-rules.cmake b/cmake/cxx-modules-rules.cmake index 23a0ec2e..43e11507 100644 --- a/cmake/cxx-modules-rules.cmake +++ b/cmake/cxx-modules-rules.cmake @@ -93,7 +93,7 @@ endif() option( BEMAN_USE_STD_MODULE "Check if 'import std;' is possible with the toolchain?" - ON + OFF ) message(STATUS "BEMAN_USE_STD_MODULE=${BEMAN_USE_STD_MODULE}") From 39cc17063a7f0059730ea7c39845432078571cb2 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Feb 2026 15:48:47 +0100 Subject: [PATCH 18/22] Fix how to control if module code is used Only BEMAN_USE_MODULES AND BEMAN_USE_STD_MODULE should control it, even if the toolchain supports it! --- CMakeLists.txt | 9 ++++++--- CMakePresets.json | 6 +++--- Makefile | 14 +++++++++----- cmake/cxx-modules-rules.cmake | 12 ++++++------ cmake/presets/CMakeGenericPresets.json | 2 +- tests/beman/execution/CMakeLists.txt | 2 +- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5907ee0a..d64c5800 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,8 +21,9 @@ set(TARGETS_EXPORT_NAME ${PROJECT_NAME}-targets) # NOTE: must be set, is importa #=============================================================================== if(BEMAN_USE_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) set(CMAKE_CXX_VISIBILITY_PRESET hidden) - set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) + set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # CMake requires the language standard to be specified as compile feature # when a target provides C++23 modules and the target will be installed @@ -48,12 +49,14 @@ if(BEMAN_USE_MODULES) ${CMAKE_CURRENT_BINARY_DIR}/beman/execution/modules_export.hpp ) target_compile_definitions(${TARGET_PREFIX} PUBLIC BEMAN_HAS_MODULES) +else() + set(CMAKE_CXX_SCAN_FOR_MODULES OFF) endif() if(BEMAN_USE_MODULES AND CMAKE_CXX_MODULE_STD) target_compile_definitions(${TARGET_PREFIX} PUBLIC BEMAN_HAS_IMPORT_STD) -else() - message(WARNING "Missing support for CMAKE_CXX_MODULE_STD!") +elseif(BEMAN_USE_MODULES) + message(WARNING "Missing or disabled support for CMAKE_CXX_MODULE_STD!") endif() #=============================================================================== diff --git a/CMakePresets.json b/CMakePresets.json index 5bc75f84..4c05a34d 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -7,9 +7,9 @@ "generator": "Ninja", "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { + "BEMAN_USE_MODULES": true, "CMAKE_CXX_STANDARD": "23", "CMAKE_CXX_EXTENSIONS": true, - "CMAKE_CXX_SCAN_FOR_MODULES": true, "CMAKE_CXX_STANDARD_REQUIRED": true, "CMAKE_EXPORT_COMPILE_COMMANDS": true, "CMAKE_SKIP_TEST_ALL_DEPENDENCY": false, @@ -83,7 +83,7 @@ "_debug-base" ], "cacheVariables": { - "CMAKE_CXX_SCAN_FOR_MODULES": false, + "BEMAN_USE_MODULES": false, "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" } }, @@ -95,7 +95,7 @@ "_release-base" ], "cacheVariables": { - "CMAKE_CXX_SCAN_FOR_MODULES": false, + "BEMAN_USE_MODULES": false, "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" } }, diff --git a/Makefile b/Makefile index 23dddc01..a2dd4e7e 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,9 @@ ifeq ($(CXX_BASE),clang++) COMPILER=clang++ endif +# NOTE default gmake use this flags! +# COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +# LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) LDFLAGS ?= SAN_FLAGS ?= CXX_FLAGS ?= -g @@ -56,7 +59,8 @@ ifeq (${hostSystemName},Darwin) # export GCC_DIR:=$(shell realpath ${GCC_PREFIX}) # XXX export CMAKE_CXX_STDLIB_MODULES_JSON=${GCC_DIR}/lib/gcc/current/libstdc++.modules.json - ifeq ($(CXX),) + ifeq ($(origin CXX),default) + $(info CXX is using the built-in default: $(CXX)) export CXX=g++-15 export CXXFLAGS=-stdlib=libstdc++ endif @@ -123,12 +127,12 @@ build build-interface: -D CMAKE_CXX_STANDARD=23 \ -D CMAKE_CXX_EXTENSIONS=ON \ -D CMAKE_CXX_STANDARD_REQUIRED=ON \ - -D CMAKE_CXX_SCAN_FOR_MODULES=OFF \ -D BEMAN_USE_MODULES=OFF \ + -D BEMAN_USE_STD_MODULE=OFF \ -D CMAKE_BUILD_TYPE=Release \ -D CMAKE_SKIP_TEST_ALL_DEPENDENCY=OFF \ - -D CMAKE_CXX_COMPILER=$(CXX) --log-level=VERBOSE - # XXX --fresh -D CMAKE_CXX_FLAGS="$(CXX_FLAGS) $(SAN_FLAGS)" + -D CMAKE_CXX_COMPILER=$(CXX) --log-level=VERBOSE --fresh + # XXX -D CMAKE_CXX_FLAGS="$(CXX_FLAGS) $(SAN_FLAGS)" cmake --build $(BUILD) --target all_verify_interface_header_sets cmake --build $(BUILD) --target all @@ -143,8 +147,8 @@ module build-module: -D CMAKE_CXX_STANDARD=23 \ -D CMAKE_CXX_EXTENSIONS=ON \ -D CMAKE_CXX_STANDARD_REQUIRED=ON \ - -D CMAKE_CXX_SCAN_FOR_MODULES=ON \ -D BEMAN_USE_MODULES=ON \ + -D BEMAN_USE_STD_MODULE=ON \ -D CMAKE_BUILD_TYPE=Release \ -D CMAKE_INSTALL_MESSAGE=LAZY \ -D CMAKE_BUILD_TYPE=Release \ diff --git a/cmake/cxx-modules-rules.cmake b/cmake/cxx-modules-rules.cmake index 43e11507..91939b36 100644 --- a/cmake/cxx-modules-rules.cmake +++ b/cmake/cxx-modules-rules.cmake @@ -90,6 +90,11 @@ 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?" @@ -97,7 +102,7 @@ option( ) message(STATUS "BEMAN_USE_STD_MODULE=${BEMAN_USE_STD_MODULE}") -if(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 @@ -122,11 +127,6 @@ if(BEMAN_USE_STD_MODULE) message(STATUS "BEMAN_HAS_IMPORT_STD=${BEMAN_HAS_IMPORT_STD}") 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}") - if(NOT BEMAN_USE_MODULES) set(CMAKE_CXX_SCAN_FOR_MODULES OFF) endif() diff --git a/cmake/presets/CMakeGenericPresets.json b/cmake/presets/CMakeGenericPresets.json index df2d2045..e86aea1e 100644 --- a/cmake/presets/CMakeGenericPresets.json +++ b/cmake/presets/CMakeGenericPresets.json @@ -12,9 +12,9 @@ "type": "path", "value": "${sourceDir}/stagedir" }, + "BEMAN_USE_MODULES": true, "CMAKE_CXX_STANDARD": "23", "CMAKE_CXX_EXTENSIONS": true, - "CMAKE_CXX_SCAN_FOR_MODULES": true, "CMAKE_CXX_STANDARD_REQUIRED": true, "CMAKE_EXPORT_COMPILE_COMMANDS": true, "CMAKE_INSTALL_MESSAGE": "LAZY", diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index 35b07dea..0bbfea16 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -148,11 +148,11 @@ if(BEMAN_EXECUTION_INSTALL_CONFIG_FILE_PACKAGE AND NOT CMAKE_SKIP_INSTALL_RULES) --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_SCAN_FOR_MODULES=${CMAKE_CXX_SCAN_FOR_MODULES}" "-D CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" "-D CMAKE_CXX_STANDARD_REQUIRED=${CMAKE_CXX_STANDARD_REQUIRED}" "-D CMAKE_PREFIX_PATH=${CMAKE_BINARY_DIR}/stagedir" From 287743850b46c4d4d47090bcf9113d7eba71e78c Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Feb 2026 16:04:27 +0100 Subject: [PATCH 19/22] Use clang++ -print-file-name=c++/libc++.modules.json only on OSX --- cmake/prelude.cmake | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake index b121b261..2f4b7970 100644 --- a/cmake/prelude.cmake +++ b/cmake/prelude.cmake @@ -33,10 +33,9 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.2) endif() # gersemi: on -# TODO(CK): not yet! -## if(NOT APPLE) -## return() -## endif() +if(NOT APPLE) + return() +endif() # FIXME: clang++ we still needs to export CXX=clang++ if("$ENV{CXX}" STREQUAL "" AND CMAKE_CXX_COMPILER) From 1185c48d2883083eb658159f9581e9ab11537e56 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Feb 2026 17:13:07 +0100 Subject: [PATCH 20/22] Quickfix: module links to Threads --- CMakeLists.txt | 4 ++++ cmake/Config.cmake.in | 2 ++ cmake/beman-install-library.cmake | 5 ++++- cmake/prelude.cmake | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d64c5800..99c13228 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,8 @@ if(BEMAN_USE_MODULES) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) + find_package(Threads REQUIRED) + # CMake requires the language standard to be specified as compile feature # when a target provides C++23 modules and the target will be installed add_library(${TARGET_PREFIX} STATIC) @@ -49,6 +51,7 @@ if(BEMAN_USE_MODULES) ${CMAKE_CURRENT_BINARY_DIR}/beman/execution/modules_export.hpp ) target_compile_definitions(${TARGET_PREFIX} PUBLIC BEMAN_HAS_MODULES) + target_link_libraries(${TARGET_PREFIX} PUBLIC Threads::Threads) else() set(CMAKE_CXX_SCAN_FOR_MODULES OFF) endif() @@ -80,6 +83,7 @@ include(./cmake/beman-install-library.cmake) beman_install_library(${TARGET_PREFIX} TARGETS ${TARGET_NAME} ${TARGET_PREFIX} # FIXME: DEPENDENCIES [===[beman.inplace_vector 1.0.0]===] [===[beman.scope 0.0.1 EXACT]===] fmt # TODO(CK): XXX OR XXX DEPENDENCIES "beman.inplace_vector 1.0.0;beman.scope 0.0.1 EXACT" + DEPENDENCIES Threads ) #=============================================================================== diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in index 6a965772..81adf800 100644 --- a/cmake/Config.cmake.in +++ b/cmake/Config.cmake.in @@ -3,6 +3,8 @@ include(CMakeFindDependencyMacro) +@BEMAN_FIND_DEPENDENCIES@ + @PACKAGE_INIT@ include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake) diff --git a/cmake/beman-install-library.cmake b/cmake/beman-install-library.cmake index 4b8290f9..5b90d9d3 100644 --- a/cmake/beman-install-library.cmake +++ b/cmake/beman-install-library.cmake @@ -247,7 +247,10 @@ function(beman_install_library name) # ---------------------------------------- set(_beman_find_deps "") foreach(dep IN ITEMS ${BEMAN_DEPENDENCIES}) - message(VERBOSE "Add find_dependency(${dep})") + message( + VERBOSE + "beman-install-library(${name}): Add find_dependency(${dep})" + ) string(APPEND _beman_find_deps "find_dependency(${dep})\n") endforeach() set(BEMAN_FIND_DEPENDENCIES "${_beman_find_deps}") diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake index 2f4b7970..e52bf2e9 100644 --- a/cmake/prelude.cmake +++ b/cmake/prelude.cmake @@ -75,7 +75,7 @@ if( elseif(LINUX) execute_process( OUTPUT_VARIABLE LLVM_MODULES - COMMAND clang++ -print-file-name=c++/libc++.modules.json + COMMAND clang++ -print-file-name=libc++.modules.json COMMAND_ECHO STDOUT OUTPUT_STRIP_TRAILING_WHITESPACE ) From 3985d0df5fa64070da67fe6245342091f32d5b13 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Feb 2026 17:28:13 +0100 Subject: [PATCH 21/22] Last try for tody --- cmake/prelude.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake index e52bf2e9..84ab7094 100644 --- a/cmake/prelude.cmake +++ b/cmake/prelude.cmake @@ -33,9 +33,10 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.2) endif() # gersemi: on -if(NOT APPLE) - return() -endif() +# FIXME: we need this for linux too! CK +# if(NOT APPLE) +# return() +# endif() # FIXME: clang++ we still needs to export CXX=clang++ if("$ENV{CXX}" STREQUAL "" AND CMAKE_CXX_COMPILER) From acf2cd3f46efedf76082cae56bfbe0dcb29f5970 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 6 Feb 2026 20:37:40 +0100 Subject: [PATCH 22/22] Reduce usage of CMAKE_EXPERIMENTAL_CXX_IMPORT_STD --- CMakePresets.json | 19 +++++++++++++++++++ cmake/prelude.cmake | 22 ++++++++++++++-------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index 4c05a34d..eccfd3f6 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -19,6 +19,17 @@ { "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" @@ -62,6 +73,10 @@ ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-libc++-toolchain.cmake" + }, + "environment": { + "CXX": "clang++", + "CMAKE_CXX_FLAGS": "-stdlib=libc++" } }, { @@ -73,6 +88,10 @@ ], "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": "infra/cmake/llvm-libc++-toolchain.cmake" + }, + "environment": { + "CXX": "clang++", + "CMAKE_CXX_FLAGS": "-stdlib=libc++" } }, { diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake index 84ab7094..588e608c 100644 --- a/cmake/prelude.cmake +++ b/cmake/prelude.cmake @@ -15,25 +15,31 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) ) endif() -if(PROJECT_NAME) - message( - WARNING - "This CMake file has to be included before first project() command call!" - ) -endif() - list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) +# --------------------------------------------------------------------------- +if(NOT BEMAN_USE_STD_MODULE OR CMAKE_VERSION VERSION_GREATER_EQUAL 4.3) + return() +endif() +# --------------------------------------------------------------------------- + # gersemi: off # --------------------------------------------------------------------------- # check if import std; is supported by CMAKE_CXX_COMPILER # --------------------------------------------------------------------------- if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.2) + if(PROJECT_NAME) + message( + WARNING + "This CMake file has to be included before first project() command call!" + ) + endif() + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") endif() # gersemi: on -# FIXME: we need this for linux too! CK +# TODO(CK): Do we need this HACK for linux too? # if(NOT APPLE) # return() # endif()