Building ADIOS2 (optionally) as part of project that also has yaml-cpp as dependency (CMake build)
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
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?
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.
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
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