Adding libraries with CPM - PIONEER-Experiment/zmq_publisher GitHub Wiki
Configuring CPM Dependencies
The publisher uses CPM.cmake to automatically fetch, configure, and build dependencies at configure time. This ensures reproducible builds and removes the need to manually install most libraries.
All dependency configuration lives in:
cmake/CPMConfig.cmake— lists dependencies, their sources, and optionsCMakeLists.txt— iterates over the list, downloads/builds each, and links the resulting targets
How Dependencies Are Declared
Each dependency is defined as a block in CPMConfig.cmake. For example:
# ---------------------- cppzmq (header-only) ----------------------
set(cppzmq_REPO "zeromq/cppzmq")
set(cppzmq_TAG "v4.8.1")
set(cppzmq_TARGET "") # No target needed; header-only
set(cppzmq_DOWNLOAD_ONLY YES)
set(cppzmq_OPTIONS
"BUILD_EXAMPLES OFF"
"BUILD_TESTS OFF"
)
This defines:
- Repository:
zeromq/cppzmq(GitHub shorthand, could also behttps://...orgit@...) - Tag/branch:
v4.8.1 - Target(s): either a single CMake target (
cppzmq::cppzmq) or left empty for header-only - Download only: marks it as header-only → CPM will fetch it but not try to build
- Options: passed to the project’s CMake at configure time
All dependencies are listed in the variable CPM_PACKAGE_LIST, and then CMakeLists.txt loops over them.
Linking Dependencies
At the bottom of CMakeLists.txt, all declared CPM packages are automatically linked:
foreach(pkg IN LISTS CPM_PACKAGE_LIST)
if(DEFINED ${pkg}_TARGET AND NOT ${${pkg}_TARGET} STREQUAL "")
target_link_libraries(publisher PRIVATE ${${pkg}_TARGET})
elseif(DEFINED ${pkg}_TARGETS)
foreach(subtarget IN LISTS ${pkg}_TARGETS)
target_link_libraries(publisher PRIVATE ${subtarget})
endforeach()
else()
message(STATUS "Skipping linking header-only or no-target package: ${pkg}")
endif()
endforeach()
This means that once a dependency is added to CPMConfig.cmake, it will automatically be available to the publisher target.
Example: Adding a New Dependency
Say you want to add fmtlib (a formatting library).
- Add it to the package list:
set(CPM_PACKAGE_LIST
cppzmq
TBB
analysis_pipeline_core
analysis_pipeline
midas_receiver
unpacker_data_products_core
midas_event_unpacker_plugin
fmt # <-- new
)
- Define its configuration:
set(fmt_REPO "fmtlib/fmt")
set(fmt_TAG "10.2.1")
set(fmt_TARGET "fmt::fmt")
set(fmt_OPTIONS
"FMT_TEST OFF"
"CMAKE_POSITION_INDEPENDENT_CODE ON"
)
- Reconfigure and build:
./scripts/build.sh --overwrite
fmt::fmt will now be linked into the publisher automatically.
Header-Only Packages
For header-only libraries, set:
set(pkg_TARGET "")
set(pkg_DOWNLOAD_ONLY YES)
The CMakeLists.txt will then generate an INTERFACE target automatically, so you can still target_link_libraries(publisher PRIVATE pkg::pkg).
Notes
- Order matters in
CPM_PACKAGE_LIST— dependencies must be listed before projects that depend on them. - System dependencies (ROOT, ZLIB, Threads, libzmq) are still found via
find_package()because they are too large or platform-specific to fetch via CPM. - Local overrides: If you install a library manually, CPM will use the system copy instead of downloading.