Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.cpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
- { name: "CPU (clang 16, Release)", build: "Release", tag: llvm16-cuda12.9, cxxstd: "20", cxxflags: "-stdlib=libc++" }
- { name: "CPU (clang 16, Release, ASAN)", build: "Release", tag: llvm16-cuda12.9, cxxstd: "20", cxxflags: "-stdlib=libc++ -fsanitize=address -fsanitize-ignorelist=/home/coder/stdexec/sanitizer-ignorelist.txt" }
- { name: "CPU (clang 22, Debug)", build: "Debug", tag: llvm22-cuda13.2, cxxstd: "23", cxxflags: "-stdlib=libc++" }
- { name: "CPU (clang 22, Debug, modules)", build: "Debug", tag: llvm22-cuda13.2, cxxstd: "23", cxxflags: "-stdlib=libc++" }
- { name: "CPU (clang 22, Release)", build: "Release", tag: llvm22-cuda13.2, cxxstd: "23", cxxflags: "-stdlib=libc++" }
- { name: "CPU (clang 22, Release, noexcept)", build: "Release", tag: llvm22-cuda13.2, cxxstd: "23", cxxflags: "-stdlib=libc++ -fno-exceptions" }
- { name: "CPU (gcc 12, Debug)", build: "Debug", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "", }
Expand Down Expand Up @@ -116,6 +117,9 @@ jobs:
-DCMAKE_CXX_STANDARD:STRING=${{ matrix.cxxstd }} \
-DCMAKE_CXX_EXTENSIONS:BOOL=OFF \
-DSTDEXEC_BUILD_TESTS:BOOL=ON \
-DSTDEXEC_BUILD_EXAMPLES:BOOL=${{ !contains(matrix.name, 'modules') }} \

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As of this commit, the examples don't build with modules enabled, so disable them for now.

-DSTDEXEC_BUILD_MODULES:BOOL=${{ contains(matrix.name, 'modules') }} \
-DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-22/lib/libc++.modules.json \

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clearly wrong in the long term, but I think it'll unblock CI for now.

;

# Compile
Expand Down
94 changes: 73 additions & 21 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.25.0)
cmake_minimum_required(VERSION 3.28.0)

set(ENV{SCCACHE_NO_DIST_COMPILE} "1")

Expand All @@ -23,6 +23,8 @@ if(POLICY CMP0167)
set(CMAKE_POLICY_DEFAULT_CMP0167 NEW)
endif()

include(cmake/enable-experimental-import-std.cmake)

# ##############################################################################
# Initialize rapids-cmake
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/RAPIDS.cmake)
Expand Down Expand Up @@ -189,10 +191,25 @@ option(STDEXEC_BUILD_RELACY_TESTS "Build stdexec relacy tests"
set(stdexec_export_targets)

# Define the main library
add_library(stdexec INTERFACE)
option(STDEXEC_BUILD_MODULES "Build stdexec C++20 modules" OFF)
if(STDEXEC_BUILD_MODULES)
set(stdexec_scope PUBLIC)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)
else()
set(stdexec_scope INTERFACE)
endif()

if(STDEXEC_BUILD_MODULES)
add_library(stdexec OBJECT)
target_compile_definitions(stdexec PUBLIC STDEXEC_BUILD_MODULES=1)
else()
set(CMAKE_CXX_SCAN_FOR_MODULES OFF)
add_library(stdexec INTERFACE)
endif()

file(GLOB_RECURSE exec_headers CONFIGURE_DEPENDS include/exec/*.hpp)
file(GLOB_RECURSE stdexec_headers CONFIGURE_DEPENDS include/stdexec/*.hpp)

target_sources(
stdexec
PUBLIC FILE_SET
Expand All @@ -213,13 +230,28 @@ target_sources(
${CMAKE_CURRENT_BINARY_DIR}/include
FILES
${CMAKE_CURRENT_BINARY_DIR}/include/stdexec_version_config.hpp)
# Mark include directories as SYSTEM so consumers don't get warnings from
# stdexec internals
target_include_directories(
stdexec SYSTEM
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

if(STDEXEC_BUILD_MODULES)
target_sources(
stdexec
PUBLIC FILE_SET
CXX_MODULES
TYPE
CXX_MODULES
BASE_DIRS
modules
FILES
modules/stdexec.cppm)

set_target_properties(stdexec PROPERTIES CXX_MODULE_STD ON)
endif()

# Mark include directories as SYSTEM so consumers don't get warnings from stdexec internals
target_include_directories(stdexec SYSTEM ${stdexec_scope}
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

list(APPEND stdexec_export_targets stdexec)

Expand All @@ -235,10 +267,16 @@ endif()
# Declare the public include directories
include(GNUInstallDirs)

target_link_libraries(stdexec INTERFACE Threads::Threads)
target_link_libraries(stdexec ${stdexec_scope} Threads::Threads)

# Use C++20 standard
target_compile_features(stdexec INTERFACE cxx_std_20)
if(STDEXEC_BUILD_MODULES)
# Use C++23 standard; modules were introduced in 20 so this feels
# like it ought to be unnecessary, but it makes `import std` work
target_compile_features(stdexec ${stdexec_scope} cxx_std_23)
else()
# Use C++20 standard
target_compile_features(stdexec ${stdexec_scope} cxx_std_20)
endif()

# # Enable GPU compilation when using NVHPC compiler
# target_compile_options(stdexec INTERFACE
Expand All @@ -247,31 +285,31 @@ target_compile_features(stdexec INTERFACE cxx_std_20)

# Enable coroutines for GCC
target_compile_options(stdexec
INTERFACE $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-fcoroutines>)
${stdexec_scope} $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-fcoroutines>)

# Increase the concepts diagnostics depth for GCC
target_compile_options(
stdexec
INTERFACE $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-fconcepts-diagnostics-depth=10>)
${stdexec_scope} $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-fconcepts-diagnostics-depth=10>)

# Do you want a preprocessor that works? Picky, picky.
target_compile_options(
stdexec INTERFACE $<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/Zc:__cplusplus
stdexec ${stdexec_scope} $<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/Zc:__cplusplus
/Zc:preprocessor /Zc:externConstexpr /bigobj>)

set(STDEXEC_NAMESPACE
"stdexec"
CACHE STRING "The name of the top-level namespace for stdexec")
if(NOT STDEXEC_NAMESPACE STREQUAL "stdexec")
target_compile_definitions(stdexec
INTERFACE STDEXEC_NAMESPACE=${STDEXEC_NAMESPACE})
${stdexec_scope} STDEXEC_NAMESPACE=${STDEXEC_NAMESPACE})
endif()

option(STDEXEC_ENABLE_EXTRA_TYPE_CHECKING
"Enable extra type checking that is costly at compile-time" OFF)
if(STDEXEC_ENABLE_EXTRA_TYPE_CHECKING)
target_compile_definitions(stdexec
INTERFACE STDEXEC_ENABLE_EXTRA_TYPE_CHECKING)
${stdexec_scope} STDEXEC_ENABLE_EXTRA_TYPE_CHECKING)
endif()

add_library(STDEXEC::stdexec ALIAS stdexec)
Expand Down Expand Up @@ -566,6 +604,7 @@ endif()

# ##############################################################################
# Install targets ------------------------------------------------------------
# TODO: this is broken in the modules build
if(STDEXEC_INSTALL)
include(CPack)

Expand All @@ -574,10 +613,23 @@ if(STDEXEC_INSTALL)
list(APPEND stdexec_install_targets parallel_scheduler)
endif()

install(
TARGETS ${stdexec_install_targets}
EXPORT stdexec-exports
FILE_SET headers FILE_SET version_config)
if(STDEXEC_BUILD_MODULES)
install(
TARGETS ${stdexec_install_targets}
EXPORT stdexec-exports
FILE_SET headers FILE_SET version_config
# I cargo-culted this modules-handling stuff from Beman
FILE_SET CXX_MODULES
DESTINATION "${CMAKE_INSTALL_DATADIR}/stdexec/modules"
CXX_MODULES_BMI
DESTINATION ${CMAKE_INSTALL_DATADIR}/stdexec/bmi-${CMAKE_CXX_COMPILER_ID}_$<CONFIG>
COMPONENT stdexec_Development)
else()
install(
TARGETS ${stdexec_install_targets}
EXPORT stdexec-exports
FILE_SET headers FILE_SET version_config)
endif()

# ############################################################################
# Install exports ------------------------------------------------------------
Expand Down
35 changes: 35 additions & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,38 @@ stdexec should follow.
on implementation details if needed for correctness; otherwise, leave
them unconstrained. Use `static_assert` if you must, but don't bother
rechecking things that were already checked at the public interface.

* Regarding the modularized build:
* Enable the modularized build with `-DSTDEXEC_BUILD_MODULES=1` at
configure time. It has so far only been tested with Clang 22.
* Every header that is transitively included by `modules/stdexec.cppm` must
check its build context:
* if `STDEXEC_USE_MODULES()` is true then modules are enabled
* if `STDEXEC_IN_MODULE_PURVIEW` is defined then not only are modules
enabled, but also the header is being included in the module definition
unit (i.e. inside `modules/stdexec.cppm` for headers in
`include/stdexec`)
* otherwise, this is a normal include into a non-modules TU
* When `STDEXEC_USE_MODULES()` is true and `STDEXEC_IN_MODULE_PURVIEW` is
defined, the header's job is to define its part of the module unit so it
should behave mostly like a traditional include. One key difference from
traditional inclusion is that standard headers should *not* be included;
instead, use `import std;`.
* When `STDEXEC_USE_MODULES()` is true and `STDEXEC_IN_MODULE_PURVIEW` is
not defined, the header should do nothing but `import stdexec;`
* Otherwise, headers should behave as normal.
* Within the header, use `STDEXEC_MODULE_EXPORT` to expose symbols through
the module interface; for symbols that are part of the metaprogramming
library in `include/stdexec/__detail/__meta.hpp` that are used outside
the module's purview, export them with `STDEXEC_MODULE_EXPORT_META`;
this is a stopgap that will need to be changed eventually. Similarly,
for logically-module-private symbols that are used in the tests or in
the `include/exec` directory, export them with
`STDEXEC_MODULE_EXPORT_AUTHORING`.

* The first non-comment, non-blank line in a test file should be
`#include <catch2/catch_all.hpp>` so as not to break the modules build.
If compile-time behavior needs to differ between modularized and
traditional builds, the next inclusion should be
`#include <stdexec/__detail/__config.hpp>` so that `STDEXEC_USE_MODULES()`
is defined and can be checked.
24 changes: 24 additions & 0 deletions cmake/enable-experimental-import-std.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.3.0")
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"451f2fe2-a8a2-47c3-bc32-94786d8fc91b"
)
elseif(CMAKE_VERSION VERSION_GREATER_EQUAL "3.30.0")
if(CMAKE_VERSION VERSION_LESS "3.31.8")
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"0e5b6991-d74f-4b3d-a41c-cf096e0b2508"
)
elseif(CMAKE_VERSION VERSION_LESS "4.0.0")
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"d0edc3af-4c50-42ea-a356-e2862fe7a444"
)
elseif(CMAKE_VERSION VERSION_LESS "4.0.3")
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"a9e1cf81-9932-4810-974b-6eccaf14e457"
)
elseif(CMAKE_VERSION VERSION_LESS "4.3.0")
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"d0edc3af-4c50-42ea-a356-e2862fe7a444"
)
endif()
endif()
65 changes: 38 additions & 27 deletions include/stdexec/__detail/__any.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,35 @@
*/
#pragma once

#include "__concepts.hpp"
#include "__config.hpp"
#include "__memory.hpp"
#include "__type_traits.hpp"
#include "__typeinfo.hpp"
#include "__utility.hpp"

#include <cstddef>
#include <cstdint>
#include <cstring>
#if STDEXEC_USE_MODULES() && !defined(STDEXEC_IN_MODULE_PURVIEW)

#include <bit>
#include <exception>
#include <memory>
#include <span>
#include <type_traits>
#include <utility>
import stdexec;

#include "__prologue.hpp"
#else

# include "__concepts.hpp"
# include "__config.hpp"
# include "__memory.hpp"
# include "__type_traits.hpp"
# include "__typeinfo.hpp"
# include "__utility.hpp"

# if !STDEXEC_USE_MODULES()
# include <cstddef>
# include <cstdint>
# include <cstring>

# include <bit>
# include <exception>
# include <memory>
# include <span>
# include <type_traits>
# include <utility>
# endif

# include "__prologue.hpp"

STDEXEC_PRAGMA_IGNORE_GNU("-Wredundant-consteval-if")
STDEXEC_PRAGMA_IGNORE_GNU("-Warray-bounds")
Expand Down Expand Up @@ -465,15 +475,15 @@ namespace STDEXEC::__any
: __val_(static_cast<_Args &&>(__args)...)
{}

#if !STDEXEC_GCC()
# if !STDEXEC_GCC()
template <class _Fn, class... _Args>
constexpr explicit __box(__in_place_from_t, _Fn &&__fn, _Args &&...__args)
noexcept(__nothrow_callable<_Fn, _Args...>)
: __val_(static_cast<_Fn &&>(__fn)(static_cast<_Args &&>(__args)...))
{
static_assert(__same_as<__call_result_t<_Fn, _Args...>, _Value>);
}
#else
# else
template <class _Fn, class... _Args>
constexpr explicit __box(__in_place_from_t, _Fn &&__fn, _Args &&...__args)
noexcept(__nothrow_callable<_Fn, _Args...>)
Expand Down Expand Up @@ -516,7 +526,7 @@ namespace STDEXEC::__any
__val_ = __rhs.__val_;
return *this;
}
#endif
# endif

template <class _Self>
[[nodiscard]]
Expand All @@ -526,16 +536,16 @@ namespace STDEXEC::__any
}

private:
#if !STDEXEC_GCC()
# if !STDEXEC_GCC()
STDEXEC_ATTRIBUTE(no_unique_address)
_Value __val_;
#else
# else
union
{
STDEXEC_ATTRIBUTE(no_unique_address)
_Value __val_;
};
#endif
# endif
};

template <class _Interface, __box_kind _BoxKind>
Expand Down Expand Up @@ -1583,28 +1593,28 @@ namespace STDEXEC::__any
struct __bad_any_cast : std::exception
{
[[nodiscard]]
#if __cpp_lib_constexpr_exceptions >= 202502L // constexpr support for std::exception
# if __cpp_lib_constexpr_exceptions >= 202502L // constexpr support for std::exception
constexpr
#endif
# endif
char const *what() const noexcept override
{
return "__bad_any_cast";
}
};

#if defined(__cpp_exceptions) && __cpp_exceptions >= 199711L
# if defined(__cpp_exceptions) && __cpp_exceptions >= 199711L
[[noreturn]]
inline void __throw_bad_any_cast()
{
throw __bad_any_cast();
}
#else
# else
[[noreturn]]
inline constexpr void __throw_bad_any_cast() noexcept
{
STDEXEC::__die("__bad_any_cast\n");
}
#endif
# endif

//////////////////////////////////////////////////////////////////////////////////////////
//! __any_static_cast
Expand Down Expand Up @@ -2254,4 +2264,5 @@ namespace STDEXEC::__any

// NOLINTEND(moderize-use-override)

#include "__epilogue.hpp"
# include "__epilogue.hpp"
#endif // !STDEXEC_USE_MODULES() || defined(STDEXEC_IN_MODULE_PURVIEW)
Loading
Loading