user3624760
user3624760

Reputation:

CMake transitive dependency is not found via find_package()

I have static library Foo, static library Bar that depends on Foo and executable Baz that depends on Bar.

Relevant sections from Foo CMakeLists.txt:

# Specifying files to copy during "make install" command.
install(TARGETS Foo EXPORT FooConfig
    INCLUDES DESTINATION include
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)

# Specifying config file that will be used to find a library using find_package().
install(EXPORT FooConfig
    FILE FooConfig.cmake
    NAMESPACE Foo::
    DESTINATION lib/cmake/Foo)
export(TARGETS Foo
    NAMESPACE Foo::
    FILE FooConfig.cmake)

Relevant sections from Bar CMakeLists.txt:

# Specifying libraries that are required for build.
find_package(Foo REQUIRED)

# Specifying libraries to link to for the users of the library.
target_link_libraries(Bar PUBLIC Foo::Foo)

# Specifying files to copy during "make install" command.
install(TARGETS Bar EXPORT BarConfig
    INCLUDES DESTINATION include
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)

# Specifying config file that will be used to find a library using find_package().
install(EXPORT BarConfig
    FILE BarConfig.cmake
    NAMESPACE Bar::
    DESTINATION lib/cmake/Bar)
export(TARGETS Bar
    NAMESPACE Bar::
    FILE BarConfig.cmake)

And finally Baz CmakeLists.txt:

find_package(Bar REQUIRED)

target_link_libraries(Baz PRIVATE Bar::Bar)

Now when building Baz I get:

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

So build finds Bar and correctly determines that it depends on Foo but can't find Foo. I have another test project that directly depends on Foo and it builds fine. How to fix this?

Upvotes: 12

Views: 2890

Answers (1)

user3624760
user3624760

Reputation:

Unfortunately, BarConfig.cmake generated like this does not handle finding dependencies, I had to modify Bar CMakeLists.txt to this:

# Specifying files to copy during "make install" command.
install(TARGETS Bar EXPORT BarTargets
    INCLUDES DESTINATION include
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)
install(FILES CMake/BarConfig.cmake DESTINATION lib/cmake/Bar)

# Specifying config file that will be used to find a library using find_package().
install(EXPORT BarTargets
    FILE BarTargets.cmake
    NAMESPACE Bar::
    DESTINATION lib/cmake/Bar)
export(TARGETS Bar
    NAMESPACE Bar::
    FILE BarTargets.cmake)

Then I created a file CMake/BarConfig.cmake with this:

include("${CMAKE_CURRENT_LIST_DIR}/BarTargets.cmake")

find_package(Foo REQUIRED)

Now this BarConfig.cmake gets installed globally and calls find_package that finds Foo.

Upvotes: 12

Related Questions