I have a C++ project where I've used directories as more of an organizational element -- the way one might use packages in Java or directories in PHP. Directories are not intended to be self-sufficient elements, but rather just a way of organizing the whole of the project and keeping me from being overwhelmed by sources. How can I construct my CMakeLists.txt files to deal with this? Making the directories libraries doesn't seem to fit here, since they are all interdependent and not intended to be used that way.
As a related issue, most of the examples I've seen of multiple subdirectories in CMake (and there aren't very many of those) have ignored or glossed over the issue of setting include_directories
, which is something I've been having trouble with. Short of combing my source files to determine which file depends on which and in what directory, is there anyway to just set all directories under /src/
as potential include directories and let CMake work out which ones are actually dependent?
Here's an example structure:
--src --top1 --mid1 --bot1 --src1.cpp --hdr1.h --bot2 --src2.cpp --hdr2.h --mid2 --bot3 --src3.cpp --src4.cpp --hdr3.h --top2 --mid3 --src5.cpp --hdr4.h
So on and so forth. How can I structure my CMakeLists.txt
files to handle this sort of structure?
Though @sakra gave a good answer to this question, I believe it is more proper to approach it more in depth.
We want to separate our code into modules and libraries for many reasons. Like code encapsulation, re usability, easier debugging etc. This idea would propagate in compiling process too.
In other word, we want to divide the compilation process into little compilation steps, each belong to one module. So every module must have its own compilation procedure. This is why we use one CMakeLists.txt
file per directory. Hence every directory would have its own compilation commands and there would be one master CMakeLists.txt
file in the root directory of your project.
Here is an example. Consider the following structure of a project:
src/ | - main.cpp | _sum/ | - sum.h | - sum.cpp
We would have one CmakeLists.txt
Per directory. First directory is the root directory of the project which src/
folder is in it. here is content for that file:
cmake_minimum_required(VERSION 3.4) project(multi_file) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "-Wall") add_subdirectory(src)
Next CMakeLists.txt
would located in src/
directory:
add_subdirectory("sum") add_executable(out main.cpp) target_link_libraries(out sum)
And the last one will be in the sum/
directory:
add_library(sum SHARED sum.cpp)
I hope this helps. I created a github repository in case you feel you need to see the code or you need further explanation.
Since the directory structure in your project is just there to keep your files organized, one approach is to have a CMakeLists.txt
that automatically finds all sources files in the src
directory and also adds all directories as include directories that have a header file in them. The following CMake file may serve as a starting point:
cmake_minimum_required(VERSION 3.12) project (Foo) file (GLOB_RECURSE Foo_SOURCES CONFIGURE_DEPENDS "src/*.cpp") file (GLOB_RECURSE Foo_HEADERS CONFIGURE_DEPENDS "src/*.h") set (Foo_INCLUDE_DIRS "") foreach (_headerFile ${Foo_HEADERS}) get_filename_component(_dir ${_headerFile} PATH) list (APPEND Foo_INCLUDE_DIRS ${_dir}) endforeach() list (REMOVE_DUPLICATES Foo_INCLUDE_DIRS) add_executable(FooExe ${Foo_SOURCES}) target_include_directories(FooExe PRIVATE ${Foo_INCLUDE_DIRS})
The two file(GLOB_RECURSE ...
commands determine the set of source and header files. The foreach
loop computes the set of include directories from the list of all header files. The CONFIGURE_DEPENDS
flags tells CMake to re-run the glob command at build time.
One drawback with computing the set of source files is that CMake will not automatically detect when new files are added to your source tree. You manually have to re-create your build files then.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With