diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 1bb2ea2..7507cbf 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -48,7 +48,7 @@ jobs: "tests": [ "Debug.Default", "Release.Default", "Release.TSan", "Release.MaxSan", "Debug.Werror", "Debug.Dynamic", - "Debug.Coverage" + "Debug.Coverage", "Debug.-DBEMAN_TAKE_BEFORE_USE_MODULES=On" ] } ] @@ -82,7 +82,7 @@ jobs: { "stdlibs": ["libstdc++", "libc++"], "tests": [ "Debug.Default", "Release.Default", "Release.TSan", - "Release.MaxSan", "Debug.Werror", "Debug.Dynamic" + "Release.MaxSan", "Debug.Werror", "Debug.Dynamic", "Debug.-DBEMAN_TAKE_BEFORE_USE_MODULES=On" ] } ] diff --git a/CMakeLists.txt b/CMakeLists.txt index c8598d4..3514edc 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.take_before DESCRIPTION "take_before_view" @@ -24,21 +26,58 @@ option( ) # for find of beman_install_library and configure_build_telemetry +option( + BEMAN_TAKE_BEFORE_USE_MODULES + "Provide beman.take_before as a C++ module" + OFF +) + +if(BEMAN_TAKE_BEFORE_USE_MODULES) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) +endif() + +configure_file( + "${PROJECT_SOURCE_DIR}/include/beman/take_before/config_generated.hpp.in" + "${PROJECT_BINARY_DIR}/include/beman/take_before/config_generated.hpp" + @ONLY +) + include(infra/cmake/beman-install-library.cmake) include(infra/cmake/BuildTelemetryConfig.cmake) -add_library(beman.take_before INTERFACE) +if(BEMAN_TAKE_BEFORE_USE_MODULES) + add_library(beman.take_before STATIC) +else() + add_library(beman.take_before INTERFACE) +endif() add_library(beman::take_before ALIAS beman.take_before) -target_sources( - beman.take_before - PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" -) - -set_target_properties( - beman.take_before - PROPERTIES VERIFY_INTERFACE_HEADER_SETS ${PROJECT_IS_TOP_LEVEL} -) +if(BEMAN_TAKE_BEFORE_USE_MODULES) + target_sources( + beman.take_before + PUBLIC + FILE_SET CXX_MODULES + FILE_SET HEADERS + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}/include" + ) + set_target_properties(beman.take_before PROPERTIES CXX_MODULE_STD ON) + target_compile_features(beman.take_before PUBLIC cxx_std_23) +else() + target_sources( + beman.take_before + PUBLIC + FILE_SET HEADERS + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}/include" + ) + set_target_properties( + beman.take_before + PROPERTIES VERIFY_INTERFACE_HEADER_SETS ${PROJECT_IS_TOP_LEVEL} + ) +endif() add_subdirectory(include/beman/take_before) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 18fd8b4..acf245e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,4 +12,7 @@ foreach(example ${ALL_EXAMPLES}) add_executable(${example}) target_sources(${example} PRIVATE ${example}.cpp) target_link_libraries(${example} PRIVATE beman::take_before) + if(BEMAN_TAKE_BEFORE_USE_MODULES) + set_target_properties(${example} PROPERTIES CXX_MODULE_STD ON) + endif() endforeach() diff --git a/examples/take_before_compose.cpp b/examples/take_before_compose.cpp index bd73ad9..0bd2a5d 100644 --- a/examples/take_before_compose.cpp +++ b/examples/take_before_compose.cpp @@ -1,11 +1,21 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // examples/take_before_compose.cpp -#include +#include + +#if BEMAN_TAKE_BEFORE_USE_MODULES() + +import std; + +#else -#include -#include -#include + #include + #include + #include + +#endif + +#include namespace btb = beman::take_before; diff --git a/examples/take_before_direct_usage.cpp b/examples/take_before_direct_usage.cpp index 6fb3372..4847b60 100644 --- a/examples/take_before_direct_usage.cpp +++ b/examples/take_before_direct_usage.cpp @@ -1,10 +1,20 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // examples/take_before_direct_usage.cpp -#include +#include + +#if BEMAN_TAKE_BEFORE_USE_MODULES() + +import std; + +#else -#include -#include + #include + #include + +#endif + +#include namespace btb = beman::take_before; diff --git a/examples/take_before_ntbs.cpp b/examples/take_before_ntbs.cpp index 1c4a47f..862c5cb 100644 --- a/examples/take_before_ntbs.cpp +++ b/examples/take_before_ntbs.cpp @@ -1,8 +1,19 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // examples/take_before_ntbs.cpp +#include + +#if BEMAN_TAKE_BEFORE_USE_MODULES() + +import std; + +#else + + #include + +#endif + #include -#include namespace btb = beman::take_before; diff --git a/examples/take_before_text_split.cpp b/examples/take_before_text_split.cpp index 229d1cb..5286c94 100644 --- a/examples/take_before_text_split.cpp +++ b/examples/take_before_text_split.cpp @@ -4,13 +4,23 @@ // This example demonstrates the usage of beman::take_before in a range-printer. // Requires: range support (C++20). -#include +#include + +#if BEMAN_TAKE_BEFORE_USE_MODULES() + +import std; + +#else -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + +#endif + +#include namespace btb = beman::take_before; diff --git a/include/beman/take_before/CMakeLists.txt b/include/beman/take_before/CMakeLists.txt index 6ec25b2..112147d 100644 --- a/include/beman/take_before/CMakeLists.txt +++ b/include/beman/take_before/CMakeLists.txt @@ -1,3 +1,24 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -target_sources(beman.take_before PUBLIC FILE_SET HEADERS FILES take_before.hpp) +if(BEMAN_TAKE_BEFORE_USE_MODULES) + target_sources( + beman.take_before + PUBLIC + FILE_SET CXX_MODULES FILES take_before.cppm + FILE_SET HEADERS + FILES + config.hpp + take_before.hpp + "${PROJECT_BINARY_DIR}/include/beman/take_before/config_generated.hpp" + ) +else() + target_sources( + beman.take_before + PUBLIC + FILE_SET HEADERS + FILES + config.hpp + take_before.hpp + "${PROJECT_BINARY_DIR}/include/beman/take_before/config_generated.hpp" + ) +endif() diff --git a/include/beman/take_before/config.hpp b/include/beman/take_before/config.hpp new file mode 100644 index 0000000..f3998de --- /dev/null +++ b/include/beman/take_before/config.hpp @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_TAKE_BEFORE_CONFIG_HPP +#define BEMAN_TAKE_BEFORE_CONFIG_HPP + +#if !defined(__has_include) || __has_include() + #include +#else + #define BEMAN_TAKE_BEFORE_USE_MODULES() 0 +#endif + +#endif diff --git a/include/beman/take_before/config_generated.hpp.in b/include/beman/take_before/config_generated.hpp.in new file mode 100644 index 0000000..a6dbcba --- /dev/null +++ b/include/beman/take_before/config_generated.hpp.in @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef BEMAN_TAKE_BEFORE_CONFIG_GENERATED_HPP +#define BEMAN_TAKE_BEFORE_CONFIG_GENERATED_HPP + +#cmakedefine01 BEMAN_TAKE_BEFORE_USE_MODULES() + +#endif diff --git a/include/beman/take_before/take_before.cppm b/include/beman/take_before/take_before.cppm new file mode 100644 index 0000000..0c7a489 --- /dev/null +++ b/include/beman/take_before/take_before.cppm @@ -0,0 +1,11 @@ +export module beman.take_before; + +import std; + +#define BEMAN_TAKE_BEFORE_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/take_before/take_before.hpp b/include/beman/take_before/take_before.hpp index 1f505fa..bcfb7f4 100644 --- a/include/beman/take_before/take_before.hpp +++ b/include/beman/take_before/take_before.hpp @@ -3,15 +3,27 @@ #ifndef BEMAN_TAKE_BEFORE_TAKE_BEFORE_HPP #define BEMAN_TAKE_BEFORE_TAKE_BEFORE_HPP -#include -#include -#include -#include -#include -#include -#include - -// clang-format off +#include + +#if BEMAN_TAKE_BEFORE_USE_MODULES() && !defined(BEMAN_TAKE_BEFORE_INCLUDED_FROM_INTERFACE_UNIT) + +import beman.take_before; + +#else + + #if !BEMAN_TAKE_BEFORE_USE_MODULES() + + #include + #include + #include + #include + #include + #include + #include + + #endif // !BEMAN_TAKE_BEFORE_USE_MODULES() + + // clang-format off #if __cpp_concepts > 202002L #error "C++20 concepts is required" #endif @@ -30,8 +42,8 @@ using maybe_const = std::conditional_t; // [range.utility.helpers] simple-view - exposition only template concept simple_view = std::ranges::view && std::ranges::range && - std::same_as, std::ranges::iterator_t> && - std::same_as, std::ranges::sentinel_t>; + std::same_as, std::ranges::iterator_t > && + std::same_as, std::ranges::sentinel_t >; // ============================================================================ // tidy-obj concept for borrowed range optimization @@ -53,7 +65,7 @@ using movable_box = std::optional; template requires std::ranges::input_range && std::is_object_v && std::indirect_binary_predicate, const T*> -class take_before_view : public std::ranges::view_interface> { +class take_before_view : public std::ranges::view_interface > { template class sentinel; // exposition only @@ -143,7 +155,7 @@ class take_before_view::sentinel { sentinel() = default; constexpr sentinel(sentinel s) - requires Const && std::convertible_to, std::ranges::sentinel_t> + requires Const && std::convertible_to, std::ranges::sentinel_t > : end_(std::move(s.end_)) { if constexpr (!tidy_obj) { value_ = s.value_; @@ -161,8 +173,10 @@ class take_before_view::sentinel { } template - requires std::sentinel_for, std::ranges::iterator_t>> - friend constexpr bool operator==(const std::ranges::iterator_t>& x, const sentinel& y) { + requires std::sentinel_for, + std::ranges::iterator_t > > + friend constexpr bool operator==(const std::ranges::iterator_t >& x, + const sentinel& y) { if constexpr (tidy_obj) { return y.end_ == x || T() == *x; } else { @@ -183,7 +197,7 @@ take_before_view(R&&, T) -> take_before_view, T>; namespace std::ranges { template -constexpr bool enable_borrowed_range> = +constexpr bool enable_borrowed_range > = enable_borrowed_range && beman::take_before::tidy_obj; } // namespace std::ranges @@ -241,7 +255,7 @@ struct take_before_fn { // Overload 3: single argument for pipe operator template constexpr auto operator()(T&& value) const { - return detail::take_before_closure>(std::forward(value)); + return detail::take_before_closure >(std::forward(value)); } }; @@ -249,4 +263,7 @@ inline constexpr take_before_fn take_before; } // namespace beman::take_before::views +#endif // #if BEMAN_TAKE_BEFORE_USE_MODULES() && + // !defined(BEMAN_TAKE_BEFORE_INCLUDED_FROM_INTERFACE_UNIT) + #endif // BEMAN_TAKE_BEFORE_TAKE_BEFORE_HPP diff --git a/port/portfile.cmake.in b/port/portfile.cmake.in index dd81274..5333b6c 100644 --- a/port/portfile.cmake.in +++ b/port/portfile.cmake.in @@ -7,9 +7,16 @@ vcpkg_from_github( HEAD_REF main ) +vcpkg_check_features( + OUT_FEATURE_OPTIONS FEATURE_OPTIONS + FEATURES + modules BEMAN_TAKE_BEFORE_USE_MODULES +) + vcpkg_cmake_configure( SOURCE_PATH "${SOURCE_PATH}" OPTIONS + ${FEATURE_OPTIONS} -DBEMAN_TAKE_BEFORE_BUILD_TESTS=OFF -DBEMAN_TAKE_BEFORE_BUILD_EXAMPLES=OFF ) @@ -21,9 +28,11 @@ vcpkg_cmake_config_fixup( CONFIG_PATH lib/cmake/beman.take_before ) -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 34977c6..906ca89 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.take_before as a C++ module" + } + } } diff --git a/tests/beman/take_before/CMakeLists.txt b/tests/beman/take_before/CMakeLists.txt index dd1e00b..f22f460 100644 --- a/tests/beman/take_before/CMakeLists.txt +++ b/tests/beman/take_before/CMakeLists.txt @@ -9,5 +9,9 @@ target_link_libraries( PRIVATE beman::take_before GTest::gtest_main ) +if(BEMAN_TAKE_BEFORE_USE_MODULES) + set_target_properties(beman.take_before.tests PROPERTIES CXX_MODULE_STD ON) +endif() + include(GoogleTest) gtest_discover_tests(beman.take_before.tests DISCOVERY_TIMEOUT 60) diff --git a/tests/beman/take_before/take_before.test.cpp b/tests/beman/take_before/take_before.test.cpp index 4d23b42..035d3cd 100644 --- a/tests/beman/take_before/take_before.test.cpp +++ b/tests/beman/take_before/take_before.test.cpp @@ -1,14 +1,24 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include +#include #include -#include -#include -#include -#include -#include +#if BEMAN_TAKE_BEFORE_USE_MODULES() + +import std; + +#else + + #include + #include + #include + #include + #include + +#endif + +#include namespace tb = beman::take_before;