Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

Expand Down Expand Up @@ -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.

Expand Down
38 changes: 37 additions & 1 deletion .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/vcpkg-release.yml
Original file line number Diff line number Diff line change
@@ -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 }}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 7 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -613,6 +603,12 @@ endif()
beman_install_library(beman.big_int TARGETS ${BEMAN_BIG_INT_INSTALL_TARGETS})

if(BEMAN_BIG_INT_BUILD_TESTS)
# [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)

Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
99 changes: 99 additions & 0 deletions conanfile.py
Original file line number Diff line number Diff line change
@@ -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"]
7 changes: 4 additions & 3 deletions docs/modules/ROOT/pages/benchmarks.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
----
Expand Down
75 changes: 74 additions & 1 deletion docs/modules/ROOT/pages/build_and_usage.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -288,6 +295,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

Expand Down
Loading
Loading