diff --git a/.github/workflows/build2.yml b/.github/workflows/build2.yml new file mode 100644 index 0000000..58ed999 --- /dev/null +++ b/.github/workflows/build2.yml @@ -0,0 +1,115 @@ +# build2 packaging smoke test. +# +# Validates the build2 metadata (manifest + buildfiles) against the real build2 +# toolchain: configures, "builds" the binless (header-only) lib{geo-utils}, +# installs to a temporary prefix, asserts the headers land under +# /include/geo/ with the detail/ subdirectory preserved, and finally +# compiles + runs a consumer (tests/consumer/main.cpp) against the installed +# package via the generated libgeo-utils.pc — so a broken export interface +# (cxx.export.poptions / .pc) fails here too, not just a missing file. +# +# This is the build2 analogue of the CMake-based install.yml: it catches +# regressions in manifest/buildfile/install-layout that the CMake, vcpkg, and +# xrepo jobs can't see. The toolchain comes from the Homebrew bottle (fast, no +# source build). We run macOS-only: for a binless (header-only) library the +# manifest, buildfiles, and install layout are OS-independent, so one platform +# fully exercises the packaging — and macOS avoids the extra Linuxbrew PATH +# wiring the Ubuntu runners would need. +# +# Triggered on push/PR to master/main, but only when files that affect the +# build2 package change (manifest, buildfiles, headers, the consumer, this +# workflow) — see the paths filter below. Can also be run manually from the +# Actions tab in GitHub UI. + +name: build2 + +on: + push: + branches: [master, main] + paths: + - 'manifest' + - 'buildfile' + - '**/buildfile' + - 'build/*.build' + - 'include/**' + - 'tests/consumer/**' + - '.github/workflows/build2.yml' + pull_request: + branches: [master, main] + paths: + - 'manifest' + - 'buildfile' + - '**/buildfile' + - 'build/*.build' + - 'include/**' + - 'tests/consumer/**' + - '.github/workflows/build2.yml' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build2: + name: build2 install (${{ matrix.os }}) + strategy: + fail-fast: false + matrix: + os: [macos-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + + - name: Install build2 toolchain + run: brew install build2 + + # In-source configuration of the project root. The cxx module is loaded + # (root.build), so a working C++ compiler is required even though a binless + # library compiles nothing; config.cxx=c++ picks the platform default + # (g++ on Linux, AppleClang on macOS). + - name: Configure + run: | + eval "$(brew shellenv)" + b --version + b configure config.cxx=c++ config.install.root="$RUNNER_TEMP/inst" + + - name: Install + run: | + eval "$(brew shellenv)" + b install + + # Assert the public entry header, a regular header, and a nested detail/ + # header all land under /include/geo/ — i.e. that install.subdirs + # preserved the detail/ subdirectory. + - name: Verify installed header layout + run: | + inst="$RUNNER_TEMP/inst" + test -f "$inst/include/geo/geo.hpp" + test -f "$inst/include/geo/spherical.hpp" + test -f "$inst/include/geo/detail/math.hpp" + echo "build2 install layout OK:" + find "$inst/include/geo" -type f | sort + + # Compile + run a real consumer against the *installed* package, resolving + # the include path through the generated libgeo-utils.pc. This exercises + # the export interface end-to-end (cxx.export.poptions -> .pc -> -I), which + # the file-existence check above cannot. pkg-config ships on the macOS + # runner image; install pkgconf as a fallback just in case. + - name: Consumer compile + run (pkg-config) + run: | + eval "$(brew shellenv)" + command -v pkg-config >/dev/null || brew install pkgconf + inst="$RUNNER_TEMP/inst" + export PKG_CONFIG_PATH="$inst/lib/pkgconfig" + pkg-config --exists libgeo-utils + cflags=$(pkg-config --cflags libgeo-utils) + echo "pkg-config --cflags libgeo-utils: $cflags" + c++ -std=c++17 $cflags tests/consumer/main.cpp -o "$RUNNER_TEMP/consumer" + "$RUNNER_TEMP/consumer" + echo "build2 consumer compile + run OK" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f11f72..a87ea42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,17 +57,17 @@ jobs: - name: Cache FetchContent dependencies uses: actions/cache@v4 with: - path: build/_deps + path: build-cmake/_deps # Include repo name in the key so a repo rename (which changes the # absolute work-dir path baked into FetchContent's subbuild cache) # invalidates stale caches automatically. key: ${{ runner.os }}-${{ matrix.name }}-${{ github.event.repository.name }}-googletest-1.14.0 - name: Configure - run: cmake -S . -B build -DGEO_UTILS_CPP_BUILD_TESTS=ON -DGEO_UTILS_CPP_BUILD_EXAMPLES=ON + run: cmake -S . -B build-cmake -DGEO_UTILS_CPP_BUILD_TESTS=ON -DGEO_UTILS_CPP_BUILD_EXAMPLES=ON - name: Build - run: cmake --build build --config Release + run: cmake --build build-cmake --config Release - name: Test - run: ctest --test-dir build -C Release --output-on-failure + run: ctest --test-dir build-cmake -C Release --output-on-failure diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7c91fff..6391628 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -35,7 +35,7 @@ jobs: - name: Cache FetchContent dependencies uses: actions/cache@v4 with: - path: build/_deps + path: build-cmake/_deps # Include repo name in the key so a repo rename (which changes the # absolute work-dir path baked into FetchContent's subbuild cache) # invalidates stale caches automatically. @@ -45,16 +45,16 @@ jobs: run: pip install gcovr - name: Configure - run: cmake -S . -B build -DGEO_UTILS_CPP_BUILD_TESTS=ON -DGEO_UTILS_CPP_ENABLE_COVERAGE=ON + run: cmake -S . -B build-cmake -DGEO_UTILS_CPP_BUILD_TESTS=ON -DGEO_UTILS_CPP_ENABLE_COVERAGE=ON - name: Build - run: cmake --build build + run: cmake --build build-cmake - name: Test - run: ctest --test-dir build --output-on-failure + run: ctest --test-dir build-cmake --output-on-failure - name: Generate coverage report - run: gcovr --xml coverage.xml --root . --filter 'include/' build/ + run: gcovr --xml coverage.xml --root . --filter 'include/' build-cmake/ # Skip upload on PRs from forks: secrets.CODECOV_TOKEN is unavailable to # workflows running on PRs from forked repositories, and a missing token diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml index b430767..26539d7 100644 --- a/.github/workflows/install.yml +++ b/.github/workflows/install.yml @@ -45,13 +45,13 @@ jobs: # generated .pc file; the install step must not pass --prefix or the # .pc would point at the configure-time prefix while files land elsewhere. - name: Configure library - run: cmake -S . -B build -DCMAKE_INSTALL_PREFIX=${{ runner.temp }}/prefix + run: cmake -S . -B build-cmake -DCMAKE_INSTALL_PREFIX=${{ runner.temp }}/prefix - name: Build library - run: cmake --build build --config Release + run: cmake --build build-cmake --config Release - name: Install library - run: cmake --install build --config Release + run: cmake --install build-cmake --config Release # pkg-config sanity: catches regressions in the .pc template, including # malformed includedirs (doubled prefix → //) and non-relocatable templates diff --git a/.gitignore b/.gitignore index 7adb8bb..307dff8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ -build/ +# Ignore CMake/build2 out-of-tree build artifacts under build/, but keep +# the tracked build2 metadata files (build/bootstrap.build, build/root.build). +build/* +!build/bootstrap.build +!build/root.build build-*/ # Compiled Object files diff --git a/README.md b/README.md index d73e6f6..6aefaed 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,36 @@ conan install --requires=geo-utils-cpp/1.0.1 --build=missing Conan Center support is pending [conan-io/conan-center-index#30152](https://github.com/conan-io/conan-center-index/pull/30152) +### build2 / bpkg + +> **Package name note:** in the build2 ecosystem this library follows the +> build2 `libfoo` convention and is named **`libgeo-utils`** (cppget.org +> submission pending). Everywhere else — GitHub project, CMake, vcpkg, Conan, +> xrepo — it is named **`geo-utils-cpp`**. Both names refer to the same library, +> same headers, same `#include ` API. + +Add the dependency to your package's `manifest`: + +``` +depends: libgeo-utils ^1.0.1 +``` + +And in the consuming `buildfile`: + +``` +import libs = libgeo-utils%lib{geo-utils} + +exe{hello}: cxx{hello} $libs +``` + +Until it is available on cppget.org, point your project at this Git repository +so the dependency above resolves — add it to your `repositories.manifest`: + +``` +role: prerequisite +location: https://github.com/gistrec/geo-utils-cpp.git#master +``` + ### Manual Copy the `include/` directory into your project and add it to your include path. diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 515e7b3..007aa2c 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -1,8 +1,8 @@ # Benchmarks for geo-utils-cpp. # # Build with: -# cmake -B build -DGEO_UTILS_CPP_BUILD_BENCHMARKS=ON -# cmake --build build --target bench_all +# cmake -B build-bench -DGEO_UTILS_CPP_BUILD_BENCHMARKS=ON +# cmake --build build-bench --target bench_all # # Google Benchmark is fetched automatically. S2, Boost.Geometry, and # GeographicLib are looked up via find_package — missing competitors are diff --git a/build/bootstrap.build b/build/bootstrap.build new file mode 100644 index 0000000..63ffeb5 --- /dev/null +++ b/build/bootstrap.build @@ -0,0 +1,7 @@ +project = libgeo-utils + +using version + +using config +using dist +using install diff --git a/build/root.build b/build/root.build new file mode 100644 index 0000000..17ee783 --- /dev/null +++ b/build/root.build @@ -0,0 +1,5 @@ +cxx.std = 17 + +using cxx + +hxx{*}: extension = hpp diff --git a/buildfile b/buildfile new file mode 100644 index 0000000..6143bca --- /dev/null +++ b/buildfile @@ -0,0 +1 @@ +./: include/ doc{README.md LICENSE NOTICE CHANGELOG.md} manifest diff --git a/docs/getting-started.md b/docs/getting-started.md index ce0bc1e..0bc1371 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -113,8 +113,8 @@ Build and install the library to a prefix on your machine, then have downstream projects locate it via `find_package`: ```sh -cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -cmake --install build --prefix /usr/local +cmake -S . -B build-cmake -DCMAKE_BUILD_TYPE=Release +cmake --install build-cmake --prefix /usr/local ``` ```cmake @@ -231,9 +231,9 @@ measuring coverage — clone the repo and configure it as a top-level project: ```sh -cmake -S . -B build -cmake --build build -ctest --test-dir build --output-on-failure +cmake -S . -B build-cmake +cmake --build build-cmake +ctest --test-dir build-cmake --output-on-failure ``` ### Build options diff --git a/include/buildfile b/include/buildfile new file mode 100644 index 0000000..c2ccdd8 --- /dev/null +++ b/include/buildfile @@ -0,0 +1 @@ +./: geo/ diff --git a/include/geo/buildfile b/include/geo/buildfile new file mode 100644 index 0000000..7322ef1 --- /dev/null +++ b/include/geo/buildfile @@ -0,0 +1,11 @@ +lib{geo-utils}: hxx{**} + +# Public include path: consumers do `#include `. +lib{geo-utils}: cxx.export.poptions = "-I$out_root/include" "-I$src_root/include" + +# Install headers under /include/geo/, preserving the detail/ subdir. +hxx{*}: +{ + install = include/geo/ + install.subdirs = true +} diff --git a/manifest b/manifest new file mode 100644 index 0000000..82bfa3b --- /dev/null +++ b/manifest @@ -0,0 +1,14 @@ +: 1 +name: libgeo-utils +version: 1.0.1 +project: geo-utils-cpp +language: c++ +summary: Header-only C++17 geographic geometry utilities +license: Apache-2.0 +topics: geography, geometry, spherical, distance, header-only +description-file: README.md +description-type: text/markdown +changes-file: CHANGELOG.md +changes-type: text/markdown +url: https://github.com/gistrec/geo-utils-cpp +email: gistrec@gmail.com