moonboy
moonboy

Reputation: 1416

CMake add library with subdirectories

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.

Upvotes: 3

Views: 13859

Answers (2)

Nicholas Smith
Nicholas Smith

Reputation: 1005

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.

Upvotes: 2

MuertoExcobito
MuertoExcobito

Reputation: 10049

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).

Upvotes: 1

Related Questions