Include same header file for different libs

Viewed 679

I have a C++ project with the following structure:

CMakeLists.txt
code/
  libClient/
     CMakeLists.txt
     include/
        LibClient/
          lib_client.h
     src/
        lib_client.cpp
  libServer/
     CMakeLists.txt
     include/
        LibServer/
          lib_server.h
     src/
        lib_server.cpp
  libSDK/
     include/
       CMakeLists.txt
       LibSDK/
         lib.h

My root CMakeLists.txt has the following content:

cmake_minimum_required(VERSION 3.0)

project(libExample)


set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

add_subdirectory(code/libClient)
add_subdirectory(code/libServer)
add_subdirectory(code/libSDK)

Now, I would like to build the libs for the server and for the client as .a files. The lib_client.cpp includes the header files with

#include <LibClient/lib_client.h>

Up to here, it is all clear for me, but the header file lib_client.h includes the lib.h which is located at /code/libSDK/include/LibSDK/lib.h with

#ifndef LIBCLIENT_H
#define LIBCLIENT_H

#include <string>
#include <LibSDK/lib.h>

To make this work, I wrote the following content in the CMakelists.txt for the ClientLib:

project(LIBCLIENT)

add_library(
    Client_lib STATIC
    src/lib_client.cpp
        include/LibClient/lib_client.h
    )

target_include_directories(egoClient_lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_include_directories(egoClient_lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../libSDK/include")   ###this line I think should be different.

My question is now, is it possible to avoid this line with the hard coded path? This lib.h is also used (included) in other header files in this project.

The CMakelists.txt for this lib.h has up to now only the content:

cmake_minimum_required(VERSION 3.0)

project(LIBSDK)

I thought about using the CMake find_package() method and write a Find<package>.cmake file, but I do not see any advantages of this because inside this file I also have to write the paths?

Thank you very much in advance.

2 Answers

If Client_lib uses SDK_lib, you'll want to use the following in Client_lib's CMakeLists.txt:

target_link_libraries(Client_lib SDK_lib)

This will tell CMake that Client_lib uses SDK_lib. It will also automatically make the PUBLIC or INTERFACE include paths configured on SDK_lib (with target_include_directories in SDK_lib's CMakeLists.txt) available for Client_lib.

Firstly, if your libClient and libServer depend on libSDK, you should rearrange your top-level CMake to look like the below. Also, based on your example project structure, your add_subdirectory() for the SDK should be code/libSDK/include:

cmake_minimum_required(VERSION 3.0)

project(libExample)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

add_subdirectory(code/libSDK/include)
add_subdirectory(code/libClient)
add_subdirectory(code/libServer)

You want to be sure to gather information about you SDK first, before traversing to the client and server directories.


Secondly, if you do not intend to build libSDK into a library, but simply use its headers, you can just define a new variable in your libSDK CMake file to specify the location of the headers:

project(LIBSDK)

set(SDK_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "My SDK headers directory.")

Now, with a cached variable from the libSDK directory, we can use it in the other CMake files:

project(LIBCLIENT)

add_library(Client_lib STATIC
    src/lib_client.cpp
)

target_include_directories(Client_lib PUBLIC 
    "${CMAKE_CURRENT_SOURCE_DIR}/include"
    "${SDK_INCLUDE_DIRECTORY}"
)

EDIT: As commented, to avoid the use of cache variables, you can also set the include directories variable with PARENT_SCOPE to make the variable accessible from your client and server CMake files:

project(LIBSDK)

set(SDK_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
Related