Rajiv
Rajiv

Reputation: 2649

What is the established way to export a cmake project with external dependencies?

I have a project that I am building with Cmake. It has the following directory structure:

Project
|
 CMakeLists.txt
 src
 |
  MyLib.h
 |
  MyLib.cpp
 |
  CMakeLists.txt
|
 third_party
 |
  abseil-cpp

Since abseil-cpp is a third-party dependency that builds with Cmake, I add it as a subdirectory in my top level CMakeLists.txt. The src folder gets similarly added as a subdirectory in my top level CMakeLists.txt. Something like:

# Contents of Project/CMakeLists.txt
# Usual CMake boiler plate here.
add_subdirectory(third_party/abseil-cpp)
add_subdirectory(src)

My src folder CMakeLists.txt creates a single library that depends on one of the library targets made by abseil-cpp. This dependency is expressed with target_link_library. My CMakeLists.txt file in the src directory looks something like:

# Contents of Project/src/CMakeLists.txt
add_library(MyLib STATIC
MyLib.cpp

MyLib.h)
target_link_library(MyLib absl::base absl::optional)

I was following the Cmake tutorial to see how I could export my project as a Cmake project that other Cmake projects could import and just get MyLib (and it's dependencies) as a Cmake target in their project. The tutorial was pretty clear on how to make this happen and have CMake files created via install that another Cmake project could import via find_package().

This works great as long as every dependency of MyLib is also added to the export set that I make for MyLib. However, since the abseil libraries are being built in another subdirectory by a CMakeLists.txt file that I would rather not touch, it wasn't clear to me how I would export the transitive list of dependencies along with MyLib. In the case of absl::base I tried exporting abseil_base (absl::base is an alias of abseil_base), but Cmake complained that I could not export a target that was not being built in the directory I was trying to export it from. Is there an established way for me to export my library as a Cmake target, with the transitive set of external dependencies (like the abseil libraries) so that an importing Cmake project could add dependencies with a simple target_link_library(external_executable MyLib::MyLib) or similar and it would pull the transitive dependencies of MyLib too?

Upvotes: 1

Views: 1644

Answers (1)

yemre
yemre

Reputation: 738

I suggest that instead of adding it as a subdirectory, install and use it through find_package. Looks like the find_package support was implemented.

In your CMakeLists.txt:

find_package(absl REQUIRED)

target_link_library(MyLib PUBLIC absl::base absl::optional)

Notice the PUBLIC, it is important.

Then define your dependencies using the find_dependency macro in your package configuration file. The tutorial that you were following explains how to do that.

It should look something like this:

@PACKAGE_INIT@

include(CMakeFindDependencyMacro)
find_dependency(absl REQUIRED)

include(${CMAKE_CURRENT_LIST_DIR}/MyLibTargets.cmake)

Upvotes: 5

Related Questions