Skip to content

Make svector installable: CMake install/export rules and find_package support #89

Description

@martinus

What

Finish the job #31 started: make svector installable and discoverable as a dependency, so find_package(svector) works after an install and packagers have something to call. Currently only the add_subdirectory/FetchContent path exists.

Why

#31 asked for nlohmann/json-style CMake integration and closed before getting there. It was filed 2022-05-31 pointing at nlohmann/json as the template, and closed four days later with "Should work now". What shipped was the add_subdirectory subset. What nlohmann/json also provides, and this does not, is an install target, an export set, a generated package config, and a version file.

Neither build file contains any of it. A grep for install, export, GNUInstallDirs, declare_dependency, override_dependency, install_headers and pkgconfig across CMakeLists.txt and meson.build returns nothing. Concretely, today:

  • find_package(svector) after an install does not work, because nothing installs and nothing exports.
  • Distro and system packagers have no install rule to invoke.
  • meson users cannot consume this as a subproject either — there is no declare_dependency for a parent project to pick up, and no meson.override_dependency.

There is a fossil of the abandoned attempt. CMakeLists.txt sets

$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>

but never does include(GNUInstallDirs), so CMAKE_INSTALL_INCLUDEDIR is undefined and that generator expression expands empty. It is harmless only because nothing installs or exports — which is itself the evidence that this path was half-written and dropped.

The standalone guard is part of why #48 happened. CMakeLists.txt defines the interface target only when _svector_is_included is true:

if(_svector_is_included)
    add_library(svector INTERFACE)
    ...
endif()

So configuring the repository standalone defines nothing at all. That is precisely what the reporter of #48 hit — "I downloaded svector, ran cmake, ran make, and that didn't really do anything." Adding install rules means reconsidering that guard: standalone should at minimum produce an installable target, while still not building the tests, which remain meson's job.

What works today and must not regress. The add_subdirectory path is fine. A consumer project that adds this repo as a subdirectory and links svector::svector configures, builds and runs a program including the header. That is the one path people use now.

Work

  • include(GNUInstallDirs) and fix the empty INSTALL_INTERFACE include directory.
  • Rework the _svector_is_included guard so the svector / svector::svector interface target exists in both the standalone and the included case, and gate only the install rules on standalone (the usual if(PROJECT_IS_TOP_LEVEL) pattern, spelled by hand since cmake_minimum_required here is 3.12 and that variable arrived in 3.21). Keep the promise that CMake never builds the tests.
  • Add install(TARGETS svector EXPORT svectorTargets) plus install(DIRECTORY include/ ...) for the header.
  • Generate and install svectorConfig.cmake and svectorConfigVersion.cmake via CMakePackageConfigHelpers. Use PROJECT_VERSION, which scripts/lint/lint-version.py already keeps in sync with the header macros, so the package version cannot drift from ANKERL_SVECTOR_VERSION_*. SameMajorVersion compatibility matches the semver policy the header documents.
  • Consider installing a pkg-config file too — cheap for a header-only library and what non-CMake and distro consumers reach for.
  • On the meson side, add a declare_dependency(include_directories: incdir) and meson.override_dependency('svector', ...) so the project is usable as a meson subproject, and optionally install_headers for symmetry.
  • Extend the CMake consumer smoke test scoped in #84 to cover the new path: install to a temporary prefix, then configure a separate project that does find_package(svector REQUIRED) and links svector::svector. Both consumption paths should be tested, not just the one.
  • Document both paths in the README next to the existing "Building & Testing" section — FetchContent, and find_package after install.

Acceptance criteria

  • cmake --install to a prefix, then find_package(svector 1.3 REQUIRED) from a separate project, compiles and runs a program using ankerl::svector.
  • The existing add_subdirectory / FetchContent path still works unchanged.
  • A version mismatch, for example find_package(svector 2.0 REQUIRED), fails as it should.
  • CMake still never builds or runs the tests.
  • Both paths are covered in CI.

Note

This is deliberately not a proposal to move the build to CMake. Meson stays the development build system — it carries the sanitizer and hardening configurations, the wrap-based dependencies, the benchmark separation and the libFuzzer target, none of which have cheap CMake equivalents. This issue only makes the library consumable by people who do not care what it is built with.

Unrelated but adjacent: ConanCenter currently ships svector/1.0.3, which is three releases behind. Worth a nudge to that recipe once this lands.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions