Dmitry
Dmitry

Reputation: 316

cmake - add .so library with it's .h headers

I have a project with structure like this:

project/
├─ src/
│  ├─ main.cpp
│  ├─ CMakeLists.txt
├─ lib/
│  ├─ libapi.so
├─ CMakeLists.txt
├─ dep/
│  ├─ api/
│  │  ├─ api_types.h

In the main CMakeLists I have:

add_subdirectory(dep)
add_executable("my_${PROJECT_NAME}")
add_subdirectory(src)

And in CMakeLists inside src folder:

target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_library(api SHARED IMPORTED)
set_property(TARGET api PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/lib/libapi.so")
target_sources("my_${PROJECT_NAME}" PRIVATE main.cpp)

In main.cpp I do #include <api_types.h> but I get this error during compile: api_types.h: No such file or directory

How can I fix it?

Upvotes: 0

Views: 111

Answers (2)

Aleksandr Medvedev
Aleksandr Medvedev

Reputation: 9008

  • First - add_subdirectory in fact just looks for CMakeLists.txt in the specified directory to apply the sub-set of the rules to the parent project. If the specified folder doesn't contain any CMakeLists.txt this command does nothing (i.e. the command add_subdirectory(dep)).

  • Second - target_include_directories expects a target object to link against (not the project name). Assuming ${PROJECT_NAME} is not a name of any of your targets (and the code given in the question reveals only two targets my_${PROJECT_NAME} and api) the command target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) does nothing sensible.

  • Last - you don't specify path to your actual headers anywhere. CMAKE_CURRENT_SOURCE_DIR refers to the current folder CMakeLists.txt is located in. You should specify path to the folder the headers are located in.

Putting all the said info together, the desired content for the top-level CMakeLists.txt should be something like that:

cmake_minimum_required(VERSION 3.20)
set(PROJECT_NAME Hello)

project(${PROJECT_NAME})

add_executable(my_${PROJECT_NAME})
add_subdirectory(src)

And for src's file it's apparently something like that:

target_include_directories(my_${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/dep/api)

target_sources(my_${PROJECT_NAME} PRIVATE main.cpp)

This solution, however, doesn't resolve another mistake in your code - the CMake files you provided don't link the library itself to the executable target. However this is not the question asked, and with respect to the members of the community, I suggest referring to answers to another related question here.

Upvotes: 1

GeorgUr
GeorgUr

Reputation: 91

target_include_directories requires your executable as target, in this case my_${PROJECT_NAME}.

You can try

target_include_directories(my_${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

As alternative I would recommend following structure

project/
├─ src/
│  ├─ main.cpp
├─ lib/
│  ├─ libapi.so
├─ CMakeLists.txt
├─ include/
│  ├─ api/
│  │  ├─ api_types.h

with following CMakeList.txt

add_executable(my_${PROJECT_NAME} src/main.cpp)
target_include_directories(my_${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
link_directories(${CMAKE_SOURCE_DIR}/lib)
target_link_libraries(my_${PROJECT_NAME} libapi)

Upvotes: 0

Related Questions