ADIOS2 icon indicating copy to clipboard operation
ADIOS2 copied to clipboard

Building ADIOS2 (optionally) as part of project that also has yaml-cpp as dependency (CMake build)

Open lsawade opened this issue 6 months ago • 4 comments

Problem

CMake target collision between yaml-cpp dependencies

When using ADIOS2 as an optional dependency alongside yaml-cpp as a hard dependency, both libraries attempt to create the same yaml-cpp target, causing a CMake configuration failure.

Details

In our CMake configuration, we configure yaml-cpp since it is a hard dependency, while ADIOS2 is optional. The yaml-cpp configuration creates:

add_library(yaml-cpp)

However, ADIOS2 does not recognize the external configuration (yaml-cpp-config.cmake) or does not match the ADIOS2 requirements. As a result, ADIOS2's configuration also tries to:

add_library(yaml-cpp)

This uses ADIOS2's internal yaml-cpp, which then fails since the target is already configured by the external yaml-cpp.

Current Workaround

My current solution is to populate adios2:

# For CMake versions < 3.28, EXCLUDE_FROM_ALL is not supported in FetchContent_Declare
      FetchContent_Declare(
          ADIOS2
          URL ${ADIOS2_URL}
          USES_TERMINAL_DOWNLOAD True
          GIT_PROGRESS TRUE
          DOWNLOAD_NO_EXTRACT FALSE
          DOWNLOAD_EXTRACT_TIMESTAMP FALSE
      )

      FetchContent_GetProperties(ADIOS2)
      if(NOT adios2_POPULATED)
          FetchContent_Populate(ADIOS2)
          # Patch ADIOS2's thirdparty CMakeLists.txt to skip yaml-cpp
          file(READ "${adios2_SOURCE_DIR}/thirdparty/CMakeLists.txt" THIRDPARTY_CMAKE)
          string(REPLACE "add_subdirectory(yaml-cpp)" "# add_subdirectory(yaml-cpp) # Skipped - using external yaml-cpp" THIRDPARTY_CMAKE "${THIRDPARTY_CMAKE}")
          file(WRITE "${adios2_SOURCE_DIR}/thirdparty/CMakeLists.txt" "${THIRDPARTY_CMAKE}")
          add_subdirectory(${adios2_SOURCE_DIR} ${adios2_BINARY_DIR} EXCLUDE_FROM_ALL)
      endif()

so that the standalone version of yaml is being linked against.

Issue with workaround

Future deprecation of

FetchContent_GetProperties(ADIOS2)
FetchContent_Populate(ADIOS2)

Proposed Solution

For consistency, ADIOS2 should wrap their external dependency targets so that projects that optionally depend on ADIOS2 can configure their own yaml-cpp version. This would allow proper dependency management where the parent project controls shared dependencies.

Environment

  • CMake version: cmake 3.31.1
  • ADIOS2 version: Current release 2.10.2
  • desired yaml-cpp version: 0.8.0

lsawade avatar Aug 12 '25 14:08 lsawade

ADIOS can be told to build with external yaml-cpp and pugixml.

      -DADIOS2_USE_EXTERNAL_YAMLCPP=ON \
      -DADIOS2_USE_EXTERNAL_PUGIXML=ON \
      -DCMAKE_PREFIX_PATH="/opt/yaml-cpp;/opt/pugixml" \

Would this solve your issue?

pnorbert avatar Aug 12 '25 16:08 pnorbert

Hi Norbert! This would not solve my issue, because I'm building yaml-cpp inside my project. Pseudo cmake looks like this:

project(specfempp)

include('cmake/yaml-cpp.cmake) # configures yaml-cpp -> runs add_library(yaml-cpp)

include('cmake/adios2.cmake) # configures adios2/thirdparty/yaml-cpp -> runs add_library(yaml-cpp)

I'm assuming that yaml-cpp is not installed on the user's system.

lsawade avatar Aug 12 '25 17:08 lsawade

My suggestion would be in https://github.com/ornladios/ADIOS2/blob/5abc6bab9a9ff3df590e209019b88d1099bbe148/thirdparty/CMakeLists.txt#L72C1-L76C8

something like

if (NOT TARGET yaml-cpp)
  if(ADIOS2_USE_EXTERNAL_YAMLCPP)
    find_package(yaml-cpp 0.7.0 REQUIRED)
  else()
    add_subdirectory(yaml-cpp)
  endif()
endif()

PS: Link to current workaround that is disabling add_subdirectory(yaml-cpp) on the adios2 side

lsawade avatar Aug 12 '25 17:08 lsawade

So another apporach is telling adios that we have 0.7.0 installed by writing a small "fake" yaml-cpp config and installing yaml-cpp=0.7.0. A minimal working example here: https://github.com/lsawade/minimal_cmake_example_yaml_and_adios2

lsawade avatar Aug 13 '25 15:08 lsawade