diff --git a/3rd_party/stdexec/conandata.yml b/3rd_party/stdexec/conandata.yml new file mode 100644 index 00000000..9bbdb684 --- /dev/null +++ b/3rd_party/stdexec/conandata.yml @@ -0,0 +1,7 @@ +sources: + # NVIDIA stdexec, commit ea0d8788 (release nvhpc-25.09) -- the exact revision the in-tree + # FetchContent blocks (iomgr/nuraft_mesg/homestore) pin, so the conan-provided headers and the + # in-tree headers are byte-identical. + "25.09": + url: "https://github.com/NVIDIA/stdexec/archive/ea0d8788da51a1671daa00b88bf238725f0844a8.tar.gz" + sha256: "aa68f58be9854305fa09e7310ca3f4d79efb948c3df93b8904d3645be9a34751" diff --git a/3rd_party/stdexec/conanfile.py b/3rd_party/stdexec/conanfile.py new file mode 100644 index 00000000..24af24b8 --- /dev/null +++ b/3rd_party/stdexec/conanfile.py @@ -0,0 +1,52 @@ +import os + +from conan import ConanFile +from conan.tools.files import copy, get +from conan.tools.layout import basic_layout + +required_conan_version = ">=2.0" + + +class StdexecConan(ConanFile): + name = "stdexec" + description = "NVIDIA reference implementation of std::execution (P2300): senders/receivers + coroutines" + license = "Apache-2.0 WITH LLVM-exception" + url = "https://github.com/NVIDIA/stdexec" + homepage = "https://github.com/NVIDIA/stdexec" + topics = ("execution", "p2300", "senders", "coroutines", "header-only") + + # Header-only: the package is one binary for all settings (see package_id), but we keep + # settings so package_info() can branch on the consumer's compiler for warning flags. + package_type = "header-library" + settings = "os", "arch", "compiler", "build_type" + no_copy_source = True + + def layout(self): + basic_layout(self, src_folder="src") + + def package_id(self): + self.info.clear() + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def package(self): + copy(self, "LICENSE*", src=self.source_folder, + dst=os.path.join(self.package_folder, "licenses")) + copy(self, "*", src=os.path.join(self.source_folder, "include"), + dst=os.path.join(self.package_folder, "include")) + + def package_info(self): + self.cpp_info.bindirs = [] + self.cpp_info.libdirs = [] + # stdexec's include pulls libstdc++'s PSTL, which defaults to the TBB backend; + # force the serial backend so consumers don't have to link TBB. Mirrors the in-tree + # stdexec_iface targets in iomgr/nuraft_mesg/homestore. + self.cpp_info.defines = ["_PSTL_PAR_BACKEND_SERIAL"] + # stdexec internals trip a couple of warnings; suppress so -Werror consumers still build. + # -Wsubobject-linkage is gcc-only -- clang rejects it as an unknown warning option. + compiler = str(self.settings.compiler) + if compiler == "gcc": + self.cpp_info.cxxflags = ["-Wno-empty-body", "-Wno-subobject-linkage"] + elif compiler == "clang": + self.cpp_info.cxxflags = ["-Wno-empty-body"] diff --git a/conanfile.py b/conanfile.py index f11cae9e..33e1e2ea 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,13 +3,14 @@ from conan.tools.build import check_min_cppstd from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake from conan.tools.files import copy +from conan.tools.scm import Version from os.path import join required_conan_version = ">=2.0" class SISLConan(ConanFile): name = "sisl" - version = "14.4.0" + version = "14.4.1" homepage = "https://github.com/eBay/sisl" description = "Library for fast data structures, utilities" @@ -52,6 +53,15 @@ class SISLConan(ConanFile): def _min_cppstd(self): return 23 + def _use_breakpad(self): + # breakpad/cci.20210521 is frozen (2021) and fails to build with gcc >= 16; keep it for the + # other Linux/libstdc++ toolchains it does support. + if self.settings.os not in ["Linux"] or self.settings.compiler.get_safe("libcxx") == "libc++": + return False + if self.settings.compiler == "gcc" and Version(self.settings.compiler.version) >= "16": + return False + return True + def validate(self): if self.settings.compiler.get_safe("cppstd"): check_min_cppstd(self, self._min_cppstd()) @@ -83,8 +93,11 @@ def requirements(self): self.requires("nlohmann_json/3.12.0", transitive_headers=True) self.requires("spdlog/1.17.0", transitive_headers=True) self.requires("zmarok-semver/1.1.0", transitive_headers=True) + # Public sisl/async coroutine headers (task.hpp/when_all.hpp) include ; ship stdexec + # transitively so package consumers resolve it without their own FetchContent. + self.requires("stdexec/25.09", transitive_headers=True) self.requires("lz4/1.10.0", override=True) - if self.settings.os in ["Linux"] and self.settings.compiler.get_safe("libcxx") != "libc++": + if self._use_breakpad(): self.requires("breakpad/cci.20210521") # ARM needs unreleased versionof libunwind @@ -237,7 +250,7 @@ def package_info(self): "nlohmann_json::nlohmann_json", "spdlog::spdlog", ]) - if self.settings.os in ["Linux"] and self.settings.compiler.get_safe("libcxx") != "libc++": + if self._use_breakpad(): self.cpp_info.components["logging"].requires.append("breakpad::breakpad") self.cpp_info.components["sobject"].requires.extend([ "logging", @@ -251,7 +264,9 @@ def package_info(self): "logging", "zmarok-semver::zmarok-semver", ]) - sisl_requires = ["sobject", "version"] + # sisl/async coroutine headers (task.hpp/when_all.hpp) include ; the umbrella component + # carries the dependency so consumers of sisl::sisl resolve stdexec. + sisl_requires = ["sobject", "version", "stdexec::stdexec"] if self.settings.os in ["Linux"]: sisl_requires.append("file_watcher") self.cpp_info.components["sisl"].requires.extend(sisl_requires) diff --git a/prepare_v2.sh b/prepare_v2.sh index 73e5c02d..97ca1c14 100755 --- a/prepare_v2.sh +++ b/prepare_v2.sh @@ -3,4 +3,6 @@ set -eu echo -n "Exporting custom recipes..." echo -n "userspace rcu." conan export 3rd_party/userspace-rcu --name userspace-rcu --version nu2.0.14.0 >/dev/null +echo -n "stdexec." +conan export 3rd_party/stdexec --name stdexec --version 25.09 >/dev/null echo " done." diff --git a/src/async/CMakeLists.txt b/src/async/CMakeLists.txt index 1d4ae152..aa3f85ad 100644 --- a/src/async/CMakeLists.txt +++ b/src/async/CMakeLists.txt @@ -1,9 +1,8 @@ cmake_minimum_required(VERSION 3.11) -# sisl_async is header-only; the tests below need stdexec available in -# the sisl build. The wiring is up to the consumer (FetchContent in a -# feature branch today, a Conan recipe later); this CMakeLists is -# inert if stdexec hasn't been declared as a target yet. +# sisl_async is header-only; the tests below need stdexec, now provided by the conan package +# (sisl requires stdexec/25.09 -> the stdexec::stdexec target; see 3rd_party/stdexec). find_package +# is QUIET + gated so a non-conan build without stdexec just skips these tests rather than failing. # # disk_task tests have no stdexec dependency — compile unconditionally. add_executable(test_disk_task) @@ -18,13 +17,14 @@ target_sources(test_value_awaitable PRIVATE tests/test_value_awaitable.cpp) target_link_libraries(test_value_awaitable PRIVATE GTest::gtest GTest::gtest_main) add_test(NAME ValueAwaitable COMMAND test_value_awaitable) -if (TARGET stdexec) +find_package(stdexec QUIET) +if (TARGET stdexec::stdexec) add_executable(test_cqe_awaitable) target_sources(test_cqe_awaitable PRIVATE tests/test_cqe_awaitable.cpp ) target_link_libraries(test_cqe_awaitable PRIVATE - stdexec + stdexec::stdexec GTest::gtest GTest::gtest_main ) @@ -35,7 +35,7 @@ if (TARGET stdexec) tests/test_manual_scheduler.cpp ) target_link_libraries(test_manual_scheduler PRIVATE - stdexec + stdexec::stdexec GTest::gtest GTest::gtest_main )