Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake library dependencies

Tags:

c++

cmake

This may be a tad hard to explain in full. I have setup a directory structure for a series of C++ libraries I am writing. I intend to use CMake to handle building these libraries. For the most part these libraries are completely separate "subsystems" but in the odd places one library needs access to the header file contained within another. Here is my directory structure.

base
 ├─ cmake
 ├─ docs
 ├─ examples
 └─ sources
    ├─ libA
    │   ├─ include
    │   │   └─ libA
    │   │       ├─ core.h
    │   │       └─ *.h
    │   ├─ source
    │   │   └─*.cpp
    └─ libB
        ├─ include
        │   └─ libB
        │       ├─ message.h
        │       └─ *.h
        └─ source
            └─ *.cpp

There are CMakeLists.txt files in a few places. The main one is within the root directory base which sets up a bunch of variables and options and lastly calls add_subdirectory(sources). Within sources the CMakeLists.txt file simply calls:

add_subdirectory(libA)
add_subdirectory(libB)

Lastly there are CMakeLists.txt files in both the libA and libB directories. These are both largely the same except for the target name. An example of one of these files is:

set(target libA)

# Sources
set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/${target}")
set(source_path  "${CMAKE_CURRENT_SOURCE_DIR}/source")

# Add include directories
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")

# Set the source files to compile
file(GLOB_RECURSE sources ${source_path}/**/*.cpp)

# Build library
add_library(${target} ${sources})

Now separately both of these libraries can be built without issue but I need to be able to include a header from libA in a source file within libB

// base/sources/libB/source/message.cpp

#include <ctime>
#include <iostream>

#include <libA/core.h>
#include <libB/message.h>

However when I build this I get the following error:

fatal error: 'libA/core.h' file not found

I have tried using target_link_libraries and target_include_directories without any luck. Clearly I am using these wrong or simply don't understand what each of these do.

like image 224
tomasbasham Avatar asked Feb 10 '17 18:02

tomasbasham


People also ask

Can CMake install dependencies?

Any complex software will have its dependencies – be it system API calls or other libraries calls either statically or dynamically linked to it. As a build system generator CMake will help you manage these dependencies in the most natural way possible.

What does add library to CMake?

add_library(<name> <type> IMPORTED [GLOBAL]) Creates an IMPORTED library target called <name> . No rules are generated to build it, and the IMPORTED target property is True . The target name has scope in the directory in which it is created and below, but the GLOBAL option extends visibility.

What does Add_subdirectory do in CMake?

Add a subdirectory to the build. Adds a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.


2 Answers

Since your library libB needs a header from libA to compile, let's say libA is a dependency of libB. Fortunately, CMake is very clever at handling dependencies, so your job is pretty easy:

libA

Instead of

# Add include directories
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")

add to the end

target_include_directories(${target} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")

This will tell CMake that it must also include the headers for libA to the other projects that need it.

libB

Just tell CMake that libB needs libA:

target_link_libraries(${target} libA)

Note that this doesn't relate directly to the linking step when you compile. For libraries it mainly tells that there is this dependency, and in this case it will automatically add the paths for the headers automatically.

like image 153
oLen Avatar answered Oct 21 '22 22:10

oLen


You can add to your CMakeLists.txt for libB, another include directory:

include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../libA/include")
like image 32
Rama Avatar answered Oct 21 '22 21:10

Rama