3

I'm using yaml-cpp library recently. I follow the config file in "yaml-cpp-config.cmake.in" which content is

# - Config file for the yaml-cpp package
# It defines the following variables
#  YAML_CPP_INCLUDE_DIR - include directory
#  YAML_CPP_LIBRARIES    - libraries to link against

# Compute paths
get_filename_component(YAML_CPP_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(YAML_CPP_INCLUDE_DIR "@CONFIG_INCLUDE_DIRS@")

# Our library dependencies (contains definitions for IMPORTED targets)
include("${YAML_CPP_CMAKE_DIR}/yaml-cpp-targets.cmake")
 
# These are IMPORTED targets created by yaml-cpp-targets.cmake
set(YAML_CPP_LIBRARIES "@EXPORT_TARGETS@")

According line 8 and line 14 (or the comment section), I edited my CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)
project(yaml_test)
find_package(yaml-cpp)
include_directories(${YAML_CPP_INCLUDE_DIRS})

add_executable(yaml_test src/test.cpp)
target_link_libraries(yaml_test ${YAML_CPP_LIBRARIES})

and test.cpp:

#include <yaml-cpp/yaml.h>

int main()
{ 
  YAML::Node node = YAML::LoadFile("test.yaml");

  return 0;
}

and I got

CMakeFiles/yaml_test.dir/src/test.cpp.o: In function `main':
test.cpp:(.text+0xf9): undefined reference to `YAML::LoadFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: error: ld returned 1 exit status
CMakeFiles/yaml_test.dir/build.make:94: recipe for target 'yaml_test' failed
make[2]: *** [yaml_test] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/yaml_test.dir/all' failed
make[1]: *** [CMakeFiles/yaml_test.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

I found a solution from undefined reference to YAML::LoadFile

changed my CMakeLists.txt to

cmake_minimum_required(VERSION 3.5)
project(yaml_test)
find_package(yaml-cpp)
include_directories(${YAMLCPP_INCLUDE_DIRS})

add_executable(yaml_test src/test.cpp)
target_link_libraries(yaml_test ${YAMLCPP_LIBRARIES})

And I can build my code succesfully.

My question is how can I tell the right include_directories and target_link_libraries straight from yaml-cpp package's CMakeLists.txt or config file?

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
hankyuan
  • 31
  • 3
  • When use `YAMLCPP` variable you seems refer to [that answer](https://stackoverflow.com/a/56332184/3440745). But this answer doesn't use `find_package(yaml-cpp)`. Instead, it uses macro `pkg_check_modules` for get information about `yaml-cpp` package, and `YAMLCPP` is simply passed to this macro (that is, you may pass any other prefix, and this prefix will be used for the output variables). But your second snippet still uses `find_package(yaml-cpp)`, which contradicts to that answer and simply wrong. – Tsyvarev Jul 08 '20 at 06:57

1 Answers1

2

My question is how can I tell the right "include_directories" and "target_link_libraries" straight from yaml-cpp package's CMakeLists.txt or config file?

Just make sure you look into the config file, which is actually used by CMake. E.g. yaml-cpp-config.cmake.in is just a template for future yaml-cpp-config.cmake, but your system could have other config files for the same package.

CMake stores the exact path to the config file in the <PackageName>_CONFIG variable so you may print value of this variable if unsure:

...
find_package(yaml-cpp)
message(STATUS "Used config file: ${yaml-cpp_CONFIG}")

Important note

When read a config file, aside from the documentation at the top it is useful for check the set line which assigns a value to the documented variable like *_LIBRARY or *_LIBRARIES. If that value is empty, then the "config" file is probably broken and documented variables most likely cannot be used. But you may resort to the using of IMPORTED targets, see below.

Note, that most "config" files provide IMPORTED target(s) for use by other code.

This mechanism is preferred over using variables *_INCLUDE_DIR and *_LIBRARIES. If cannot find the documentation about which exact IMPORTED target to use, then see into the value of *_LIBRARIES variable in the config file: The variable may contain a list of IMPORTED targets, which you could try to use in your code via target_link_libraries.

For more details look into find_package documentation.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • Hi, Tsyvarev. Thanks for you professional answer. But I still have a problem. After I follow your suggestion. I find the config file is located at /usr/local/share/cmake/yaml-cpp. There is four cmake files including "yaml-cpp-config.cmake", "yaml-cpp-targets.cmake", "yaml-cpp-config-version.cmake", and "yaml-cpp-targets-noconfig.cmake". But in "yaml-cpp-config.cmake", there is the same content as template config file. In "yaml-cpp-config-targets.cmake", I can't find any relevant word as "YAML_CPP" or "YAMLCPP". – hankyuan Jul 08 '20 at 06:05
  • Sorry for asking such an annoy problem, but I stock in this problem for very long time...... – hankyuan Jul 08 '20 at 06:07
  • You need to look only into `yaml-cpp-config.cmake`: only this script could contain setting of variable which could be useful for the user. Files `yaml-cpp-targets.cmake` and `yaml-cpp-targets-noconfig.cmake` are generated by CMake and quite complex, but they could define only IMPORTED targets. The file `yaml-cpp-config-version.cmake` is only about version checking. If the file `yaml-cpp-config.cmake` describes the variable `YAML_CPP_LIBRARIES`, then this variable should work... Is line `set(YAML_CPP_LIBRARIES "...")` assigns a **non-empty value** to the variable? – Tsyvarev Jul 08 '20 at 06:56
  • Yes, I found a solution in [link](https://stackoverflow.com/questions/59893474/why-my-package-config-cmake-have-package-include-dir-and-package-librairie) And my _yaml-cp-config.cmake_ just like you said. It assigns both empty value to YAML_CPP_INCLUDE_DIR and YAML_CPP_LIBRARIES `set(YAML_CPP_LIBRARIES "")` `set(YAML_CPP_INCLUDE_DIR "")` But why they are empty values? I built this library by [this insturction](https://github.com/jbeder/yaml-cpp). And I doing something wrong? – hankyuan Jul 08 '20 at 07:08
  • "But why they are empty values?" - This is a bug(?) in the yaml-cpp project. In the [linked answer](https://stackoverflow.com/questions/59893474/why-my-package-config-cmake-have-package-include-dir-and-package-librairie) there is a link to the bugreport, which is still open. – Tsyvarev Jul 08 '20 at 07:16
  • Thanks you for your patience. I can move forward finally! – hankyuan Jul 08 '20 at 07:22