diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 409f66ee..88eead7e 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -13,10 +13,10 @@ on: jobs: beman-submodule-check: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-submodule-check.yml@1.1.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-submodule-check.yml@1.2.1 preset-test: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-preset-test.yml@1.1.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-preset-test.yml@1.2.1 with: matrix_config: > [ @@ -29,7 +29,7 @@ jobs: ] build-and-test: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-build-and-test.yml@1.1.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-build-and-test.yml@1.2.1 with: matrix_config: > { @@ -40,7 +40,8 @@ jobs: "tests": [ { "stdlibs": ["libstdc++"], "tests": [ - "Debug.Default", "Release.Default", "Release.MaxSan", + "Debug.Default", "Release.Default", "Release.TSan", + "Release.MaxSan", "Debug.Werror", "Debug.Dynamic", "Debug.Coverage" ] } @@ -51,7 +52,7 @@ jobs: } ] }, - { "versions": ["14", "13"], + { "versions": ["14"], "tests": [ { "cxxversions": ["c++26", "c++23"], "tests": [{ "stdlibs": ["libstdc++"], "tests": ["Release.Default"]}] @@ -60,7 +61,7 @@ jobs: } ], "clang": [ - { "versions": ["20"], + { "versions": ["21"], "tests": [ {"cxxversions": ["c++26"], "tests": [ @@ -79,7 +80,7 @@ jobs: } ] }, - { "versions": ["19"], + { "versions": ["20", "19"], "tests": [ { "cxxversions": ["c++26", "c++23"], "tests": [ @@ -95,7 +96,7 @@ jobs: { "cxxversions": ["c++23"], "tests": [ { "stdlibs": ["stl"], - "tests": ["Debug.Default", "Release.Default"] + "tests": ["Debug.Default", "Release.Default", "Release.MaxSan"] } ] } @@ -107,4 +108,4 @@ jobs: create-issue-when-fault: needs: [preset-test, build-and-test] if: failure() && github.event_name == 'schedule' - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-create-issue-when-fault.yml@1.1.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-create-issue-when-fault.yml@1.2.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9636e830..e67742c9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: # CMake linting and formatting - repo: https://github.com/BlankSpruce/gersemi - rev: 0.25.3 + rev: 0.25.4 hooks: - id: gersemi name: CMake linting diff --git a/CMakeLists.txt b/CMakeLists.txt index 87029607..e0bc6a7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,93 +3,57 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # gersemi: on -cmake_minimum_required(VERSION 3.25...4.2) +cmake_minimum_required(VERSION 3.30...4.2) -#========================== pre project settings =============================== -# gersemi: off -if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.2) - set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") - - if(CMAKE_CXX_STDLIB_MODULES_JSON) - message( - STATUS - "CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON}" - ) - endif() -endif() -# gersemi: on -#=============================================================================== +include(cmake/prelude.cmake) #=================================================== -project(beman_execution VERSION 0.0.1 LANGUAGES CXX) +project(beman_execution VERSION 0.1.0 LANGUAGES CXX) #=================================================== -if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) - message(FATAL_ERROR "In-source builds are not allowed!") -endif() +# Modules opt in only on compilers that support it: msvc, g++-15 and clang-20+ +include(cxx-modules-rules) -set(TARGET_NAME execution) -set(TARGET_NAMESPACE beman) -set(TARGET_PREFIX ${TARGET_NAMESPACE}.${TARGET_NAME}) -set(TARGET_LIBRARY ${PROJECT_NAME}) -set(TARGET_ALIAS ${TARGET_NAMESPACE}::${TARGET_NAME}) +set(TARGET_NAME beman_execution_headers) # used in src, and docs +set(TARGET_NAMESPACE beman) # NOTE: only still used in docs? +set(TARGET_PREFIX ${PROJECT_NAME}) # NOTE: only still used in docs? set(TARGET_PACKAGE_NAME ${PROJECT_NAME}-config) set(TARGETS_EXPORT_NAME ${PROJECT_NAME}-config-targets) -#========================== post project settings ============================== -# Tell CMake that we explicitly want `import std`. -# This will initialize the property on all targets declared after this to 1 -message(STATUS "CMAKE_CXX_COMPILER_IMPORT_STD=${CMAKE_CXX_COMPILER_IMPORT_STD}") -if(${CMAKE_CXX_STANDARD} IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD) - set(CMAKE_CXX_MODULE_STD ON) - message(STATUS "CMAKE_CXX_MODULE_STD=${CMAKE_CXX_MODULE_STD}") -endif() - -# gersemi: off -if(CMAKE_CXX_SCAN_FOR_MODULES AND ${CMAKE_GENERATOR} STREQUAL Ninja) - set(BEMAN_USE_MODULES ON) - message(STATUS "BEMAN_USE_MODULES=${BEMAN_USE_MODULES}") -else() - message(WARNING "Missing support for CMAKE_CXX_SCAN_FOR_MODULES!") -endif() - -if(CMAKE_EXPORT_COMPILE_COMMANDS) - set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) - message( - STATUS - "CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}" - ) -endif() -# gersemi: on - +#=============================================================================== 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_NAME} STATIC) - target_compile_features(${TARGET_NAME} PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) + add_library(beman_execution STATIC) + add_library(beman::beman_execution ALIAS beman_execution) + target_compile_features( + beman_execution + PUBLIC cxx_std_${CMAKE_CXX_STANDARD} + ) include(GenerateExportHeader) generate_export_header( - ${TARGET_NAME} - BASE_NAME beman.execution + beman_execution + BASE_NAME beman_execution EXPORT_FILE_NAME beman/execution/modules_export.hpp ) target_sources( - ${TARGET_NAME} + beman_execution PUBLIC FILE_SET HEADERS BASE_DIRS include ${CMAKE_CURRENT_BINARY_DIR} FILES ${CMAKE_CURRENT_BINARY_DIR}/beman/execution/modules_export.hpp ) + target_compile_definitions(beman_execution PUBLIC BEMAN_USE_MODULES) endif() if(BEMAN_USE_MODULES AND CMAKE_CXX_MODULE_STD) - target_compile_definitions(${TARGET_NAME} PUBLIC BEMAN_HAS_IMPORT_STD) + target_compile_definitions(beman_execution PUBLIC BEMAN_HAS_IMPORT_STD) else() message(WARNING "Missing support for CMAKE_CXX_MODULE_STD!") endif() @@ -133,6 +97,10 @@ if(NOT BEMAN_EXECUTION_ENABLE_INSTALL OR CMAKE_SKIP_INSTALL_RULES) return() endif() +include(infra/cmake/beman-install-library-config.cmake) +# FIXME: install TARGETS target beman.execution is exported but not all of its interface file sets are installed +# TODO: beman_install_library(beman_execution beman_execution_headers) + include(CMakePackageConfigHelpers) write_basic_package_version_file( diff --git a/CMakePresets.json b/CMakePresets.json index bea60b3d..5bc75f84 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -9,7 +9,7 @@ "cacheVariables": { "CMAKE_CXX_STANDARD": "23", "CMAKE_CXX_EXTENSIONS": true, - "CMAKE_CXX_SCAN_FOR_MODULES": false, + "CMAKE_CXX_SCAN_FOR_MODULES": true, "CMAKE_CXX_STANDARD_REQUIRED": true, "CMAKE_EXPORT_COMPILE_COMMANDS": true, "CMAKE_SKIP_TEST_ALL_DEPENDENCY": false, @@ -83,6 +83,7 @@ "_debug-base" ], "cacheVariables": { + "CMAKE_CXX_SCAN_FOR_MODULES": false, "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" } }, @@ -94,6 +95,7 @@ "_release-base" ], "cacheVariables": { + "CMAKE_CXX_SCAN_FOR_MODULES": false, "CMAKE_TOOLCHAIN_FILE": "infra/cmake/appleclang-toolchain.cmake" } }, diff --git a/README.md b/README.md index 5f22e037..7b13e7e7 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ contains some links for general information about the sender/receivers and `std: ## Preconditions - cmake v3.30 or newer -- ninja v1.11.1 or newer +- ninja v1.13.0 or newer - A compiler that supports at least C++23 diff --git a/cmake/cxx-modules-rules.cmake b/cmake/cxx-modules-rules.cmake new file mode 100644 index 00000000..b756b89f --- /dev/null +++ b/cmake/cxx-modules-rules.cmake @@ -0,0 +1,150 @@ +# +# A CMake language file to be included as the last step of all project() command calls. +# This file must be included/used as CMAKE_PROJECT_INCLUDE -> after project() +# + +# ---- The include guard applies within the current directory and below ---- +include_guard(DIRECTORY) + +if(NOT PROJECT_NAME) + message( + FATAL_ERROR + "This CMake file has to be included as the last step of all project() command calls!" + ) +endif() + +# Use modules? default NO! +if(NOT DEFINED CMAKE_CXX_SCAN_FOR_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES OFF) +endif() + +# Control whether the test target depends on the all target. +set(CMAKE_SKIP_TEST_ALL_DEPENDENCY OFF) + +# gersemi: off +option(CMAKE_EXPORT_COMPILE_COMMANDS "Prepare run-clang-tidy" ${PROJECT_IS_TOP_LEVEL}) +if(CMAKE_EXPORT_COMPILE_COMMANDS) + message( + STATUS + "CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}" + ) + set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) +endif() +# gersemi: on + +# Ensure non-empty default build type for single-config +get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(NOT isMultiConfig) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type") +endif() +set(CMAKE_DEBUG_POSTFIX _d) + +# ------------------------------------------------------------------------------ +# This property setting also needs to be consistent between the installed shared +# library and its consumer, otherwise most toolchains will once again reject the +# consumer's generated BMI. +# ------------------------------------------------------------------------------ +if(NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 23) +endif() + +# Neither of these two are technically needed, but they make the expectation clear +set(CMAKE_CXX_EXTENSIONS ON) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# NOTE: only with Ninja generator install of bmi files works yet! +if(CMAKE_GENERATOR MATCHES "Ninja") + if( + CMAKE_CXX_COMPILER_ID STREQUAL "Clang" + AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0 + ) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + + if(NOT LINUX) + string(APPEND CMAKE_CXX_MODULE_MAP_FLAG " -fmodules-reduced-bmi") + endif() + + add_compile_options($ENV{CXXFLAGS}) + add_link_options($ENV{CXXFLAGS}) + elseif( + CMAKE_CXX_COMPILER_ID STREQUAL "GNU" + AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0 + ) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + else() + set(CMAKE_CXX_SCAN_FOR_MODULES OFF) + endif() +endif() + +if(CMAKE_CXX_STDLIB_MODULES_JSON) + message( + STATUS + "CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON}" + ) +endif() + +if(NOT DEFINED CMAKE_CXX_MODULE_STD) + set(CMAKE_CXX_MODULE_STD OFF) +endif() + +option( + BEMAN_USE_STD_MODULE + "Check if 'import std;' is possible with the toolchain" + OFF +) +message(STATUS "BEMAN_USE_STD_MODULE=${BEMAN_USE_STD_MODULE}") + +if(BEMAN_USE_STD_MODULE) + # ------------------------------------------------------------------------- + # Tell CMake that we explicitly want `import std`. + # This will initialize the property on all targets declared after this to 1 + # ------------------------------------------------------------------------- + message( + STATUS + "CMAKE_CXX_COMPILER_IMPORT_STD=${CMAKE_CXX_COMPILER_IMPORT_STD}" + ) + if(${CMAKE_CXX_STANDARD} IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD) + set(CMAKE_CXX_MODULE_STD ON) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + option( + BEMAN_HAS_IMPORT_STD + "Build with import std; possible" + ${CMAKE_CXX_MODULE_STD} + ) + message(STATUS "BEMAN_HAS_IMPORT_STD=${BEMAN_HAS_IMPORT_STD}") + message(STATUS "CMAKE_CXX_MODULE_STD=${CMAKE_CXX_MODULE_STD}") + else() + set(CMAKE_CXX_MODULE_STD OFF) + message(WARNING "CMAKE_CXX_MODULE_STD=${CMAKE_CXX_MODULE_STD}") + endif() +endif() +message(STATUS "CMAKE_CXX_SCAN_FOR_MODULES=${CMAKE_CXX_SCAN_FOR_MODULES}") + +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}") + +# ------------------------------------------------------------------------------ +# Avoid creating CMAKE_..._OUTPUT_DIRECTORY as cache variables, they should not +# be under the control of the developer. They should be controlled by the +# project because parts of the project may make assumptions about the relative +# layout of the binaries. More importantly, leaving them as ordinary variables +# also means they can be unset within subdirectories where test executables are +# defined, allowing them to avoid being collected with the other main binaries +# and cluttering up that area. +# ------------------------------------------------------------------------------ +set(stageDir ${CMAKE_CURRENT_BINARY_DIR}/stagedir) +include(GNUInstallDirs) + +if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_BINDIR}) +endif() +if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_LIBDIR}) +endif() +if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_LIBDIR}) +endif() diff --git a/cmake/prelude.cmake b/cmake/prelude.cmake new file mode 100644 index 00000000..c7b86338 --- /dev/null +++ b/cmake/prelude.cmake @@ -0,0 +1,114 @@ +# +# This file must be included/used as CMAKE_PROJECT_TOP_LEVEL_INCLUDES -> before project() is called! +# + +# ---- The include guard applies globally to the whole build ---- +include_guard(GLOBAL) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message( + FATAL_ERROR + "In-source builds are not supported. " + "Please read the BUILDING document before trying to build this project. " + "You may need to delete 'CMakeCache.txt' and 'CMakeFiles/' first." + ) +endif() + +if(PROJECT_NAME) + message( + FATAL_ERROR + "This CMake file has to be included before first project() command call!" + ) +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}) + +# --------------------------------------------------------------------------- +# check if import std; is supported by CMAKE_CXX_COMPILER +# --------------------------------------------------------------------------- +if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.2) + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") +endif() +# gersemi: on + +# 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() + +# --------------------------------------------------------------------------- +# Workaround needed for CMAKE and clang++ to find the libc++.modules.json file +# --------------------------------------------------------------------------- +if( + CMAKE_VERSION VERSION_GREATER_EQUAL 4.2 + AND ("$ENV{CXX}" MATCHES "clang" OR CMAKE_CXX_COMPILER MATCHES "clang") +) + # NOTE: Always use libc++ + # see https://releases.llvm.org/19.1.0/projects/libcxx/docs/index.html + set(ENV{CXXFLAGS} -stdlib=libc++) + message(STATUS "CXXFLAGS=-stdlib=libc++") + + if(APPLE) + execute_process( + OUTPUT_VARIABLE LLVM_PREFIX + COMMAND brew --prefix llvm + COMMAND_ECHO STDOUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + file(REAL_PATH ${LLVM_PREFIX} LLVM_DIR) + set(LLVM_DIR ${LLVM_DIR} CACHE FILEPATH "") + + message(STATUS "LLVM_DIR=${LLVM_DIR}") + add_link_options(-L${LLVM_DIR}/lib/c++) + include_directories(SYSTEM ${LLVM_DIR}/include) + + set(CMAKE_CXX_STDLIB_MODULES_JSON + ${LLVM_DIR}/lib/c++/libc++.modules.json + ) + elseif(LINUX) + execute_process( + OUTPUT_VARIABLE LLVM_MODULES + COMMAND clang++ -print-file-name=c++/libc++.modules.json + COMMAND_ECHO STDOUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT CMAKE_CXX_STDLIB_MODULES_JSON) + set(CMAKE_CXX_STDLIB_MODULES_JSON ${LLVM_MODULES}) + endif() + message( + STATUS + "CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON}" + ) + endif() + + if(EXISTS ${CMAKE_CXX_STDLIB_MODULES_JSON}) + message( + STATUS + "CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON}" + ) + # gersemi: off + set(CACHE{CMAKE_CXX_STDLIB_MODULES_JSON} + TYPE FILEPATH + HELP "Result of: clang++ -print-file-name=c++/libc++.modules.json" + VALUE ${CMAKE_CXX_STDLIB_MODULES_JSON} + ) + # gersemi: on + else() + message( + WARNING + "File does NOT EXISTS! ${CMAKE_CXX_STDLIB_MODULES_JSON}" + ) + endif() +endif() diff --git a/cmake/presets/CMakeDarwinPresets.json b/cmake/presets/CMakeDarwinPresets.json index 04528268..8ce5fb03 100644 --- a/cmake/presets/CMakeDarwinPresets.json +++ b/cmake/presets/CMakeDarwinPresets.json @@ -8,7 +8,6 @@ "name": "debug-base-Darwin", "hidden": true, "cacheVariables": { - "CMAKE_CXX_STDLIB_MODULES_JSON": "$env{CMAKE_CXX_STDLIB_MODULES_JSON}", "CMAKE_BUILD_TYPE": "Debug" }, "condition": { @@ -21,7 +20,6 @@ "name": "release-base-Darwin", "hidden": true, "cacheVariables": { - "CMAKE_CXX_STDLIB_MODULES_JSON": "$env{CMAKE_CXX_STDLIB_MODULES_JSON}", "CMAKE_BUILD_TYPE": "RelWithDebInfo" }, "condition": { diff --git a/cmake/presets/CMakeGenericPresets.json b/cmake/presets/CMakeGenericPresets.json index 826484cc..d222b74b 100644 --- a/cmake/presets/CMakeGenericPresets.json +++ b/cmake/presets/CMakeGenericPresets.json @@ -1,5 +1,5 @@ { - "version": 6, + "version": 9, "configurePresets": [ { "name": "root-config", diff --git a/cmake/presets/CMakeLinuxPresets.json b/cmake/presets/CMakeLinuxPresets.json index 61f9b24a..73716857 100644 --- a/cmake/presets/CMakeLinuxPresets.json +++ b/cmake/presets/CMakeLinuxPresets.json @@ -1,5 +1,5 @@ { - "version": 6, + "version": 9, "include": [ "CMakeGenericPresets.json" ], @@ -8,7 +8,6 @@ "name": "debug-base-Linux", "hidden": true, "cacheVariables": { - "CMAKE_CXX_STDLIB_MODULES_JSON": "$env{CMAKE_CXX_STDLIB_MODULES_JSON}", "CMAKE_BUILD_TYPE": "Debug" }, "condition": { @@ -21,7 +20,6 @@ "name": "release-base-Linux", "hidden": true, "cacheVariables": { - "CMAKE_CXX_STDLIB_MODULES_JSON": "$env{CMAKE_CXX_STDLIB_MODULES_JSON}", "CMAKE_BUILD_TYPE": "RelWithDebInfo" }, "condition": { diff --git a/cmake/presets/CMakeWindowsPresets.json b/cmake/presets/CMakeWindowsPresets.json index d8834f2c..6ab8f1cf 100644 --- a/cmake/presets/CMakeWindowsPresets.json +++ b/cmake/presets/CMakeWindowsPresets.json @@ -1,5 +1,5 @@ { - "version": 6, + "version": 9, "include": [ "CMakeGenericPresets.json" ], diff --git a/docs/code/CMakeLists.txt b/docs/code/CMakeLists.txt index d22c6ca5..21b13180 100644 --- a/docs/code/CMakeLists.txt +++ b/docs/code/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # gersemi: on -list(APPEND EXAMPLES) +set(EXAMPLES) # if(BEMAN_USE_MODULES) # list(APPEND EXAMPLES modules) # modules.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index baa1019e..807929fe 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,8 +3,25 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # gersemi: on -list( - APPEND EXAMPLES +cmake_minimum_required(VERSION 3.30...4.2) + +include(../cmake/prelude.cmake) + +project(beman_execution.example LANGUAGES CXX) + +if(PROJECT_IS_TOP_LEVEL) + include(../cmake/cxx-modules-rules.cmake) + + if(NOT DEFINED BEMAN_USE_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES OFF) + endif() + + find_package(beman_execution 0.1.0 EXACT REQUIRED) + + enable_testing() +endif() + +set(EXAMPLES stackoverflow inspect playground @@ -22,15 +39,20 @@ list( ) if(BEMAN_USE_MODULES) - list(APPEND EXAMPLES modules) # modules.cpp + # FIXME: not yet! list(APPEND EXAMPLES modules) # modules.cpp endif() foreach(EXAMPLE ${EXAMPLES}) - set(EXAMPLE_TARGET ${TARGET_PREFIX}.examples.${EXAMPLE}) + set(EXAMPLE_TARGET ${PROJECT_NAME}.${EXAMPLE}) add_executable(${EXAMPLE_TARGET}) target_sources(${EXAMPLE_TARGET} PRIVATE ${EXAMPLE}.cpp) - target_link_libraries( - ${EXAMPLE_TARGET} - PRIVATE ${TARGET_NAMESPACE}::${TARGET_NAME} - ) + if(BEMAN_USE_MODULES) + target_link_libraries(${EXAMPLE_TARGET} PRIVATE beman::beman_execution) + else() + target_link_libraries( + ${EXAMPLE_TARGET} + PRIVATE beman::beman_execution_headers + ) + endif() + add_test(NAME ${EXAMPLE_TARGET} COMMAND ${EXAMPLE_TARGET}) endforeach() diff --git a/examples/modules.cpp b/examples/modules.cpp index a79229ae..feab7927 100644 --- a/examples/modules.cpp +++ b/examples/modules.cpp @@ -1,12 +1,10 @@ // examples/modules.cpp -*-C++-*- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// FIXME: does not compile with g++-15 on OSX! CK -// #if defined(__APPLE__) && defined(__GNUC__) -// FIXME: does not seem to compile with g++-15 in Docker! DK -#if defined(__GNUC__) +#ifndef WIN32 #undef BEMAN_HAS_IMPORT_STD #endif + #ifdef BEMAN_HAS_IMPORT_STD import std; #else @@ -20,8 +18,21 @@ import std; #endif +#if defined(__cpp_modules) && __cpp_modules < 201907L + +#ifdef BEMAN_USE_MODULES +#warning "__cpp_modules seems not usable!" +import beman.execution; +#else +#include +#endif + +#else + import beman.execution; +#endif + namespace ex = beman::execution; int main() { diff --git a/src/beman/execution/CMakeLists.txt b/src/beman/execution/CMakeLists.txt index e8fbe2d2..b0653ea6 100644 --- a/src/beman/execution/CMakeLists.txt +++ b/src/beman/execution/CMakeLists.txt @@ -4,13 +4,12 @@ # gersemi: on if(NOT TARGET ${TARGET_NAME}) - add_library(${TARGET_NAME} STATIC) + add_library(${TARGET_NAME} INTERFACE) endif() -add_library(${TARGET_ALIAS} ALIAS ${TARGET_NAME}) +add_library(beman::${TARGET_NAME} ALIAS ${TARGET_NAME}) target_sources( ${TARGET_NAME} - PRIVATE execution.cpp PUBLIC FILE_SET ${TARGET_NAME}_public_headers TYPE HEADERS @@ -196,14 +195,19 @@ target_sources( ${PROJECT_SOURCE_DIR}/include/beman/execution/detail/write_env.hpp ) +set(TARGET_LIST ${TARGET_NAME}) + if(BEMAN_USE_MODULES) target_sources( - ${TARGET_NAME} + beman_execution + PRIVATE execution.cpp PUBLIC FILE_SET CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR}/src/beman/execution FILES ${PROJECT_SOURCE_DIR}/src/beman/execution/execution.cppm ) + target_link_libraries(beman_execution PUBLIC ${TARGET_NAME}) + list(APPEND TARGET_LIST beman_execution) endif() get_property( @@ -220,8 +224,8 @@ if(NOT BEMAN_EXECUTION_ENABLE_INSTALL OR CMAKE_SKIP_INSTALL_RULES) endif() install( - TARGETS ${TARGET_NAME} - EXPORT ${TARGETS_EXPORT_NAME}1 + TARGETS ${TARGET_LIST} + EXPORT ${TARGETS_EXPORT_NAME} ARCHIVE DESTINATION lib/$ FILE_SET HEADERS FILE_SET ${TARGET_NAME}_public_headers @@ -233,10 +237,10 @@ install( ) install( - EXPORT ${TARGETS_EXPORT_NAME}1 + EXPORT ${TARGETS_EXPORT_NAME} FILE ${TARGETS_EXPORT_NAME}.cmake DESTINATION "${INSTALL_CONFIGDIR}" - NAMESPACE ${TARGET_NAMESPACE}:: + NAMESPACE beman:: CXX_MODULES_DIRECTORY . ) diff --git a/src/beman/execution/execution.cppm b/src/beman/execution/execution.cppm index 466a158b..76690cf8 100644 --- a/src/beman/execution/execution.cppm +++ b/src/beman/execution/execution.cppm @@ -7,11 +7,10 @@ module; +#include + #include -#if defined(__APPLE__) && defined(__GNUC__) -#undef BEMAN_HAS_IMPORT_STD -#endif #ifdef BEMAN_HAS_IMPORT_STD import std; #else @@ -40,7 +39,9 @@ export module beman.execution; // ---------------------------------------------------------------------------- +#ifndef BEMAN_EXECUTION_EXPORT #define BEMAN_EXECUTION_EXPORT +#endif #if defined(disabled__cpp_deleted_function) #define BEMAN_EXECUTION_DELETE(msg) delete (msg) diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index 465567b7..12a40d7a 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -1,12 +1,5 @@ # src/beman/execution/tests/CMakeLists.txt # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required(VERSION 3.25...4.2) - -project(beman_execution_tests LANGUAGES CXX) - -if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) - message(FATAL_ERROR "In-source builds are not allowed!") -endif() list(APPEND todo exec-associate.test) @@ -118,11 +111,45 @@ list( include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) foreach(test ${execution_tests}) - set(TEST_EXE ${TARGET_PREFIX}.${test}) + set(TEST_EXE ${PROJECT_NAME}.${test}) add_executable(${TEST_EXE} ${test}.cpp) if(BEMAN_USE_MODULES) - target_compile_definitions(${TARGET_NAME} PUBLIC BEMAN_USE_MODULES) + target_link_libraries(${TEST_EXE} PRIVATE beman::beman_execution) + else() + target_link_libraries( + ${TEST_EXE} + PRIVATE beman::beman_execution_headers + ) endif() - target_link_libraries(${TEST_EXE} PRIVATE beman::execution) add_test(NAME ${TEST_EXE} COMMAND $) endforeach() + +if(BEMAN_EXECUTION_ENABLE_INSTALL) + # test if the targets are usable from the install directory + add_test( + NAME install-to-stagedir + COMMAND + ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --prefix + ${CMAKE_BINARY_DIR}/stagedir --config $ + ) + add_test( + NAME find-package-test + COMMAND + ${CMAKE_CTEST_COMMAND} # --verbose + --output-on-failure -C $ # + --build-and-test "${CMAKE_SOURCE_DIR}/examples" + "${CMAKE_CURRENT_BINARY_DIR}/find-package-test" # + --build-generator ${CMAKE_GENERATOR} # + --build-makeprogram ${CMAKE_MAKE_PROGRAM} # + --build-options # + "-D BEMAN_USE_MODULES=${BEMAN_USE_MODULES}" + "-D 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" + ) +endif()