3

TL;DR

Using CMake, how can I include subdirectories into a library such that they can be included without referencing the directories they reside?

End TL;DR

In attempt to be brief and speak in higher level ideas of what and how, I have removed everything that I consider to be unnecessary details. I will make edits if need be. As such, this is a brief synopsis of my project structure.

ParentDir
--src
----source.cpp
----source.h
----entities_dir
------entity.cpp
------entity.h
------CMakeLists.txt
----CMakeLists.txt
--CMakeLists.txt
--main.cpp

as it currently stands, I have a library defined by the CMakeLists in the src directory. As such, I can include src files in main by #include as apposed to #include "src/file.h" I would like to be able to do the same for my headers that exist within the subdirectories of src.

CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
project(Project) 

add_executable(Project ${SOURCE_FILES} main.cpp)
include_directories(src)
add_subdirectory(src)
target_link_libraries(Project Library) # Engine Libraries

src/CMakeLists.txt

file(GLOB SOURCE_FILES *.cpp)
file(GLOB HEADER_FILES *.h)

add_library(Library STATIC ${SOURCE_FILES} ${HEADER_FILES})

main.cpp

#include <source.h> // this works
#include <entity.h> // this does not work but I want it to
#include <entities/entity.h> // this works but I don't want this
int main() {}

I am not sure how to do this exactly. I have tried to GLOB_RECURSE, add_subdirectory(entities), etc. I have also tried creating a library called Entities inside the src/entities/CMakeLists.txt and linking that with link_libraries. None of these have been successful. What is the proper way to accomplish this, because I think I am probably approaching this completely wrong.

moonboy
  • 1,296
  • 4
  • 16
  • 29
  • 3
    You need that path in your compilers header search path, which is achieved with include_directories() call. You can amend your existing include_directories(src) call to be include_directories(src src/entities). Im not aware of a way to make that recursive, nor would I recommend it. – Nicholas Smith Feb 19 '17 at 00:22
  • so that works. It seems to be challenging my understanding of how you are supposed to use cmake though. I have seen it commonplace to have cmakelists in each directory. Since, in this case, the src cmakelists is creating the actual library, shouldn't the parent cmake only need to reference the src cmake and not need knowledge of the src subdirs? – moonboy Feb 19 '17 at 00:35
  • @qexyn if you want to leave an answer I will accept it. – moonboy Mar 06 '17 at 23:01

2 Answers2

2

You need that path in your compilers header search path, which is achieved with include_directories() call. You can amend your existing include_directories(src) call to be:

include_directories(src src/entities)

Also, this SO post is related and worth reading: Recursive CMake search for header and source files. There is an excerpt there from the CMake website itself recommending against the usage of file(GLOB ...), which lends to recommending against recursive solutions in general. As a heavy user of CMake, I agree with the arguments made against it.

Community
  • 1
  • 1
Nicholas Smith
  • 975
  • 7
  • 18
1

You just need to add:

include_directories(${CMAKE_CURRENT_LIST_DIR})

In each CMakeLists.txt in your your hierarchy.

CMake in itself doesn't compile your project, it only calls your toolchain and passes parameters to it, and your toolchain doesn't 'know' that it is being called by CMake, or the structure of your project. As such, you need to tell the toolchain where to locate include files.

While it is commonplace to have a CMakeLists.txt in every subdirectory, this is by no means a requirement. The CMakeLists.txt in your src directory could contain all instructions necessary to generate a build. Generally, CMakeLists.txt are put at each level to make the structure easier to manage, eg. each directory only needs to know what it needs to do (presumably, with the files in that directory).

MuertoExcobito
  • 9,741
  • 2
  • 37
  • 78
  • This unfortunately did not work. Following the advice of a comment, I did add "include_directories(src/entities)" which worked, however I am really looking for an answer in which i can just "include_directories(src)" and the CMakeLists.txt in the src directory handles all the sub directories. – moonboy Feb 28 '17 at 17:55