0

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?

Dmitry
  • 160
  • 9

2 Answers2

1
  • 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.

The Dreams Wind
  • 8,416
  • 2
  • 19
  • 49
  • 1. I still get `api_types.h: No such file or directory` 2. Doesn't this part link the library? `add_library(api SHARED IMPORTED) set_property(TARGET api PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/lib/libapi.so")` – Dmitry Oct 11 '22 at 11:53
  • @Dmitry you link library with `target_link_library`, while `add_library` just adds the library target (not linked to anything). For the first issue i can't see why exactly this could be happening, but let me quickly implement this solution locally and check if it works – The Dreams Wind Oct 11 '22 at 11:58
  • @Dmitry my bad, i just used `include` instead of `dep` folder. Just ensure that `target_include_directories` refers to actual folder in your project. Now it should be good – The Dreams Wind Oct 11 '22 at 12:04
  • Still don't get it =( Can this part be wrong? `#include ` – Dmitry Oct 11 '22 at 13:05
  • Found the typo. Stupid me >. – Dmitry Oct 11 '22 at 13:35
0

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)
GeorgUr
  • 61
  • 6