From 07de1f638de0860ea9e8830a8790a2208fc0c6a2 Mon Sep 17 00:00:00 2001 From: Edward Nolan Date: Sat, 2 May 2026 18:18:50 -0600 Subject: [PATCH] Implement modules support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This approach to modules implementation is based on the approach used to implement module support for Boost by Rubén Pérez (anarthal). See his documentation: https://github.com/anarthal/boost-cmake/blob/e29bc2a5bd3493d353bf597610d4b32b5a11d0dc/modules.md The basic idea is that every header is in one of three modes: - Normal mode (the user included the header, and we aren't building with modules) - In this case, the macros configure the header so its contents are the same as their pre-refactor state - included-from-interface-unit-mode - Here, we're inserting all the code from the header into an export block inside the implementation of the .cppm file, so this mode is the same as normal mode except that we ifdef out any standard library includes, or any other dependencies that the .cppm file is bringing in via module - Compatibility header mode - The project is built as a module, but the consumer still is bringing the dependency in by writing #include <{...}.hpp>. In this case the header #ifdefs out everything except a simple import beman.foo statement. --- .github/workflows/ci_tests.yml | 55 ++++- .github/workflows/pre-commit-check.yml | 2 +- .github/workflows/pre-commit-update.yml | 2 +- .github/workflows/vcpkg-release.yml | 2 +- CMakeLists.txt | 59 +++++- examples/CMakeLists.txt | 6 + examples/transform_view_direct_usage.cpp | 5 + include/beman/transform_view/CMakeLists.txt | 26 ++- include/beman/transform_view/config.hpp | 11 + .../transform_view/config_generated.hpp.in | 8 + .../beman/transform_view/transform_view.cppm | 11 + .../beman/transform_view/transform_view.hpp | 83 +++++--- infra/.beman_submodule | 2 +- infra/.github/workflows/pre-commit.yml | 1 + infra/.pre-commit-config.yaml | 1 + infra/cmake/BuildTelemetry.cmake | 1 + infra/cmake/BuildTelemetryConfig.cmake | 1 + infra/cmake/Config.cmake.in | 2 +- infra/cmake/beman-install-library.cmake | 6 +- .../enable-experimental-import-std.cmake | 189 ++++++++++++++++++ infra/cmake/telemetry.sh | 1 + infra/cmake/use-fetch-content.cmake | 1 + port/portfile.cmake.in | 17 +- port/vcpkg.json.in | 7 +- tests/beman/transform_view/CMakeLists.txt | 6 + .../transform_view/transform_view.test.cpp | 8 +- 26 files changed, 443 insertions(+), 70 deletions(-) create mode 100644 include/beman/transform_view/config.hpp create mode 100644 include/beman/transform_view/config_generated.hpp.in create mode 100644 include/beman/transform_view/transform_view.cppm create mode 100644 infra/cmake/enable-experimental-import-std.cmake diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 002f7e7..86a9a50 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.6.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-submodule-check.yml@1.7.1 preset-test: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-preset-test.yml@1.6.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-preset-test.yml@1.7.1 with: matrix_config: > [ @@ -31,7 +31,7 @@ jobs: ] build-and-test: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-build-and-test.yml@1.6.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-build-and-test.yml@1.7.1 with: matrix_config: > { @@ -44,17 +44,37 @@ jobs: "tests": [ "Debug.Default", "Release.Default", "Release.TSan", "Release.MaxSan", "Debug.Werror", "Debug.Dynamic", - "Debug.Coverage" + "Debug.Coverage", "Debug.-DBEMAN_TRANSFORM_VIEW_USE_MODULES=True" ] } ] }, { "cxxversions": ["c++23"], - "tests": [{ "stdlibs": ["libstdc++"], "tests": ["Release.Default"]}] + "tests": [ + { "stdlibs": ["libstdc++"], + "tests": [ + "Release.Default", "Debug.-DBEMAN_TRANSFORM_VIEW_USE_MODULES=True" + ] + } + ] + } + ] + }, + { "versions": ["15"], + "tests": [ + { "cxxversions": ["c++26", "c++23"], + "tests": [ + { + "stdlibs": ["libstdc++"], + "tests": [ + "Release.Default", "Debug.-DBEMAN_TRANSFORM_VIEW_USE_MODULES=True" + ] + } + ] } ] }, - { "versions": ["15", "14"], + { "versions": ["14"], "tests": [ { "cxxversions": ["c++26", "c++23"], "tests": [{ "stdlibs": ["libstdc++"], "tests": ["Release.Default"]}] @@ -70,14 +90,19 @@ jobs: { "stdlibs": ["libstdc++", "libc++"], "tests": [ "Debug.Default", "Release.Default", "Release.TSan", - "Release.MaxSan", "Debug.Dynamic" + "Release.MaxSan", "Debug.Dynamic", + "Debug.-DBEMAN_TRANSFORM_VIEW_USE_MODULES=True" ] } ] }, { "cxxversions": ["c++23"], "tests": [ - {"stdlibs": ["libstdc++", "libc++"], "tests": ["Release.Default"]} + { "stdlibs": ["libstdc++", "libc++"], + "tests": [ + "Release.Default", "Debug.-DBEMAN_TRANSFORM_VIEW_USE_MODULES=True" + ] + } ] } ] @@ -114,7 +139,10 @@ jobs: { "cxxversions": ["c++23"], "tests": [ { "stdlibs": ["stl"], - "tests": ["Debug.Default", "Release.Default", "Release.MaxSan"] + "tests": [ + "Debug.Default", "Release.Default", "Release.MaxSan", + "Debug.-DBEMAN_TRANSFORM_VIEW_USE_MODULES=True" + ] } ] } @@ -124,11 +152,16 @@ jobs: } vcpkg-ci: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-vcpkg-ci.yml@1.6.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-vcpkg-ci.yml@1.7.1 with: port_name: beman-transform-view + feature_combinations: | + [ + {"features": {}}, + {"features": {"modules": true}} + ] 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.6.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-create-issue-when-fault.yml@1.7.1 diff --git a/.github/workflows/pre-commit-check.yml b/.github/workflows/pre-commit-check.yml index e5df5ee..b429ecf 100644 --- a/.github/workflows/pre-commit-check.yml +++ b/.github/workflows/pre-commit-check.yml @@ -10,4 +10,4 @@ on: jobs: pre-commit: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-pre-commit.yml@1.6.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-pre-commit.yml@1.7.1 diff --git a/.github/workflows/pre-commit-update.yml b/.github/workflows/pre-commit-update.yml index 445c891..995dd18 100644 --- a/.github/workflows/pre-commit-update.yml +++ b/.github/workflows/pre-commit-update.yml @@ -9,7 +9,7 @@ on: jobs: auto-update-pre-commit: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-update-pre-commit.yml@1.6.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-update-pre-commit.yml@1.7.1 secrets: APP_ID: ${{ secrets.AUTO_PR_BOT_APP_ID }} PRIVATE_KEY: ${{ secrets.AUTO_PR_BOT_PRIVATE_KEY }} diff --git a/.github/workflows/vcpkg-release.yml b/.github/workflows/vcpkg-release.yml index 872dc7f..30fbb69 100644 --- a/.github/workflows/vcpkg-release.yml +++ b/.github/workflows/vcpkg-release.yml @@ -6,7 +6,7 @@ on: types: [published] jobs: vcpkg-release: - uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-vcpkg-release.yml@1.6.0 + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-vcpkg-release.yml@1.7.1 with: port_name: beman-transform-view secrets: diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d2d559..d6db470 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.30...4.3) +include(infra/cmake/enable-experimental-import-std.cmake) + project( beman.transform_view DESCRIPTION "A conditionally borrowed std::ranges::transform_view" @@ -23,22 +25,59 @@ option( ${PROJECT_IS_TOP_LEVEL} ) +option( + BEMAN_TRANSFORM_VIEW_USE_MODULES + "Provide beman.transform_view as a C++ module" + OFF +) + +if(BEMAN_TRANSFORM_VIEW_USE_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) +endif() + +configure_file( + "${PROJECT_SOURCE_DIR}/include/beman/transform_view/config_generated.hpp.in" + "${PROJECT_BINARY_DIR}/include/beman/transform_view/config_generated.hpp" + @ONLY +) + # for find of beman_install_library and configure_build_telemetry include(infra/cmake/beman-install-library.cmake) include(infra/cmake/BuildTelemetryConfig.cmake) -add_library(beman.transform_view INTERFACE) +if(BEMAN_TRANSFORM_VIEW_USE_MODULES) + add_library(beman.transform_view STATIC) +else() + add_library(beman.transform_view INTERFACE) +endif() add_library(beman::transform_view ALIAS beman.transform_view) -target_sources( - beman.transform_view - PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" -) - -set_target_properties( - beman.transform_view - PROPERTIES VERIFY_INTERFACE_HEADER_SETS ${PROJECT_IS_TOP_LEVEL} -) +if(BEMAN_TRANSFORM_VIEW_USE_MODULES) + target_sources( + beman.transform_view + PUBLIC + FILE_SET CXX_MODULES + FILE_SET HEADERS + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}/include" + ) + set_target_properties(beman.transform_view PROPERTIES CXX_MODULE_STD ON) + target_compile_features(beman.transform_view PUBLIC cxx_std_23) +else() + target_sources( + beman.transform_view + PUBLIC + FILE_SET HEADERS + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}/include" + ) + set_target_properties( + beman.transform_view + PROPERTIES VERIFY_INTERFACE_HEADER_SETS ${PROJECT_IS_TOP_LEVEL} + ) +endif() add_subdirectory(include/beman/transform_view) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 112e633..112b7d2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -14,4 +14,10 @@ foreach(example ${ALL_EXAMPLES}) beman.transform_view.examples.${example} PRIVATE beman::transform_view ) + if(BEMAN_TRANSFORM_VIEW_USE_MODULES) + set_target_properties( + beman.transform_view.examples.${example} + PROPERTIES CXX_MODULE_STD ON + ) + endif() endforeach() diff --git a/examples/transform_view_direct_usage.cpp b/examples/transform_view_direct_usage.cpp index ddb7f00..8e396f3 100644 --- a/examples/transform_view_direct_usage.cpp +++ b/examples/transform_view_direct_usage.cpp @@ -1,8 +1,13 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include +#if BEMAN_TRANSFORM_VIEW_USE_MODULES() +import std; +#else #include +#endif namespace tv26 = beman::transform_view; diff --git a/include/beman/transform_view/CMakeLists.txt b/include/beman/transform_view/CMakeLists.txt index 86347a6..2aa122e 100644 --- a/include/beman/transform_view/CMakeLists.txt +++ b/include/beman/transform_view/CMakeLists.txt @@ -1,6 +1,24 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -target_sources( - beman.transform_view - PUBLIC FILE_SET HEADERS FILES transform_view.hpp -) +if(BEMAN_TRANSFORM_VIEW_USE_MODULES) + target_sources( + beman.transform_view + PUBLIC + FILE_SET CXX_MODULES FILES transform_view.cppm + FILE_SET HEADERS + FILES + config.hpp + transform_view.hpp + "${PROJECT_BINARY_DIR}/include/beman/transform_view/config_generated.hpp" + ) +else() + target_sources( + beman.transform_view + PUBLIC + FILE_SET HEADERS + FILES + config.hpp + transform_view.hpp + "${PROJECT_BINARY_DIR}/include/beman/transform_view/config_generated.hpp" + ) +endif() diff --git a/include/beman/transform_view/config.hpp b/include/beman/transform_view/config.hpp new file mode 100644 index 0000000..88e5d00 --- /dev/null +++ b/include/beman/transform_view/config.hpp @@ -0,0 +1,11 @@ +#ifndef BEMAN_TRANSFORM_VIEW_CONFIG_HPP +#define BEMAN_TRANSFORM_VIEW_CONFIG_HPP + +#if !defined(__has_include) || \ + __has_include() +#include +#else +#define BEMAN_TRANSFORM_VIEW_USE_MODULES() 0 +#endif + +#endif diff --git a/include/beman/transform_view/config_generated.hpp.in b/include/beman/transform_view/config_generated.hpp.in new file mode 100644 index 0000000..1c4d0dd --- /dev/null +++ b/include/beman/transform_view/config_generated.hpp.in @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_TRANSFORM_VIEW_CONFIG_GENERATED_HPP +#define BEMAN_TRANSFORM_VIEW_CONFIG_GENERATED_HPP + +#cmakedefine01 BEMAN_TRANSFORM_VIEW_USE_MODULES() + +#endif diff --git a/include/beman/transform_view/transform_view.cppm b/include/beman/transform_view/transform_view.cppm new file mode 100644 index 0000000..c1ffdb0 --- /dev/null +++ b/include/beman/transform_view/transform_view.cppm @@ -0,0 +1,11 @@ +export module beman.transform_view; + +import std; + +#define BEMAN_TRANSFORM_VIEW_INCLUDED_FROM_INTERFACE_UNIT +export { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winclude-angled-in-module-purview" +#include +#pragma clang diagnostic pop +} diff --git a/include/beman/transform_view/transform_view.hpp b/include/beman/transform_view/transform_view.hpp index 2f29b12..1049099 100644 --- a/include/beman/transform_view/transform_view.hpp +++ b/include/beman/transform_view/transform_view.hpp @@ -3,10 +3,21 @@ #ifndef BEMAN_TRANSFORM_VIEW_HPP #define BEMAN_TRANSFORM_VIEW_HPP +#include + +#if BEMAN_TRANSFORM_VIEW_USE_MODULES() && \ + !defined(BEMAN_TRANSFORM_VIEW_INCLUDED_FROM_INTERFACE_UNIT) + +import beman.transform_view; + +#else + +#if !BEMAN_TRANSFORM_VIEW_USE_MODULES() #include #include #include #include +#endif namespace beman::transform_view { @@ -38,10 +49,10 @@ constexpr auto category_tag() { return 0; // int means "no tag" } else { constexpr bool call_result_is_ref = std::is_reference_v< - std::invoke_result_t>>; + std::invoke_result_t > >; if constexpr (call_result_is_ref) { using C = typename std::iterator_traits< - std::ranges::iterator_t>::iterator_category; + std::ranges::iterator_t >::iterator_category; if constexpr (std::derived_from) { return std::random_access_iterator_tag{}; } else { @@ -133,18 +144,18 @@ struct iter_access { documented below. */ template requires std::ranges::view && std::is_object_v && - std::regular_invocable> && + std::regular_invocable > && detail::can_ref< - std::invoke_result_t>> + std::invoke_result_t > > class transform_view - : public std::ranges::view_interface> { + : public std::ranges::view_interface > { template class sentinel; template - class iterator - : public detail::iterator_category_base, - detail::maybe_const> { + class iterator : public detail::iterator_category_base< + detail::maybe_const, + detail::maybe_const > { using Parent = detail::maybe_const; using Base = detail::maybe_const; std::ranges::iterator_t current_ = @@ -162,18 +173,19 @@ class transform_view using iterator_concept = decltype(detail::concept_tag()); using value_type = std::remove_cvref_t< std::invoke_result_t&, - std::ranges::range_reference_t>>; + std::ranges::range_reference_t > >; using difference_type = std::ranges::range_difference_t; iterator() - requires std::default_initializable> + requires std::default_initializable > = default; constexpr iterator(Parent& parent, std::ranges::iterator_t current) : current_(std::move(current)), parent_(std::addressof(parent)) {} constexpr iterator(iterator i) - requires Const && std::convertible_to, - std::ranges::iterator_t> + requires Const + && std::convertible_to, + std::ranges::iterator_t > : current_(std::move(i.current_)), parent_(i.parent_) {} constexpr const std::ranges::iterator_t& base() const& noexcept { @@ -245,7 +257,7 @@ class transform_view } friend constexpr bool operator==(const iterator& x, const iterator& y) - requires std::equality_comparable> + requires std::equality_comparable > { return x.current_ == y.current_; } @@ -273,7 +285,7 @@ class transform_view #if !defined(__APPLE__) friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires std::ranges::random_access_range && - std::three_way_comparable> + std::three_way_comparable > { return x.current_ <=> y.current_; } @@ -298,7 +310,7 @@ class transform_view friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires std::sized_sentinel_for, - std::ranges::iterator_t> + std::ranges::iterator_t > { return x.current_ - y.current_; } @@ -316,8 +328,9 @@ class transform_view constexpr explicit sentinel(std::ranges::sentinel_t end) : end_(end) {} constexpr sentinel(sentinel i) - requires Const && std::convertible_to, - std::ranges::sentinel_t> + requires Const + && std::convertible_to, + std::ranges::sentinel_t > : end_(std::move(i.end_)) {} constexpr std::ranges::sentinel_t base() const { return end_; } @@ -325,7 +338,7 @@ class transform_view template requires std::sentinel_for< std::ranges::sentinel_t, - std::ranges::iterator_t>> + std::ranges::iterator_t > > friend constexpr bool operator==(const iterator& x, const sentinel& y) { #if defined(_MSC_VER) @@ -338,9 +351,9 @@ class transform_view template requires std::sized_sentinel_for< std::ranges::sentinel_t, - std::ranges::iterator_t>> + std::ranges::iterator_t > > friend constexpr std::ranges::range_difference_t< - detail::maybe_const> + detail::maybe_const > operator-(const iterator& x, const sentinel& y) { #if defined(_MSC_VER) return detail::iter_access::current(x) - y.end_; @@ -352,9 +365,9 @@ class transform_view template requires std::sized_sentinel_for< std::ranges::sentinel_t, - std::ranges::iterator_t>> + std::ranges::iterator_t > > friend constexpr std::ranges::range_difference_t< - detail::maybe_const> + detail::maybe_const > operator-(const sentinel& y, const iterator& x) { #if defined(_MSC_VER) return y.end_ - detail::iter_access::current(x); @@ -395,8 +408,9 @@ class transform_view /** Returns a `const` iterator for the beginning of `*this`. */ constexpr iterator begin() const requires std::ranges::range && - std::regular_invocable> + std::regular_invocable< + const F&, + std::ranges::range_reference_t > { return iterator{*this, std::ranges::begin(base_)}; } @@ -416,8 +430,9 @@ class transform_view /** Returns a `const` sentinel for the end of `*this`. */ constexpr sentinel end() const requires std::ranges::range && - std::regular_invocable> + std::regular_invocable< + const F&, + std::ranges::range_reference_t > { return sentinel{std::ranges::end(base_)}; } @@ -425,8 +440,9 @@ class transform_view /** Returns a `const` iterator for the end of `*this`. */ constexpr iterator end() const requires std::ranges::common_range && - std::regular_invocable> + std::regular_invocable< + const F&, + std::ranges::range_reference_t > { return iterator{*this, std::ranges::end(base_)}; } @@ -504,7 +520,7 @@ struct bind_back_t { private: using indices = std::index_sequence_for; - template + template static constexpr decltype(auto) call_impl(T&& this_, std::index_sequence, Args&&... args) { return ((T&&)this_) @@ -525,7 +541,7 @@ constexpr auto bind_back(Func&& f, Args&&... args) { } template - requires std::is_class_v && std::same_as> + requires std::is_class_v && std::same_as > struct range_adaptor_closure { template requires std::invocable @@ -544,7 +560,7 @@ struct range_adaptor_closure { #endif template -struct closure : range_adaptor_closure> { +struct closure : range_adaptor_closure > { constexpr closure(F f) : f_(f) {} template @@ -598,8 +614,11 @@ inline constexpr detail::adaptor transform = transform_impl{}; template constexpr bool std::ranges::enable_borrowed_range< - beman::transform_view::transform_view> = + beman::transform_view::transform_view > = std::ranges::borrowed_range && beman::transform_view::detail::tidy_func; +#endif // BEMAN_TRANSFORM_VIEW_USE_MODULES() && + // !defined(BEMAN_TRANSFORM_VIEW_INCLUDED_FROM_INTERFACE_UNIT) + #endif // BEMAN_TRANSFORM_VIEW_HPP diff --git a/infra/.beman_submodule b/infra/.beman_submodule index a2ad45f..f6970c1 100644 --- a/infra/.beman_submodule +++ b/infra/.beman_submodule @@ -1,3 +1,3 @@ [beman_submodule] remote=https://github.com/bemanproject/infra.git -commit_hash=1b14bad2cd2cf0e44d1aeb608557e0e35ce27eaa +commit_hash=66b4f0cdf527cb66bfe2f009f0d2b0ceb56d2cd0 diff --git a/infra/.github/workflows/pre-commit.yml b/infra/.github/workflows/pre-commit.yml index 9646831..7051c13 100644 --- a/infra/.github/workflows/pre-commit.yml +++ b/infra/.github/workflows/pre-commit.yml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception name: Lint Check (pre-commit) on: diff --git a/infra/.pre-commit-config.yaml b/infra/.pre-commit-config.yaml index 8052e18..6fe1e85 100644 --- a/infra/.pre-commit-config.yaml +++ b/infra/.pre-commit-config.yaml @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 diff --git a/infra/cmake/BuildTelemetry.cmake b/infra/cmake/BuildTelemetry.cmake index c2ff343..cc94f40 100755 --- a/infra/cmake/BuildTelemetry.cmake +++ b/infra/cmake/BuildTelemetry.cmake @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception include_guard(GLOBAL) include(${CMAKE_CURRENT_LIST_DIR}/BuildTelemetryConfig.cmake) diff --git a/infra/cmake/BuildTelemetryConfig.cmake b/infra/cmake/BuildTelemetryConfig.cmake index 15aae48..2160c34 100755 --- a/infra/cmake/BuildTelemetryConfig.cmake +++ b/infra/cmake/BuildTelemetryConfig.cmake @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception include_guard(GLOBAL) set(BUILD_TELEMETRY_DIR ${CMAKE_CURRENT_LIST_DIR}) diff --git a/infra/cmake/Config.cmake.in b/infra/cmake/Config.cmake.in index 3f1341c..df903cf 100644 --- a/infra/cmake/Config.cmake.in +++ b/infra/cmake/Config.cmake.in @@ -1,5 +1,5 @@ -# cmake/Config.cmake.in -*-makefile-*- # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# cmake/Config.cmake.in -*-makefile-*- include(CMakeFindDependencyMacro) diff --git a/infra/cmake/beman-install-library.cmake b/infra/cmake/beman-install-library.cmake index dc5a4d1..df2dbe9 100644 --- a/infra/cmake/beman-install-library.cmake +++ b/infra/cmake/beman-install-library.cmake @@ -122,7 +122,9 @@ function(beman_install_library name) endif() if(NOT BEMAN_INSTALL_DESTINATION) - set(BEMAN_INSTALL_DESTINATION "${_config_install_dir}/modules") + set(BEMAN_INSTALL_DESTINATION + "${CMAKE_INSTALL_DATADIR}/${name}/modules" + ) endif() string(REPLACE "beman." "" install_component_name "${name}") @@ -210,7 +212,7 @@ function(beman_install_library name) # NOTE: There's currently no convention for this location! CK CXX_MODULES_BMI DESTINATION - ${_config_install_dir}/bmi-${CMAKE_CXX_COMPILER_ID}_$ + ${CMAKE_INSTALL_DATADIR}/${name}/bmi-${CMAKE_CXX_COMPILER_ID}_$ COMPONENT "${install_component_name}_Development" ) else() diff --git a/infra/cmake/enable-experimental-import-std.cmake b/infra/cmake/enable-experimental-import-std.cmake new file mode 100644 index 0000000..7e8aa26 --- /dev/null +++ b/infra/cmake/enable-experimental-import-std.cmake @@ -0,0 +1,189 @@ +if(CMAKE_VERSION VERSION_EQUAL "3.30.0") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.1") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.2") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.3") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.4") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.5") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.6") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.7") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.8") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.30.9") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.0") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.1") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.10") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.11") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.12") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.2") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.3") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.4") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.5") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.6") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.7") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.8") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "3.31.9") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.0.0") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "a9e1cf81-9932-4810-974b-6eccaf14e457" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.0.1") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "a9e1cf81-9932-4810-974b-6eccaf14e457" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.0.2") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "a9e1cf81-9932-4810-974b-6eccaf14e457" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.0.3") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.0.4") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.0.5") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.0.6") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.0.7") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.1.0") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.1.1") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.1.2") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.1.3") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.1.4") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.1.5") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.1.6") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.2.0") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.2.1") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.2.2") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.2.3") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.2.4") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.2.5") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "d0edc3af-4c50-42ea-a356-e2862fe7a444" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.3.0") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "451f2fe2-a8a2-47c3-bc32-94786d8fc91b" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.3.1") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "451f2fe2-a8a2-47c3-bc32-94786d8fc91b" + ) +elseif(CMAKE_VERSION VERSION_EQUAL "4.3.2") + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "451f2fe2-a8a2-47c3-bc32-94786d8fc91b" + ) +endif() diff --git a/infra/cmake/telemetry.sh b/infra/cmake/telemetry.sh index 323982e..cb5fd88 100755 --- a/infra/cmake/telemetry.sh +++ b/infra/cmake/telemetry.sh @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #!/usr/bin/env bash set -o nounset diff --git a/infra/cmake/use-fetch-content.cmake b/infra/cmake/use-fetch-content.cmake index 73594be..3c7136d 100644 --- a/infra/cmake/use-fetch-content.cmake +++ b/infra/cmake/use-fetch-content.cmake @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception cmake_minimum_required(VERSION 3.24) include(FetchContent) diff --git a/port/portfile.cmake.in b/port/portfile.cmake.in index 948f51e..1cd2bf5 100644 --- a/port/portfile.cmake.in +++ b/port/portfile.cmake.in @@ -6,9 +6,16 @@ vcpkg_from_github( HEAD_REF main ) +vcpkg_check_features( + OUT_FEATURE_OPTIONS FEATURE_OPTIONS + FEATURES + modules BEMAN_TRANSFORM_VIEW_USE_MODULES +) + vcpkg_cmake_configure( SOURCE_PATH "${SOURCE_PATH}" OPTIONS + ${FEATURE_OPTIONS} -DBEMAN_TRANSFORM_VIEW_BUILD_TESTS=OFF -DBEMAN_TRANSFORM_VIEW_BUILD_EXAMPLES=OFF ) @@ -20,9 +27,11 @@ vcpkg_cmake_config_fixup( CONFIG_PATH lib/cmake/beman.transform_view ) -file(REMOVE_RECURSE - "${CURRENT_PACKAGES_DIR}/debug" - "${CURRENT_PACKAGES_DIR}/lib" -) +if(NOT "modules" IN_LIST FEATURES) + file(REMOVE_RECURSE + "${CURRENT_PACKAGES_DIR}/debug" + "${CURRENT_PACKAGES_DIR}/lib" + ) +endif() vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") diff --git a/port/vcpkg.json.in b/port/vcpkg.json.in index 0d06eb0..d654b00 100644 --- a/port/vcpkg.json.in +++ b/port/vcpkg.json.in @@ -13,5 +13,10 @@ "name": "vcpkg-cmake-config", "host": true } - ] + ], + "features": { + "modules": { + "description": "Provide beman.transform_view as a C++ module" + } + } } diff --git a/tests/beman/transform_view/CMakeLists.txt b/tests/beman/transform_view/CMakeLists.txt index 39360df..988d665 100644 --- a/tests/beman/transform_view/CMakeLists.txt +++ b/tests/beman/transform_view/CMakeLists.txt @@ -11,6 +11,12 @@ target_link_libraries( beman.transform_view.tests.transform_view PRIVATE beman::transform_view GTest::gtest_main ) +if(BEMAN_TRANSFORM_VIEW_USE_MODULES) + set_target_properties( + beman.transform_view.tests.transform_view + PROPERTIES CXX_MODULE_STD ON + ) +endif() include(GoogleTest) gtest_discover_tests( diff --git a/tests/beman/transform_view/transform_view.test.cpp b/tests/beman/transform_view/transform_view.test.cpp index 030b776..d89d117 100644 --- a/tests/beman/transform_view/transform_view.test.cpp +++ b/tests/beman/transform_view/transform_view.test.cpp @@ -1,15 +1,21 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include +#include #include +#if BEMAN_TRANSFORM_VIEW_USE_MODULES() +import std; +#else #include #include #include #include #include #include +#endif + +#include namespace tv26 = beman::transform_view;