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 options
  • CMakeLists.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 be https://... or git@...)
  • 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).

  1. 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
)
  1. 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"
)
  1. 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.