diff --git a/.github/workflows/conan.yaml b/.github/workflows/conan.yaml new file mode 100644 index 0000000..12082d8 --- /dev/null +++ b/.github/workflows/conan.yaml @@ -0,0 +1,48 @@ +name: Conan +on: + workflow_dispatch: + pull_request: + push: + branches: [main] + +jobs: + conan-package: + runs-on: ubuntu-24.04 + + steps: + - name: Run sccache-cache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Conan Environment + uses: hankhsu1996/setup-conan@v1.1.0 + with: + cache-dependencies: true + cache-tool: true + + - name: Install conan dependencies + run: | + conan profile detect --force + conan install . --output-folder=build --build=missing -s:a compiler.cppstd=20 -o:a build_tests=True + + - name: CMake configuration + run: | + cmake --preset conan-release \ + -DSPARROW_IPC_BUILD_TESTS=ON \ + -DFETCH_DEPENDENCIES_WITH_CMAKE=MISSING \ + -DCMAKE_C_COMPILER_LAUNCHER=sccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + + - name: Build tests + working-directory: build/build/Release + run: cmake --build . --config Release --target test_sparrow_ipc_lib + + - name: Run tests + working-directory: build/build/Release + run: cmake --build . --config Release --target run_tests_with_junit_report + + - name: Run sccache stat for check + shell: bash + run: ${SCCACHE_PATH} --show-stats diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cd4ac1..3e44c46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,9 +99,15 @@ foreach(fbs_file IN LISTS FLATBUFFERS_SCHEMAS) list(APPEND FLATBUFFERS_GENERATED_HEADERS "${FLATBUFFERS_GENERATED_DIR}/${header_name}_generated.h") endforeach() +if(TARGET flatbuffers::flatc) + set(FLATC_EXECUTABLE flatbuffers::flatc) +else() + set(FLATC_EXECUTABLE flatc) +endif() + add_custom_command( OUTPUT ${FLATBUFFERS_GENERATED_HEADERS} - COMMAND flatc --cpp -o ${FLATBUFFERS_GENERATED_DIR} --cpp-std c++17 --scoped-enums ${FLATBUFFERS_SCHEMAS} + COMMAND ${FLATC_EXECUTABLE} --cpp -o ${FLATBUFFERS_GENERATED_DIR} --cpp-std c++17 --scoped-enums ${FLATBUFFERS_SCHEMAS} DEPENDS ${FLATBUFFERS_SCHEMAS} COMMENT "Generating FlatBuffers C++ headers from schemas" ) diff --git a/cmake/external_dependencies.cmake b/cmake/external_dependencies.cmake index 742a3c9..e1ff392 100644 --- a/cmake/external_dependencies.cmake +++ b/cmake/external_dependencies.cmake @@ -11,16 +11,23 @@ endif() function(find_package_or_fetch) set(options) - set(oneValueArgs PACKAGE_NAME VERSION GIT_REPOSITORY TAG) + set(oneValueArgs CONAN_PKG_NAME PACKAGE_NAME VERSION GIT_REPOSITORY TAG) set(multiValueArgs) cmake_parse_arguments(PARSE_ARGV 0 arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ) + + set(actual_pkg_name ${arg_PACKAGE_NAME}) + if(arg_CONAN_PKG_NAME) + set(actual_pkg_name ${arg_CONAN_PKG_NAME}) + endif() + if(NOT FETCH_DEPENDENCIES_WITH_CMAKE STREQUAL "ON") - find_package(${arg_PACKAGE_NAME} ${FIND_PACKAGE_OPTIONS}) + find_package(${actual_pkg_name} ${FIND_PACKAGE_OPTIONS}) endif() + if(FETCH_DEPENDENCIES_WITH_CMAKE STREQUAL "ON" OR FETCH_DEPENDENCIES_WITH_CMAKE STREQUAL "MISSING") - if(NOT ${arg_PACKAGE_NAME}_FOUND) + if(NOT ${actual_pkg_name}_FOUND) message(STATUS "📦 Fetching ${arg_PACKAGE_NAME}") FetchContent_Declare( ${arg_PACKAGE_NAME} @@ -33,7 +40,7 @@ function(find_package_or_fetch) FetchContent_MakeAvailable(${arg_PACKAGE_NAME}) message(STATUS "\t✅ Fetched ${arg_PACKAGE_NAME}") else() - message(STATUS "📦 ${arg_PACKAGE_NAME} found here: ${arg_PACKAGE_NAME}_DIR") + message(STATUS "📦 ${actual_pkg_name} found here: ${actual_pkg_name}_DIR") endif() endif() endfunction() @@ -53,6 +60,7 @@ endif() set(FLATBUFFERS_BUILD_TESTS OFF) set(FLATBUFFERS_BUILD_SHAREDLIB ${SPARROW_IPC_BUILD_SHARED}) find_package_or_fetch( + CONAN_PKG_NAME flatbuffers PACKAGE_NAME FlatBuffers VERSION v25.2.10 GIT_REPOSITORY https://github.com/google/flatbuffers.git @@ -71,4 +79,4 @@ if(SPARROW_IPC_BUILD_TESTS) GIT_REPOSITORY https://github.com/doctest/doctest.git TAG v2.4.12 ) -endif() \ No newline at end of file +endif() diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..17336f7 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,104 @@ +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.build.cppstd import check_min_cppstd +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +from conan.tools.files import copy +from conan.tools.scm import Version +import os + +required_conan_version = ">=2.0" + +class SparrowIPCRecipe(ConanFile): + name = "sparrow-ipc" + description = "C++20 library for memory-mapped serialization of Apache Arrow data." + license = "BSD-3-Clause" + author = "QuantStack" + url = "https://github.com/QuantStack/sparrow-ipc" + homepage = "https://github.com/QuantStack/sparrow-ipc" + topics = ("arrow", "apache arrow", "columnar format", "dataframe", "ipc", "serialization", "deserialization", "flatbuffers") + package_type = "library" + settings = "os", "arch", "compiler", "build_type" + exports_sources = "include/*", "src/*", "cmake/*", "CMakeLists.txt", "LICENSE" + options = { + "shared": [True, False], + "fPIC": [True, False], + "build_tests": [True, False], + } + default_options = { + "shared": False, + "fPIC": True, + "build_tests": False, + } + + _flatbuffers_version = "24.12.23" + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def configure(self): + if self.options.shared: + self.options.rm_safe("fPIC") + + def requirements(self): + self.requires("sparrow/1.0.0") + self.requires(f"flatbuffers/{self._flatbuffers_version}") + if self.options.get_safe("build_tests"): + self.test_requires("doctest/2.4.12") + + def build_requirements(self): + self.tool_requires("cmake/[>=3.28.1 <4.2.0]") + self.tool_requires(f"flatbuffers/{self._flatbuffers_version}") + + @property + def _min_cppstd(self): + return 20 + + @property + def _compilers_minimum_version(self): + return { + "apple-clang": "16", + "clang": "18", + "gcc": "12", + "msvc": "194" + } + + def validate(self): + if self.settings.compiler.get_safe("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 layout(self): + cmake_layout(self, src_folder=".") + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + + tc = CMakeToolchain(self) + tc.variables["SPARROW_IPC_BUILD_SHARED"] = self.options.shared + tc.variables["SPARROW_IPC_BUILD_TESTS"] = self.options.build_tests + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + copy(self, "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 = ["sparrow-ipc"] + self.cpp_info.set_property("cmake_file_name", "sparrow-ipc") + self.cpp_info.set_property("cmake_target_name", "sparrow-ipc::sparrow-ipc")