Skip to content

CMake: support consumption via FetchContent, add_subdirectory, and Boost superproject #181

@sgerbino

Description

@sgerbino

Problem

Capy cannot be cleanly consumed by downstream projects via FetchContent or add_subdirectory, and has gaps in its Boost superproject integration.

Boost superproject integration

No boost_install() callinstall(EXPORT ...) is never created for boost_capy. Downstream Boost libraries that depend on boost_capy and use boost_install themselves will fail:

CMake Error: install(EXPORT "...") includes target "..." which requires
target "boost_capy" that is not in any export set.

This is the same class of issue reported in cppalliance/corosio#125.

FetchContent / add_subdirectory consumption

target_include_directories uses raw pathsboost_capy_setup_properties uses "${PROJECT_SOURCE_DIR}/include" without BUILD_INTERFACE/INSTALL_INTERFACE generator expressions. This embeds the build machine's absolute path into the installed target, breaking consumers who find_package after install. The private include path ("${PROJECT_SOURCE_DIR}") has the same issue.

Unconditional benchmark buildadd_subdirectory(bench) is not gated by an option, so FetchContent consumers also build capy's benchmark executable.

Standalone preset is inadequate

The CMakePresets.json standalone preset is a thin wrapper that just sets a few cache variables (C++20, Release, tests/examples off). It doesn't resolve dependencies or provide a real standalone build story. It should be removed — developers who want a quick local build can pass those variables directly. Corosio's CMakeLists.txt already handles the real standalone case (FetchContent fallback for Boost + capy), and capy should follow the same pattern if/when it has dependencies.

Proposed Changes

1. Add boost_install() for superproject builds

if(BOOST_SUPERPROJECT_VERSION AND NOT CMAKE_VERSION VERSION_LESS 3.13)
    boost_install(
        TARGETS boost_capy
        VERSION ${BOOST_SUPERPROJECT_VERSION}
        HEADER_DIRECTORY include
    )
endif()

2. Use generator expressions for include directories

target_include_directories(${target} PUBLIC
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>)
target_include_directories(${target} PRIVATE
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)

3. Gate benchmarks behind an option

option(BOOST_CAPY_BUILD_BENCH "Build boost::capy benchmarks" ${BOOST_CAPY_IS_ROOT})
if(BOOST_CAPY_BUILD_BENCH)
    add_subdirectory(bench)
endif()

4. Remove standalone preset

Delete CMakePresets.json. The standalone preset provides no value beyond a few cache variable defaults and creates a false impression that capy supports a real standalone build mode.

Acceptance Criteria

  • Boost superproject: boost_install creates proper export sets; downstream libraries using boost_install don't get CMake errors about missing export sets
  • FetchContent: a downstream project can FetchContent_Declare(capy ...) and target_link_libraries(... Boost::capy) without pulling in benchmarks
  • Install: find_package(boost_capy) works after cmake --install without embedding source tree paths
  • No CMakePresets.json in the repository

Related

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions