diff --git a/recipes/fibertaskinglib/all/conandata.yml b/recipes/fibertaskinglib/all/conandata.yml new file mode 100644 index 0000000000000..fc89f76dc1d26 --- /dev/null +++ b/recipes/fibertaskinglib/all/conandata.yml @@ -0,0 +1,12 @@ +sources: + "2.0.4": + url: "https://github.com/RichieSams/FiberTaskingLib/archive/refs/tags/v2.0.4.tar.gz" + sha256: "680a82c0c74d221ddf15e662f842ac72a6be7ea0e3695f7093afe57162f14f9e" +patches: + "2.0.4": + - patch_file: "patches/2.0.4-0001-remove-prefix.patch" + patch_description: "use cci's package" + patch_type: "conan" + - patch_file: "patches/2.0.4-0002-add-installer.patch" + patch_description: "add installer" + patch_type: "portability" diff --git a/recipes/fibertaskinglib/all/conanfile.py b/recipes/fibertaskinglib/all/conanfile.py new file mode 100644 index 0000000000000..730cca9fdea20 --- /dev/null +++ b/recipes/fibertaskinglib/all/conanfile.py @@ -0,0 +1,95 @@ +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.files import apply_conandata_patches, export_conandata_patches, get, copy +from conan.tools.build import check_min_cppstd +from conan.tools.scm import Version +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +from conan.tools.env import VirtualBuildEnv +import os + + +required_conan_version = ">=1.53.0" + + +class FiberTaskingLibConan(ConanFile): + name = "fibertaskinglib" + description = "enabling task-based multi-threading. It allows execution of task graphs with arbitrary dependencies." + license = "Apache-2.0" + url = "https://github.com/conan-io/conan-center-index" + homepage = "https://github.com/RichieSams/FiberTaskingLib" + topics = ("coroutine", "fiber", "task-scheduler") + package_type = "static-library" + settings = "os", "arch", "compiler", "build_type" + options = { + "with_cpp17": [True, False], + } + default_options = { + "with_cpp17": False, + } + + @property + def _min_cppstd(self): + return "17" if self.options.with_cpp17 else "11" + + @property + def _compilers_minimum_version(self): + return { + "17": { + "gcc": "8", + "clang": "7", + "apple-clang": "12", + "Visual Studio": "16", + "msvc": "192", + }, + }.get(self._min_cppstd, {}) + + def export_sources(self): + export_conandata_patches(self) + + def layout(self): + cmake_layout(self, src_folder="src") + + def validate(self): + if self.settings.compiler.cppstd: + check_min_cppstd(self, self._min_cppstd) + minimum_version = self._compilers_minimum_version.get(str(self.settings.compiler), False) + if minimum_version and Version(self.settings.compiler.version) < minimum_version: + raise ConanInvalidConfiguration( + f"{self.ref} requires C++{self._min_cppstd}, which your compiler does not support." + ) + + def build_requirements(self): + self.tool_requires("cmake/[>=3.25 <4]") + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def generate(self): + tc = CMakeToolchain(self) + tc.variables["FTL_BUILD_TESTS"] = False + tc.variables["FTL_BUILD_BENCHMARKS"] = False + tc.variables["FTL_BUILD_EXAMPLES"] = False + tc.variables["FTL_CPP_17"] = self.options.with_cpp17 + tc.generate() + venv = VirtualBuildEnv(self) + venv.generate(scope="build") + + def build(self): + apply_conandata_patches(self) + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + copy(self, pattern="LICENSE", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder) + cmake = CMake(self) + cmake.install() + + def package_info(self): + self.cpp_info.libs = ["ftl", "boost_context"] + + self.cpp_info.set_property("cmake_file_name", "FiberTaskingLib") + self.cpp_info.set_property("cmake_target_name", "FiberTaskingLib::FiberTaskingLib") + + if self.settings.os in ["Linux", "FreeBSD"]: + self.cpp_info.system_libs.append("pthread") diff --git a/recipes/fibertaskinglib/all/patches/2.0.4-0001-remove-prefix.patch b/recipes/fibertaskinglib/all/patches/2.0.4-0001-remove-prefix.patch new file mode 100644 index 0000000000000..eb7fb5456412b --- /dev/null +++ b/recipes/fibertaskinglib/all/patches/2.0.4-0001-remove-prefix.patch @@ -0,0 +1,13 @@ +diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt +index 992e1b8..5e885e3 100644 +--- a/source/CMakeLists.txt ++++ b/source/CMakeLists.txt +@@ -91,7 +91,7 @@ target_include_directories(ftl PUBLIC ../include) + target_link_libraries(ftl boost_context ${CMAKE_THREAD_LIBS_INIT}) + + # Remove the prefix +-set_target_properties(ftl PROPERTIES PREFIX "") ++# set_target_properties(ftl PROPERTIES PREFIX "") + + # Set the c++ std + if (FTL_CPP_17) diff --git a/recipes/fibertaskinglib/all/patches/2.0.4-0002-add-installer.patch b/recipes/fibertaskinglib/all/patches/2.0.4-0002-add-installer.patch new file mode 100644 index 0000000000000..e29030135b09a --- /dev/null +++ b/recipes/fibertaskinglib/all/patches/2.0.4-0002-add-installer.patch @@ -0,0 +1,37 @@ +diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt +index 5e885e3..a41e5c1 100644 +--- a/source/CMakeLists.txt ++++ b/source/CMakeLists.txt +@@ -103,3 +103,13 @@ endif() + + # Set the warnings + AddCompilerFlags(ftl) ++ ++include(GNUInstallDirs) ++ ++install( ++ TARGETS ftl ++ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ++) ++install(DIRECTORY "../include/ftl" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") +diff --git a/third_party/boost_context/CMakeLists.txt b/third_party/boost_context/CMakeLists.txt +index 84a9c72..16f9a7b 100644 +--- a/third_party/boost_context/CMakeLists.txt ++++ b/third_party/boost_context/CMakeLists.txt +@@ -107,3 +107,14 @@ endif() + + add_library(boost_context STATIC ${BOOST_CONTEXT_SRC}) + target_include_directories(boost_context INTERFACE include) ++ ++include(GNUInstallDirs) ++ ++install( ++ TARGETS boost_context ++ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ++) ++install(DIRECTORY "include/boost_context" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") ++ diff --git a/recipes/fibertaskinglib/all/test_package/CMakeLists.txt b/recipes/fibertaskinglib/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000000..e9ff650bd19cb --- /dev/null +++ b/recipes/fibertaskinglib/all/test_package/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.15) +project(test_package LANGUAGES CXX) + +find_package(FiberTaskingLib REQUIRED CONFIG) + +add_executable(${PROJECT_NAME} test_package.cpp) +target_link_libraries(${PROJECT_NAME} PRIVATE FiberTaskingLib::FiberTaskingLib) +if(FTL_CPP_17) + target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) +else() + target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) +endif() diff --git a/recipes/fibertaskinglib/all/test_package/conanfile.py b/recipes/fibertaskinglib/all/test_package/conanfile.py new file mode 100644 index 0000000000000..8e7e4bdd461f2 --- /dev/null +++ b/recipes/fibertaskinglib/all/test_package/conanfile.py @@ -0,0 +1,34 @@ +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import cmake_layout, CMake +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +import os + + +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "VirtualRunEnv" + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) + + def generate(self): + tc = CMakeToolchain(self) + tc.variables["FTL_CPP_17"] = self.dependencies["fibertaskinglib"].options.with_cpp17 + tc.generate() + deps = CMakeDeps(self) + deps.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if can_run(self): + bin_path = os.path.join(self.cpp.build.bindir, "test_package") + self.run(bin_path, env="conanrun") diff --git a/recipes/fibertaskinglib/all/test_package/test_package.cpp b/recipes/fibertaskinglib/all/test_package/test_package.cpp new file mode 100644 index 0000000000000..c5c6ef86421e0 --- /dev/null +++ b/recipes/fibertaskinglib/all/test_package/test_package.cpp @@ -0,0 +1,95 @@ +#include "ftl/task_scheduler.h" +#include "ftl/wait_group.h" + +#include +#include + +struct NumberSubset { + uint64_t start; + uint64_t end; + + uint64_t total; +}; + +void AddNumberSubset(ftl::TaskScheduler *taskScheduler, void *arg) { + (void)taskScheduler; + NumberSubset *subset = reinterpret_cast(arg); + + subset->total = 0; + + while (subset->start != subset->end) { + subset->total += subset->start; + ++subset->start; + } + + subset->total += subset->end; +} + +/** + * Calculates the value of a triangle number by dividing the additions up into tasks + * + * A triangle number is defined as: + * Tn = 1 + 2 + 3 + ... + n + * + * The code is checked against the numerical solution which is: + * Tn = n * (n + 1) / 2 + */ +int main() { + // Create the task scheduler and bind the main thread to it + ftl::TaskScheduler taskScheduler; + taskScheduler.Init(); + + // Define the constants to test + constexpr uint64_t triangleNum = 47593243ULL; + constexpr uint64_t numAdditionsPerTask = 10000ULL; + constexpr uint64_t numTasks = (triangleNum + numAdditionsPerTask - 1ULL) / numAdditionsPerTask; + + // Create the tasks + // FTL allows you to create Tasks on the stack. + // However, in this case, that would cause a stack overflow + ftl::Task *tasks = new ftl::Task[numTasks]; + NumberSubset *subsets = new NumberSubset[numTasks]; + uint64_t nextNumber = 1ULL; + + for (uint64_t i = 0ULL; i < numTasks; ++i) { + NumberSubset *subset = &subsets[i]; + + subset->start = nextNumber; + subset->end = nextNumber + numAdditionsPerTask - 1ULL; + if (subset->end > triangleNum) { + subset->end = triangleNum; + } + + tasks[i] = { AddNumberSubset, subset }; + + nextNumber = subset->end + 1; + } + + // Schedule the tasks + ftl::WaitGroup wg(&taskScheduler); + taskScheduler.AddTasks(numTasks, tasks, ftl::TaskPriority::Normal, &wg); + + // FTL creates its own copies of the tasks, so we can safely delete the memory + delete[] tasks; + + // Wait for the tasks to complete + wg.Wait(); + + // Add the results + uint64_t result = 0ULL; + for (uint64_t i = 0; i < numTasks; ++i) { + result += subsets[i].total; + } + + // Test + assert(triangleNum * (triangleNum + 1ULL) / 2ULL == result); + (void)result; + + // Cleanup + delete[] subsets; + + // The destructor of TaskScheduler will shut down all the worker threads + // and unbind the main thread + + return 0; +} diff --git a/recipes/fibertaskinglib/config.yml b/recipes/fibertaskinglib/config.yml new file mode 100644 index 0000000000000..1f2301f1f0282 --- /dev/null +++ b/recipes/fibertaskinglib/config.yml @@ -0,0 +1,3 @@ +versions: + "2.0.4": + folder: all