3

I use find_package() to find some library. How do I know which variables it defines, so I could use them for linking with that library?

For example, the following CMakeLists.txt successfully is run by CMake, but then make fails at the linking stage, because ${DOCOPT_LIBRARIES} was empty.

cmake_minimum_required(VERSION 3.1)

project(test)

set(PROJECT_LIBS "")

find_package(docopt REQUIRED)
include_directories(${DOCOPT_INCLUDE_DIRS})
set(PROJECT_LIBS ${PROJECT_LIBS} ${DOCOPT_LIBRARIES})

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS})

But I have no idea what else to try?

Tom de Geus
  • 5,625
  • 2
  • 33
  • 77
  • Define "fails upon linking". What's the actual error? What's the link command `cmake` is trying to use (`make VERBOSE=1` will print it)? – Stephen Newell Apr 16 '18 at 13:17
  • @StephenNewell Thanks for pointing out the shortcomings in my description. I have edited. The relevant output from `make VERBOSE=1` is `c++ -O3 -DNDEBUG -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/test.dir/main.cpp.o -o test` – Tom de Geus Apr 16 '18 at 13:50

2 Answers2

4

The usage of results of find_package(XXX) depends on the script which is actually used by this command:

  1. FindXXX.cmake.

    This file is either shipped with the project which wants to use it, or with CMake. Usually, such "Find" scripts start with some description about their usage.

  2. XXXConfig.cmake or xxx-config.cmake.

    "Config" scripts are usually installed with the package. Normally, they are generated by CMake using specific CMake commands. You need to consult the package's documentation for use such scripts properly.

If the package doesn't document the usage of its "Config" script, then you may only guess about its usage.

Reading a "Config" script itself could be difficult: CMake includes into it a lot of "sugar", which helps portability and compatibility.

Normally, a "Config" script provides some IMPORTED library target(s), which can be used with target_link_libraries call.

One may scan the project's CMakeLists.txt for a line like

install(TARGETS <targets...> EXPORT ...)

Here <targets...> denotes targets, which can be accessed after find_package() call.

Also scan for a line like

install(EXPORT ...)

if it has NAMESPACE option, then its value prepends all exported targets.

Example:

For docopt package, its CMakeLists.txt contains a line

install(TARGETS docopt EXPORT ${export_name} DESTINATION ${CMAKE_INSTALL_LIBDIR})

thus its docopt target is exported.

As installation of the export file

install(EXPORT ${export_name} DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/docopt")

doesn't contain NAMESPACE option, the export target is accessible with its original name:

find_package(docopt REQUIRED)
...
add_executable(${PROJECT_NAME} main.cpp)
# Use *IMPORTED* 'docopt' target
target_link_libraries(${PROJECT_NAME} docopt)
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
1

After performing a find_package, perhaps you can't make cmake print exactly the variables that the package specifically defined, but perhaps you may appreciate the following code from this SO answer, which gives lists all of the variables defined at a certain point in your cmake files. Here's and example usage:

find_package(FluidSynth REQUIRED)
get_cmake_property(_variableNames VARIABLES)
list (SORT _variableNames)
foreach (_variableName ${_variableNames})
    message(STATUS "${_variableName}=${${_variableName}}")
endforeach()

Which prints many variables including those set by fluidsynth - search for variables beginning with fluidsynth and their values.

Doron Behar
  • 2,606
  • 2
  • 21
  • 24