From 17b17a5b158341cf11b06d9f9daba2447ef6575a Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 8 Oct 2026 11:35:00 -0400 Subject: [PATCH 1/2] Add vcpkg and Conan packaging; bump version to 0.1.1 Fetch GoogleTest only when BEMAN_BIG_INT_BUILD_TESTS is on and keep it out of the install, so a package build needs no network access (vcpkg builds with FETCHCONTENT_FULLY_DISCONNECTED) and installs only beman.big_int. vcpkg: port templates under port/ (beman-big-int, static library, features modules and simd-mul), a developer vcpkg.json and vcpkg-configuration.json, a release workflow that publishes the port to the Beman vcpkg registry, and a vcpkg-ci job using the Beman reusable workflow. Conan: a Conan 2 recipe (conanfile.py, option simd_mul) with a test_package, and a CI job running conan create on Linux, macOS and Windows. Document both under "Package managers" in Build and Usage. --- .github/workflows/ci_tests.yml | 38 +++++++- .github/workflows/vcpkg-release.yml | 18 ++++ .gitignore | 4 + CMakeLists.txt | 25 ++--- README.md | 5 + conanfile.py | 99 ++++++++++++++++++++ docs/modules/ROOT/pages/build_and_usage.adoc | 66 +++++++++++++ port/portfile.cmake.in | 48 ++++++++++ port/vcpkg.json.in | 25 +++++ test_package/CMakeLists.txt | 12 +++ test_package/conanfile.py | 30 ++++++ test_package/test_package.cpp | 24 +++++ vcpkg-configuration.json | 15 +++ vcpkg.json | 5 + 14 files changed, 402 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/vcpkg-release.yml create mode 100644 conanfile.py create mode 100644 port/portfile.cmake.in create mode 100644 port/vcpkg.json.in create mode 100644 test_package/CMakeLists.txt create mode 100644 test_package/conanfile.py create mode 100644 test_package/test_package.cpp create mode 100644 vcpkg-configuration.json create mode 100644 vcpkg.json diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 6a76ced4..fdfd05fb 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -209,7 +209,43 @@ jobs: - run: cmake --build build/msvc-release - run: ctest --preset msvc-release -j4 + # Renders port/*.in against this checkout and installs it as an overlay port + # for each feature combination, then builds the repository with the vcpkg + # toolchain and the root vcpkg.json. + vcpkg-ci: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-vcpkg-ci.yml@1.7.4 + with: + port_name: beman-big-int + feature_combinations: | + [ + {"features": {}}, + {"features": {"modules": true}}, + {"features": {"simd-mul": true}} + ] + + # Builds the Conan package from conanfile.py and runs test_package against it. + conan: + strategy: + fail-fast: false + matrix: + runner: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.runner }} + name: "Conan: ${{ matrix.runner }}" + steps: + - uses: actions/checkout@v6 + - uses: lukka/get-cmake@latest + with: + cmakeVersion: 4.3.3 + # The runner's default GCC 13 is older than the supported minimum. + - if: runner.os == 'Linux' + run: | + echo "CC=gcc-14" >> "$GITHUB_ENV" + echo "CXX=g++-14" >> "$GITHUB_ENV" + - run: pipx install conan + - run: conan profile detect + - run: conan create . -s compiler.cppstd=23 --build=missing + create-issue-when-fault: - needs: [preset-test, build-and-test, msvc-arm64, ifma-sde-linux, ifma-sde-windows] + needs: [preset-test, build-and-test, msvc-arm64, ifma-sde-linux, ifma-sde-windows, vcpkg-ci, conan] if: failure() && github.event_name == 'schedule' uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-create-issue-when-fault.yml@1.7.4 diff --git a/.github/workflows/vcpkg-release.yml b/.github/workflows/vcpkg-release.yml new file mode 100644 index 00000000..639096df --- /dev/null +++ b/.github/workflows/vcpkg-release.yml @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-License-Identifier: BSL-1.0 + +# On each published GitHub release, renders port/*.in with the tag's version and +# tarball SHA512 and pushes the port to the Beman vcpkg registry. +name: vcpkg registry release + +on: + release: + types: [published] + +jobs: + vcpkg-release: + uses: bemanproject/infra-workflows/.github/workflows/reusable-beman-vcpkg-release.yml@1.7.4 + with: + port_name: beman-big-int + secrets: + VCPKG_REGISTRY_TOKEN: ${{ secrets.VCPKG_REGISTRY_TOKEN }} diff --git a/.gitignore b/.gitignore index a4e399f9..4a1061ed 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,10 @@ /compile_commands.json /build +# Conan writes these when it builds test_package (conan create / conan test). +/test_package/build +/test_package/CMakeUserPresets.json + # CMake generates this from detail/config_generated.hpp.in (which is tracked); # ignored anywhere, e.g. an in-source build's generated/include. config_generated.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d05f70e6..66ddceb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,19 +11,9 @@ project( beman.big_int DESCRIPTION "Reference implementation of std::big_int" LANGUAGES CXX - VERSION 0.1.0 + VERSION 0.1.1 ) -include(FetchContent) -FetchContent_Declare( - googletest - URL - https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip -) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(googletest) - # [CMAKE.SKIP_TESTS] option( BEMAN_BIG_INT_BUILD_TESTS @@ -613,6 +603,19 @@ endif() beman_install_library(beman.big_int TARGETS ${BEMAN_BIG_INT_INSTALL_TARGETS}) if(BEMAN_BIG_INT_BUILD_TESTS) + # Fetched only for the tests, so a package build (vcpkg, Conan) needs no + # network access, and kept out of this project's install. + include(FetchContent) + FetchContent_Declare( + googletest + URL + https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip + ) + # For Windows: Prevent overriding the parent project's compiler/linker settings + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(googletest) + enable_testing() add_subdirectory(tests/beman/big_int) diff --git a/README.md b/README.md index 3e35f1ed..5cef9e2f 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,11 @@ SIMD-accelerated multiplication, installation, CMake integration, and basic usage, see the [Build and Usage](https://bemanproject.github.io/big_int/build_and_usage.html) documentation. +`beman.big_int` is also packaged for vcpkg, as the port `beman-big-int` in the +[Beman vcpkg registry](https://github.com/bemanproject/vcpkg-registry), and for +Conan, through the [`conanfile.py`](conanfile.py) recipe at the repository root. +See [Package managers](https://bemanproject.github.io/big_int/build_and_usage.html#build_and_usage_package_managers). + ## Development See the [Contributing Guidelines](CONTRIBUTING.md). diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 00000000..5ee3d81d --- /dev/null +++ b/conanfile.py @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-License-Identifier: BSL-1.0 + +import os +import re + +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.build import check_min_cppstd +from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout +from conan.tools.files import copy, load, rmdir +from conan.tools.scm import Version + +required_conan_version = ">=2.0" + + +class BemanBigIntConan(ConanFile): + name = "beman-big-int" + description = "Reference implementation of std::big_int, the arbitrary-precision integer proposed for C++29" + license = ("Apache-2.0 WITH LLVM-exception", "BSL-1.0") + url = "https://github.com/bemanproject/big_int" + homepage = "https://github.com/bemanproject/big_int" + topics = ("beman", "big-int", "bignum", "arbitrary-precision", "multiprecision") + # The multiplication and division kernels are compiled, and the library + # exports no DLL interface, so it is only ever a static library. + package_type = "static-library" + settings = "os", "arch", "compiler", "build_type" + options = { + "fPIC": [True, False], + "simd_mul": [True, False], + } + default_options = { + "fPIC": True, + "simd_mul": False, + } + exports_sources = ( + "CMakeLists.txt", + "LICENSE", + "LICENSE-BOOST", + "include/*", + "src/*", + "infra/cmake/*", + "extra/big_int.natvis", + ) + + @property + def _min_compiler_versions(self): + # The tested platforms in docs/modules/ROOT/pages/build_and_usage.adoc. + return { + "gcc": "14", + "clang": "19", + "apple-clang": "17", + "msvc": "194", + } + + def set_version(self): + # The single source of truth is project(VERSION) in CMakeLists.txt. + cmakelists = load(self, os.path.join(self.recipe_folder, "CMakeLists.txt")) + self.version = self.version or re.search(r"project\([^)]*VERSION\s+([0-9.]+)", cmakelists).group(1) + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def layout(self): + cmake_layout(self, src_folder=".") + + def validate(self): + check_min_cppstd(self, 23) + minimum = self._min_compiler_versions.get(str(self.settings.compiler)) + if minimum and Version(self.settings.compiler.version) < minimum: + raise ConanInvalidConfiguration( + f"{self.ref} requires {self.settings.compiler} {minimum} or later" + ) + + def generate(self): + tc = CMakeToolchain(self) + tc.cache_variables["BEMAN_BIG_INT_BUILD_TESTS"] = False + tc.cache_variables["BEMAN_BIG_INT_BUILD_EXAMPLES"] = False + tc.cache_variables["BEMAN_BIG_INT_BUILD_BENCHMARKS"] = False + tc.cache_variables["BEMAN_BIG_INT_SIMD_MUL"] = bool(self.options.simd_mul) + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + copy(self, "LICENSE*", self.source_folder, os.path.join(self.package_folder, "licenses")) + cmake = CMake(self) + cmake.install() + # CMakeDeps generates the config files from package_info() instead. + rmdir(self, os.path.join(self.package_folder, "lib", "cmake")) + + def package_info(self): + self.cpp_info.set_property("cmake_file_name", "beman.big_int") + self.cpp_info.set_property("cmake_target_name", "beman::big_int") + self.cpp_info.libs = ["beman.big_int"] diff --git a/docs/modules/ROOT/pages/build_and_usage.adoc b/docs/modules/ROOT/pages/build_and_usage.adoc index 65b4701d..92b3f846 100644 --- a/docs/modules/ROOT/pages/build_and_usage.adoc +++ b/docs/modules/ROOT/pages/build_and_usage.adoc @@ -288,6 +288,72 @@ This will generate the following directory structure: \-- beman.big_int-targets.cmake ---- +[#build_and_usage_package_managers] +== Package managers + +Both packages build the library as a static library, with tests, examples and +benchmarks off, and define the same `beman::big_int` CMake target as an installed +build (see xref:#build_and_usage_cmake[CMake configuration]). The x86-64 kernel +options stay at `AUTO`, so the BMI2/ADX and AVX-512 IFMA kernels are selected only +when the package manager's compiler flags target them (for example `-march=native` +in a vcpkg triplet's `VCPKG_CXX_FLAGS` or a Conan profile's +`tools.build:cxxflags`). + +[#build_and_usage_vcpkg] +=== vcpkg + +`beman.big_int` is published to the Beman project's +https://github.com/bemanproject/vcpkg-registry[vcpkg registry] as the port +`beman-big-int`. Add that registry to your project's `vcpkg-configuration.json` +(this repository's own +https://github.com/bemanproject/big_int/blob/main/vcpkg-configuration.json[`vcpkg-configuration.json`] +shows how), then depend on the port in your `vcpkg.json`: + +[source,json] +---- +{ + "dependencies": [ "beman-big-int" ] +} +---- + +The port has two optional features: + +* `simd-mul` builds with `BEMAN_BIG_INT_SIMD_MUL` (see + xref:#build_and_usage_simd[SIMD-accelerated multiplication]). +* `modules` also builds and installs the named module and its + `beman::big_int_module` target (see + xref:#build_and_usage_modules[the pass:[C++] named module]); it is not + available with AppleClang. + +[#build_and_usage_conan] +=== Conan + +The repository root holds a Conan 2 recipe, `conanfile.py`, and its +`test_package`. To build the package into your local Conan cache from a +checkout: + +[source,bash] +---- +conan create . -s compiler.cppstd=23 --build=missing +---- + +Then require it from your own recipe or `conanfile.txt` and use the `CMakeDeps` +generator: + +[source] +---- +[requires] +beman-big-int/0.1.1 + +[generators] +CMakeDeps +CMakeToolchain +---- + +The recipe needs `compiler.cppstd` to be 23 or later and offers the option +`simd_mul` (default `False`), which builds with `BEMAN_BIG_INT_SIMD_MUL`. The +named module is not packaged for Conan. + [#build_and_usage_cmake] == CMake configuration diff --git a/port/portfile.cmake.in b/port/portfile.cmake.in new file mode 100644 index 00000000..850c364d --- /dev/null +++ b/port/portfile.cmake.in @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-License-Identifier: BSL-1.0 + +# Rendered into the Beman vcpkg registry on each release by +# .github/workflows/vcpkg-release.yml, which fills in the version and SHA512 of +# the tagged release. +# The multiplication and division kernels are compiled, and the library exports +# no DLL interface, so it is built as a static library on every triplet. +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO bemanproject/big_int + REF "v@VERSION@" + SHA512 @SHA512@ + HEAD_REF main +) + +vcpkg_check_features( + OUT_FEATURE_OPTIONS FEATURE_OPTIONS + FEATURES + modules BEMAN_BIG_INT_BUILD_MODULE + simd-mul BEMAN_BIG_INT_SIMD_MUL +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + ${FEATURE_OPTIONS} + -DBEMAN_BIG_INT_BUILD_TESTS=OFF + -DBEMAN_BIG_INT_BUILD_EXAMPLES=OFF + -DBEMAN_BIG_INT_BUILD_BENCHMARKS=OFF +) + +vcpkg_cmake_install() + +vcpkg_cmake_config_fixup( + PACKAGE_NAME beman.big_int + CONFIG_PATH lib/cmake/beman.big_int +) + +file( + REMOVE_RECURSE + "${CURRENT_PACKAGES_DIR}/debug/include" + "${CURRENT_PACKAGES_DIR}/debug/share" +) + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE" "${SOURCE_PATH}/LICENSE-BOOST") diff --git a/port/vcpkg.json.in b/port/vcpkg.json.in new file mode 100644 index 00000000..0785b8d0 --- /dev/null +++ b/port/vcpkg.json.in @@ -0,0 +1,25 @@ +{ + "name": "beman-big-int", + "version-semver": "@VERSION@", + "description": "Reference implementation of std::big_int, the arbitrary-precision integer proposed for C++29", + "homepage": "https://github.com/bemanproject/big_int", + "license": "Apache-2.0 WITH LLVM-exception OR BSL-1.0", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ], + "features": { + "modules": { + "description": "Also build and install the beman.big_int C++ named module (beman::big_int_module); not supported by AppleClang" + }, + "simd-mul": { + "description": "Use the double-precision FP NTT with NEON/AVX2 kernels for FFT-sized multiplication (BEMAN_BIG_INT_SIMD_MUL)" + } + } +} diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt new file mode 100644 index 00000000..5f759258 --- /dev/null +++ b/test_package/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-License-Identifier: BSL-1.0 + +cmake_minimum_required(VERSION 3.30...4.3) + +project(test_package LANGUAGES CXX) + +find_package(beman.big_int REQUIRED CONFIG) + +add_executable(test_package test_package.cpp) +target_link_libraries(test_package PRIVATE beman::big_int) +target_compile_features(test_package PRIVATE cxx_std_23) diff --git a/test_package/conanfile.py b/test_package/conanfile.py new file mode 100644 index 00000000..2bc14973 --- /dev/null +++ b/test_package/conanfile.py @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# SPDX-License-Identifier: BSL-1.0 + +import os + +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import CMake, cmake_layout + + +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "CMakeDeps", "CMakeToolchain" + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) + + 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/test_package/test_package.cpp b/test_package/test_package.cpp new file mode 100644 index 00000000..d764811b --- /dev/null +++ b/test_package/test_package.cpp @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// SPDX-License-Identifier: BSL-1.0 + +#include + +#include + +// 3^4000 is about 100 limbs, so its square and the division below go through +// the compiled multiplication and division kernels, not just the headers. +auto main() -> int { + using beman::big_int::big_int; + + big_int a{1}; + for (int i{0}; i < 4000; ++i) { + a *= 3; + } + + const big_int square{a * a}; + const auto digits{to_string(square).size()}; + + std::cout << "beman.big_int: 3^8000 has " << digits << " decimal digits\n"; + + return (digits == 3817 && square / a == a && square % a == 0) ? 0 : 1; +} diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 00000000..106b0bee --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,15 @@ +{ + "default-registry": { + "kind": "git", + "repository": "https://github.com/microsoft/vcpkg.git", + "baseline": "9e593bb18ea69cc5095e012465dcd675a822ed0d" + }, + "registries": [ + { + "kind": "git", + "repository": "https://github.com/bemanproject/vcpkg-registry.git", + "baseline": "c17ef23da258b64ce26bdebb33239c6ff826f4c8", + "packages": ["beman-*"] + } + ] +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 00000000..5ea1ed95 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,5 @@ +{ + "$comment": "Developer manifest. The library has no dependencies; the tests fetch GoogleTest and Boost.Multiprecision with FetchContent. The released port is rendered from port/.", + "name": "beman-big-int", + "version-semver": "0.1.1" +} From d6922436c30487cf8255ab0ae4c45f2777928ede Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 8 Oct 2026 12:01:05 -0400 Subject: [PATCH 2/2] Replace FetchContent with beman infra --- .github/copilot-instructions.md | 8 +++-- .github/workflows/fuzz.yml | 1 + CMakeLists.txt | 17 +++-------- CONTRIBUTING.md | 5 +-- docs/modules/ROOT/pages/benchmarks.adoc | 7 +++-- docs/modules/ROOT/pages/build_and_usage.adoc | 9 +++++- lockfile.json | 24 +++++++++++++-- tests/beman/big_int/CMakeLists.txt | 23 +++++--------- tests/beman/big_int/perf/CMakeLists.txt | 32 ++++++-------------- vcpkg.json | 16 ++++++++-- 10 files changed, 80 insertions(+), 62 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b12e2086..8b6c8e64 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -11,8 +11,10 @@ and only search the repo when information here is incomplete or has become incor - Type: CMake-based C++ library with tests and examples. - Main language: C++23 (supports C++23/C++26 in CI matrix). - Build system: CMake presets + Ninja. -- Test framework: GoogleTest via CMake `FetchContent`. -- Additional test dependency: Boost.Multiprecision (fetched in test CMake). +- Test framework: GoogleTest via `find_package(GTest)`. +- Additional test dependency: Boost.Multiprecision via `find_package(boost_multiprecision)`. +- Dependencies come from the environment, or from `lockfile.json` through + `-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./infra/cmake/use-fetch-content.cmake` (set by the presets). - Lint/format: pre-commit hooks (`clang-format`, `gersemi`, `codespell`, YAML/whitespace checks). - CI: GitHub Actions workflows in `.github/workflows/`, mostly through reusable workflows from `bemanproject/infra-workflows`. @@ -83,7 +85,7 @@ Validated result: all hooks passed (`clang-format`, `gersemi`, `codespell`, whit - Observed: `cmake --workflow --preset gcc-release` timed out at 1 second tool timeout. - Mitigation: for workflow builds/tests, use >=120s timeout in constrained runners; ~10-11s was observed for full configure/build/test in this environment. -- `FetchContent` emits deprecation warnings from vendored googletest CMake minimum versions. +- The googletest pinned in `lockfile.json` emits CMake deprecation warnings for its old minimum version. - Observed during configure; not fatal. - Mitigation: treat as upstream dependency warning unless CI policy changes. diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 308b2414..83898906 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -41,6 +41,7 @@ jobs: -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./infra/cmake/use-fetch-content.cmake \ -DBEMAN_BIG_INT_BUILD_TESTS=ON \ -DBEMAN_BIG_INT_FUZZ=ON diff --git a/CMakeLists.txt b/CMakeLists.txt index 66ddceb9..594a5287 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -603,18 +603,11 @@ endif() beman_install_library(beman.big_int TARGETS ${BEMAN_BIG_INT_INSTALL_TARGETS}) if(BEMAN_BIG_INT_BUILD_TESTS) - # Fetched only for the tests, so a package build (vcpkg, Conan) needs no - # network access, and kept out of this project's install. - include(FetchContent) - FetchContent_Declare( - googletest - URL - https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip - ) - # For Windows: Prevent overriding the parent project's compiler/linker settings - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) - FetchContent_MakeAvailable(googletest) + # [CMAKE.USE_FIND_PACKAGE] Test dependencies come from the environment, or + # from lockfile.json with + # -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./infra/cmake/use-fetch-content.cmake + # (as the presets do). + find_package(GTest REQUIRED) enable_testing() add_subdirectory(tests/beman/big_int) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f1bc147f..3b6fdf8b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,8 +60,9 @@ Instead of installing the project's dependencies via a package manager, you can configure beman.big_int to fetch them automatically via CMake FetchContent. To do so, specify -`-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./infra/cmake/use-fetch-content.cmake`. This will -bring in GoogleTest automatically along with any other dependency the project may require. +`-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./infra/cmake/use-fetch-content.cmake` (the CMake +presets already do). This will bring in GoogleTest and Boost.Multiprecision for the tests, +and Google Benchmark when `BEMAN_BIG_INT_BUILD_BENCHMARKS` is on. Example commands: diff --git a/docs/modules/ROOT/pages/benchmarks.adoc b/docs/modules/ROOT/pages/benchmarks.adoc index 11ac49ca..5de9cf8c 100644 --- a/docs/modules/ROOT/pages/benchmarks.adoc +++ b/docs/modules/ROOT/pages/benchmarks.adoc @@ -47,9 +47,10 @@ once a value outgrows the inplace buffer and the optimization no longer applies. [#benchmarks_small_value_build] === Building and running -Google Benchmark is pulled in with CMake `FetchContent` (just like GoogleTest), -gated behind the `BEMAN_BIG_INT_BUILD_BENCHMARKS` option. It is off by default and -only meaningful in a release build, so dedicated release presets enable it: +Google Benchmark is found with `find_package` (just like GoogleTest), and the +presets fetch it at the version pinned in `lockfile.json`. It is gated behind the +`BEMAN_BIG_INT_BUILD_BENCHMARKS` option, which is off by default and only +meaningful in a release build, so dedicated release presets enable it: [source,bash] ---- diff --git a/docs/modules/ROOT/pages/build_and_usage.adoc b/docs/modules/ROOT/pages/build_and_usage.adoc index 92b3f846..e5d666b5 100644 --- a/docs/modules/ROOT/pages/build_and_usage.adoc +++ b/docs/modules/ROOT/pages/build_and_usage.adoc @@ -20,11 +20,18 @@ This project requires at least the following to build: * A pass:[C++] compiler that conforms to the pass:[C++23] standard or greater * CMake 3.30 or later -* (Test only) GoogleTest +* (Test only) GoogleTest and Boost.Multiprecision +* (Benchmarks only) Google Benchmark You can disable building tests by setting the CMake option `BEMAN_BIG_INT_BUILD_TESTS` to `OFF` when configuring the project. +The build locates these with `find_package`, so any installation CMake can find +works, including one from vcpkg (the repository's `vcpkg.json` lists them). The +CMake presets instead fetch them at the versions pinned in `lockfile.json`; see the +https://github.com/bemanproject/big_int/blob/main/CONTRIBUTING.md[Contributing Guidelines] +to do the same without a preset. + [#build_and_usage_platforms] === Tested platforms diff --git a/lockfile.json b/lockfile.json index 787b9055..db65fb39 100644 --- a/lockfile.json +++ b/lockfile.json @@ -4,9 +4,29 @@ "name": "googletest", "package_name": "GTest", "git_repository": "https://github.com/google/googletest.git", - "git_tag": "6910c9d9165801d8827d628cb72eb7ea9dd538c5", + "git_tag": "03597a01ee50ed33e9dfd640b249b4be3799d395", "cmake_args": { - "INSTALL_GTEST": "OFF" + "INSTALL_GTEST": "OFF", + "gtest_force_shared_crt": "ON" + } + }, + { + "name": "boost_multiprecision", + "package_name": "boost_multiprecision", + "git_repository": "https://github.com/boostorg/multiprecision.git", + "git_tag": "c48ae180f5b22fca8479ac7e0c5f0d527d442072" + }, + { + "name": "googlebenchmark", + "package_name": "benchmark", + "git_repository": "https://github.com/google/benchmark.git", + "git_tag": "192ef10025eb2c4cdd392bc502f0c852196baa48", + "cmake_args": { + "BENCHMARK_ENABLE_TESTING": "OFF", + "BENCHMARK_ENABLE_GTEST_TESTS": "OFF", + "BENCHMARK_ENABLE_INSTALL": "OFF", + "BENCHMARK_INSTALL_DOCS": "OFF", + "BENCHMARK_ENABLE_WERROR": "OFF" } } ] diff --git a/tests/beman/big_int/CMakeLists.txt b/tests/beman/big_int/CMakeLists.txt index 0b41a56b..b32c988e 100644 --- a/tests/beman/big_int/CMakeLists.txt +++ b/tests/beman/big_int/CMakeLists.txt @@ -2,7 +2,6 @@ # SPDX-License-Identifier: BSL-1.0 include(GoogleTest) -include(FetchContent) option( BEMAN_BIG_INT_FUZZ @@ -12,20 +11,14 @@ option( file(GLOB TEST_SOURCES "*.test.cpp") -# Pull in Boost.Multiprecision for parity tests that cross-check beman::big_int -# against boost::cpp_int. -# The standalone release of this library is self-contained - -FetchContent_Declare( - boost_multiprecision - URL - https://github.com/boostorg/multiprecision/archive/refs/tags/Boost_1_89_0.tar.gz - URL_HASH - SHA256=d6000cc58594fead142eee4bf3a1aec39bf144dcb6accd8f4b8e6d780d258482 - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - SYSTEM -) -FetchContent_MakeAvailable(boost_multiprecision) +# Boost.Multiprecision, for parity tests that cross-check beman::big_int against +# boost::cpp_int. When lockfile.json supplies it as a subproject, mark it SYSTEM +# as an installed package would be, so the warning set below skips its headers. +find_package(boost_multiprecision REQUIRED) +get_target_property(_bigint_boost_mp Boost::multiprecision ALIASED_TARGET) +if(_bigint_boost_mp) + set_target_properties(${_bigint_boost_mp} PROPERTIES SYSTEM ON) +endif() # The project's test warning set. function(beman_big_int_test_warnings test_target) diff --git a/tests/beman/big_int/perf/CMakeLists.txt b/tests/beman/big_int/perf/CMakeLists.txt index 87e739d4..f69a7e76 100644 --- a/tests/beman/big_int/perf/CMakeLists.txt +++ b/tests/beman/big_int/perf/CMakeLists.txt @@ -88,29 +88,17 @@ if(BEMAN_BIG_INT_SHAPE_SWEEP_ONLY) return() endif() -include(FetchContent) - -# Pull in Google Benchmark for the big_int-vs-builtin micro-benchmarks, mirroring -# how the top-level build fetches GoogleTest. Only fetched when +# Google Benchmark for the big_int-vs-builtin micro-benchmarks, found like +# GoogleTest (see the top-level CMakeLists). Only needed when # BEMAN_BIG_INT_BUILD_BENCHMARKS is enabled (this directory is added from the -# top-level CMakeLists under that option). -set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) -set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE) -set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) -set(BENCHMARK_INSTALL_DOCS OFF CACHE BOOL "" FORCE) -# Google Benchmark builds itself with -Werror by default, which can break on -# newer compilers than its release was tested against; turn it off. -set(BENCHMARK_ENABLE_WERROR OFF CACHE BOOL "" FORCE) - -FetchContent_Declare( - googlebenchmark - URL https://github.com/google/benchmark/archive/refs/tags/v1.9.5.tar.gz - URL_HASH - SHA256=9631341c82bac4a288bef951f8b26b41f69021794184ece969f8473977eaa340 - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - SYSTEM -) -FetchContent_MakeAvailable(googlebenchmark) +# top-level CMakeLists under that option). lockfile.json turns off its tests, +# install and -Werror; when it supplies it as a subproject, mark it SYSTEM as an +# installed package would be. +find_package(benchmark REQUIRED) +get_target_property(_bigint_benchmark benchmark::benchmark ALIASED_TARGET) +if(_bigint_benchmark) + set_target_properties(${_bigint_benchmark} PROPERTIES SYSTEM ON) +endif() # Benchmark sources use the `.gbench.cpp` suffix so they are never confused with # the standalone GMP/boost comparison programs (`*.perf.cpp`, `*.limbs.cpp`) that diff --git a/vcpkg.json b/vcpkg.json index 5ea1ed95..535dff74 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,5 +1,17 @@ { - "$comment": "Developer manifest. The library has no dependencies; the tests fetch GoogleTest and Boost.Multiprecision with FetchContent. The released port is rendered from port/.", + "$comment": "Developer manifest for the tests (and, with the benchmarks feature, the benchmarks); lockfile.json pins the same dependencies for infra/cmake/use-fetch-content.cmake. The released port is rendered from port/.", "name": "beman-big-int", - "version-semver": "0.1.1" + "version-semver": "0.1.1", + "dependencies": [ + "boost-multiprecision", + "gtest" + ], + "features": { + "benchmarks": { + "description": "Google Benchmark, for BEMAN_BIG_INT_BUILD_BENCHMARKS", + "dependencies": [ + "benchmark" + ] + } + } }