Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include header files from static library with CMake

I have a problem building a CMake project with a static library. My project strucutre looks like that:

Foo/
|-- CMakeLists.txt
|-- lib/
    |-- CMakeLists.txt
    |-- libA/
        |-- CMakeLists.txt
        |-- libA.cpp
        |-- libA.h
        |-- libAB.h
|-- src/
    |-- CMakeLists.txt
    |-- main.cpp
    |-- srcDirA/
        |-- CMakeLists.txt
        |-- srcA.h
    |-- srcDirB/
        |-- CMakeLists.txt
        |-- srcB.cpp
        |-- srcB.h

And the */CMakeLists.txt look like that:

Foo/CMakeLists.txt:

cmake_minimum_required(VERSION 3.5.1)
project(FOO)

set(CMAKE_CXX_STANDARD 11)

add_subdirectory(lib)
add_subdirectory(src)

Foo/lib/CMakeLists.txt:

add_subdirectory(libA)

Foo/lib/libA/CMakeLists.txt:

add_library (staticLibA STATIC libA.cpp)

Foo/src/CMakeLists.txt:

add_subdirectory(srcDirA)
add_subdirectory(srcDirB)
include_directories(".")

add_executable(foo main.cpp)
target_link_libraries(foo LINK_PUBLIC libA)

Foo/src/srcDirA/CMakeLists.txt is empty

Foo/src/srcDirB/CMakeLists.txt is empty

Now I am trying to include the header from my static library into my main project like this:

Foo/src/main.cpp:

#include "srcDirB/srcB.h"
#include "libA/libA.h"  

int main() {
   //...
   return 0;
}

If I try to build this with CMake, libA is generated but I am getting a fatal error:

libA/libA.h: No such file or directory.

Does anyone know what I am doing wrong? Do I have to create a ProjectConfig.cmake file?

like image 552
Hymir Avatar asked Dec 30 '16 07:12

Hymir


1 Answers

You don't need to create any Config files; these are for importing 3rd-party projects.

Since you're using CMake >= 3.5.1, you can esaily specify usage requirements for your libraries. Usage requirements are things like flags or include directories which clients need to build with the library.

So in Foo/lib/libA/CMakeLists.txt:, you'll do this:

add_library (staticLibA STATIC libA.cpp)
target_include_directories(staticLibA INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/..)

Or, if you want the same include directory to apply to libA itself (which is likely), use PUBLIC instead of INTERFACE.

That's all you really need to do. However, given the modern CMake you're using, you should replace your use of the legacy keyword LINK_PUBLIC with its modern equivalent PUBLIC.

Also, since you mention both CMakeLists in .../srcDir* are empty, why have them there in the first place? You can easily get rid of both them and the related add_subdirectory calls.

like image 176
Angew is no longer proud of SO Avatar answered Sep 22 '22 04:09

Angew is no longer proud of SO