From cc58eae1dfba6154a98f04c0166742e2f672a2d9 Mon Sep 17 00:00:00 2001 From: Brian Szmyd Date: Tue, 2 Jun 2026 13:16:56 -0600 Subject: [PATCH 1/2] sisl: ship stdexec as a real conan dependency (3rd_party recipe) sisl/async/task.hpp and when_all.hpp are public, installed headers that FetchContent. So consumers of the sisl package -- and everything downstream (nuraft_mesg and its test_package) -- could not find exec/task.hpp. Add a header-only conan recipe for stdexec pinned to commit ea0d8788 (release nvhpc-25.09, the exact revision the in-tree FetchContent blocks use, so the headers are byte-identical), export it from prepare_v2.sh, and require it with transitive_headers=True so it flows to all consumers. The recipe also propagates -D_PSTL_PAR_BACKEND_SERIAL (keeps off the TBB PSTL backend) and -Wno-empty-body/-Wno-subobject-linkage, matching the in-tree stdexec_iface targets. Verified: conan create builds the settings-independent header package (sha256 matched); generated CMakeDeps for a consumer carry the include dir, the PSTL define, and the warning flags; the sisl->stdexec edge resolves with headers=True/transitive_headers=True. --- 3rd_party/stdexec/conandata.yml | 7 +++++ 3rd_party/stdexec/conanfile.py | 48 +++++++++++++++++++++++++++++++++ conanfile.py | 9 +++++-- prepare_v2.sh | 2 ++ src/async/CMakeLists.txt | 14 +++++----- 5 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 3rd_party/stdexec/conandata.yml create mode 100644 3rd_party/stdexec/conanfile.py 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..9ff28069 --- /dev/null +++ b/3rd_party/stdexec/conanfile.py @@ -0,0 +1,48 @@ +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"] + if str(self.settings.compiler) in ("gcc", "clang"): + # stdexec internals legitimately trip these; suppress so -Werror consumers still build. + self.cpp_info.cxxflags = ["-Wno-empty-body", "-Wno-subobject-linkage"] diff --git a/conanfile.py b/conanfile.py index f11cae9e..bcdb08dc 100644 --- a/conanfile.py +++ b/conanfile.py @@ -9,7 +9,7 @@ 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" @@ -83,6 +83,9 @@ 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++": self.requires("breakpad/cci.20210521") @@ -251,7 +254,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 ) From 74fb2d53414014d47f2fbd08c06dcba860fe7c2b Mon Sep 17 00:00:00 2001 From: Brian Szmyd Date: Tue, 2 Jun 2026 13:45:14 -0600 Subject: [PATCH 2/2] sisl: fix stdexec clang flags + gate breakpad for gcc >= 16 - stdexec recipe: -Wno-subobject-linkage is gcc-only; clang rejects it as an unknown warning option (fatal under -Werror). Apply it for gcc only; clang gets just -Wno-empty-body. Both still get -D_PSTL_PAR_BACKEND_SERIAL. - conanfile: gate the breakpad/cci.20210521 requirement behind a _use_breakpad() helper that excludes gcc >= 16 (the 2021 recipe doesn't build there); other Linux/libstdc++ toolchains keep it. --- 3rd_party/stdexec/conanfile.py | 8 ++++++-- conanfile.py | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/3rd_party/stdexec/conanfile.py b/3rd_party/stdexec/conanfile.py index 9ff28069..24af24b8 100644 --- a/3rd_party/stdexec/conanfile.py +++ b/3rd_party/stdexec/conanfile.py @@ -43,6 +43,10 @@ def package_info(self): # 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"] - if str(self.settings.compiler) in ("gcc", "clang"): - # stdexec internals legitimately trip these; suppress so -Werror consumers still build. + # 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 bcdb08dc..33e1e2ea 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,6 +3,7 @@ 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" @@ -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()) @@ -87,7 +97,7 @@ def requirements(self): # 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 @@ -240,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",