3

I am trying to generate a config CMake file for a sample project I have. My example is made of two CMake projects: a library, which uses spdlog internally and eigen in its interface and an application, which uses the library. The idea is to learn how to create a Config.cmake file so the application can find the library. This is what I have:

cmake_minimum_required(VERSION 3.16)
project(tutorial-4 CXX)

set(CMAKE_CXX_STANDARD 14)

find_package(Eigen3 REQUIRED)

set(LIBRARY_SOURCES
    Lib/lib.cpp)

set(LIBRARY_HEADERS
    Lib/lib.h)

add_library(smalllib-4
    SHARED
    ${LIBRARY_SOURCES}
    ${LIBRARY_HEADERS}
    )

find_package(spdlog REQUIRED)
find_package(Eigen3 REQUIRED)

target_link_libraries(smalllib-4
    PRIVATE spdlog::spdlog
    PUBLIC Eigen3::Eigen)

target_include_directories(smalllib-4 PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
  $<INSTALL_INTERFACE:include>
)

set_target_properties(smalllib-4 PROPERTIES PUBLIC_HEADER ${LIBRARY_HEADERS})

install(TARGETS smalllib-4
        EXPORT smalllib
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib/static
        PUBLIC_HEADER DESTINATION include/Lib)

install(EXPORT smalllib NAMESPACE smalllib:: DESTINATION share/smalllib)
include(CMakePackageConfigHelpers)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
    ${CMAKE_CURRENT_BINARY_DIR}/smalllibConfig.cmake
    INSTALL_DESTINATION share/smalllib
    )

install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/smalllibConfig.cmake
    DESTINATION share/smalllib
    )

This generates succesfuly a smalllibConfig.cmake, but when I try to do find_package(smalllib REQUIRED), I get the following error:

CMake Error at CMakeLists.txt:10 (add_executable):
  Target "smallapp" links to target "Eigen3::Eigen" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

This happens because in the generated smalllib.cmake, I have the following

add_library(smalllib::smalllib-4 SHARED IMPORTED)

set_target_properties(smalllib::smalllib-4 PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "Eigen3::Eigen"
)

but Eigen3::Eigen is not defined here.

Eigen is a dependency of the library, so adding it to the application doesn't seem to be the correct way to go using modern CMake. What is the generic way to create my config files for CMake?

2 Answers 2

5

The config file for smalllib package should define Eigen3::Eigen target. The most direct approach is to use find_dependency macro for Eigen3 as you use find_package in the CMakeLists.txt for the package itself:

Config.cmake.in (this file is used as a template for the resulted config file):

# Get definition of 'find_dependency' macro
include(CMakeFindDependencyMacro)
# Find Eigen3. This will create 'Eigen3::Eigen' target
find_dependency(Eigen3)

# Include CMake-generated config file for the 'smalllib' target
# which uses 'Eigen3::Eigen' target.
include(${CMAKE_CURRENT_LIST_DIR}/smalllib.cmake)

This way is described in the CMake documentation about the packaging.

Sign up to request clarification or add additional context in comments.

Comments

0

From the description, it seems like the generated smalllibConfig.cmake is missing a call to find_package(Eigen3 REQUIRED) before the targets file gets included.

1 Comment

I was expecting this to happen automatically or that the library target had already all the INTERFACE properties added, so no call to Eigen3::Eigen was needed again. Is this common practice?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.