CMake and dependencies

1.4k views Asked by At

I have the following directory structure and library dependencies:

./lib-a
./lib-b (depending on lib-a)

Each directory contains a CMakeLists.txt file for generating its own library. I am using an out-of-source building policy.

In order to say that lib-b depends on lib-a, I have put the command add_subdirectory(../lib-a lib-a) in ./lib-b/CMakeLists.txt, according to what is taught by the official CMake tutorial. This way I obtain that a subdirectory lib-a is created in ./lib-b/build dir.

This is not the behaviour I desire. What I would like to obtain is CMake making reference to lib-a in generating lib-b and, if lib-a has not been already generated, CMake should generate it inside ./lib-a/build by using the CMakeLists.txt of lib-a (in a behaviour similar to the one of the make tool when dealing with dependencies).

I would also like to add that I am not using a root CMakeLists.txt in my example, but what I would like to have is the lib-b/CMakeLists.txt declaring the dependency on lib-a, thus making lib-a to be compiled, if not already, by using its own lib-a/CMakeLists.txt.

Here is the dirs structure and their contents:

lib-a/
    CMakeLists.txt (for compiling lib-a)
    src/
        test.cpp
    include/
        test.hpp

lib-b/
   main.cpp
   CMakeLists.txt (for compiling lib-b; here is the point where I would like to make reference to lib-a, that I need for the generation of lib-b)

lib-b/main.cpp contains also an include of test.hpp of lib-a, because it is using a function of lib-a. This should be taken into consideration in the specification of lib-b/CMakeLists.txt.

What should the content of the two lib-a/CMakeLists.txt and lib-b/CMakeLists.txt files be?

1

There are 1 answers

6
IdeaHat On

I think you misunderstand the tutorial. The thing that links the libraries together is target_link_library(lib_b lib_a). If the name of the dependency is a library that is part of the build, CMake will magically make the dependencies work. It has nothing to do with subdirectories. In fact, if I have the following directory structure:

./
./a.hpp
./a.cpp
./b.hpp
./b.cpp
./CMakeLists.txt

The following will set the dependencies just fine:

PROJECT(lib_a)
ADD_LIBRARY(lib_a a.hpp a.cpp)
PROJECT(lib_b)
ADD_LIBRARY(lib_b b.hpp b.cpp)
TARGET_LINK_LIBRARIES(lib_b lib_a)

This will work across subdirectory projects as well:

 ./
 ./CMakeLists.txt
 ./lib_a/CMakeLists.txt
 ./lib_a/a.hpp
 ./lib_a/a.cpp
 ./lib_b/CMakeLists.txt
 ./lib_b/b.hpp
 ./lib_b/b.cpp

And the list files:

 # ./CMakeLists.txt
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 ADD_SUBDIRECTORY(lib_a)
 ADD_SUBDIRECTORY(lib_b)

 # ./lib_a/CMakeLists.txt
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 PROJECT(lib_a)
 ADD_LIBRARY(lib_a a.hpp a.cpp)

 # ./lib_b/CMakeLists.txt
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 PROJECT(lib_b)
 INCLUDE_DIRECTORIES(${lib_a_SOURCE_DIR})
 ADD_LIBRARY(lib_b b.hpp b.cpp)
 TARGET_LINK_LIBRARIES(lib_b lib_a)