Whenever I wanted to include a directory that was located outside of my project with Clion I would use the -I somedir flag. This time however, what I want to do is to have a hierarchy like this:
/project
CMakeLists.txt
/src
/Graph
Graph.h
Graph.cpp
/Dijkstra
Dijkstra.h
Dijstra.cpp
I want my code in a /src directory. And not only that, but also, for example, inside the file Dijkstra.h I want to include the Graph.h like this: #include "Graph/Graph.h and not like this: #include "../Graph/Graph.h.
If I only add an -I src flag, then if I am inside the Dijkstra.h file and I wanted to include Graph.h, I would have to write #include "../Graph/Graph.h, which is not what I want.
So I tried to also add INCLUDE_DIRECTORIES(src). That fixed the problem above, however when tried to compiled, I got a linker error undefined reference to....
So I tried adding the files one by one like this:
set(SOURCE_FILES
src/Dijkstra/Dijkstra.h
src/Dijkstra/Dijkstra.cpp
src/Graph/Graph.h
src/Graph/Graph.cpp)
add_executable(someprojectname ${SOURCE_FILES})
and that brought back the previous problem, where I had to include the files like this: #include "../Graph/Graph.h".
How can I do this properly to get the behavior I want ?
Command INCLUDE_DIRECTORIES doesn't add any source file for compile!
Instead, this command defines directories for search header files.
You need to list all source files in add_executable() call in any case:
include_directories(src)
set(SOURCE_FILES
src/Dijkstra/Dijkstra.cpp
src/Graph/Graph.cpp)
add_executable(someprojectname ${SOURCE_FILES})
UPDATE: #Tsyvarev's answer is correct. I've edited this answer to remove the incorrect part and keep the comments relating to target_include_directories(), but it should be viewed as additional to Tsyvarev's answer.
INCLUDE_DIRECTORIES(src) will make the src directory get added as a search path to all targets defined from that point on. It does not add sources to any targets. The search path will be relative to the current source directory and CMake will adjust it as appropriate when descending into subdirectories via add_subdirectory(). While this is fine if that's what you want, as the project gets bigger and more complicated, you may find you would prefer to apply the include path settings to just some targets. For that, use target_include_directories() instead:
target_include_directories(someprojectname "${CMAKE_CURRENT_SOURCE_DIR}/src")
This will have the same effect, but it restricts the use of the added include path to just the someprojectname target. If you later define some other target which doesn't need the include path, it won't be added. This can help prevent situations like unexpected files being picked up if you have deep directory hierarchies and you re-use directory names in different places, for example).
The target_include_directories() command has additional benefits when applied to library targets because CMake has the ability to carry the include path through to anything you link against that library too. Doesn't sound like much, but for large projects which define and link many libraries, it can be a huge help. There are other target-specific commands which have similar benefits too. This article may give you a bit of a feel for what is possible (disclaimer: I wrote the article). It is more focused on target_sources(), but the discussion around carrying dependencies through to other targets may be useful.
Related
I am trying to integrate spdlog, a header only logging library into a C++ project but I am having trouble getting CMake to recognise the include paths properly. I am using the latest CLion with CMake 3.10.2 on Ubuntu 18.04.
My project structure looks like this:
Project Dir
|- libs
| |- spdlog #this is the include directory taken straight from GitHub
|
|- src
| |-...
|- CMakeLists.txt
In the CMakeLists.txt file I define the include directory:
include_directories("libs/")
Now when I attempt to write #include <spdlog/spdlog.h> in a header file located in src/ CLion complains that it cannot find spdlog.h even though I have checked and the file is definitely in the spdlog folder. Using quotation marks instead of angled brackets in the include statement does not fix the problem however using the path relative to the file (e.g. ../libs/spdlog/spdlog.h) works as it should. What is more confusing to me is that in the source file corresponding to the header I can include the file no problem.
I haven't been able to find anything like this issue anywhere and I'm struggling to understand what is causing CMake or CLion to behave like this.
EDIT: As per Matthieu Brucher's suggestion I have tried using fully qualified paths to the include folder but it still does not work. The problem seems to be that folders seem to not be recognised in headers, as they work in source files.
EDIT2: Here is the entire CMakeLists.txt I am using. It is nested into a different directory than the top level CMakeLists.txt for the entire project as this was the only solution I have found online to get something akin to VS's multiple projects in a solution in CLion. However since all paths are relative I don't think this would be a problem. I also know that spdlog is a C++11 library but I will need some C++14 features elsewhere in the near future.
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(TokenEngine VERSION 0.0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(SOURCE_FILES src/Application.cpp src/Application.hpp src/EntryPoint.hpp src/Logger.cpp src/Logger.hpp)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/libs/")
add_library(TokenEngine SHARED ${SOURCE_FILES})
#Expose the public API of the engine to any project that might use it
target_include_directories(TokenEngine PUBLIC include)
EDIT3: When I attempted to recreate the error to show the full message given somehow the it was gone, being replaced by a different one totally unrelated to CMake...
You may want to use fully qualified paths:
include_directories(${CMAKE_SOURCE_DIR}/libs/)
You also have to add the include folder to the include paths to be able to include via #include <spdlog/spdlog.h>. This should look like
include_directories(${CMAKE_SOURCE_DIR}/libs)
But I prefer using
target_include_directories(yourTarget PUBLIC ${CMAKE_SOURCE_DIR}/libs)
where yourTarget is the target where you want to use spdlog. Like that you will have the include directories also available if you are going to link your yourTarget to something else. If you need spdlog just in yourTargets cpp files you can change the PUBLIC to PRIVATE. See cmake doc.
I just started getting into CMake with C++ and was wondering how other programmers avoid having to do "../include" in all their CMakeFiles.txt.
One example is here: https://github.com/clab/cnn/blob/master/examples/CMakeLists.txt
They create an executable for each example without having to call INCLUDE_DIRECTORIES(...).
I tried adding the headers when calling ADD_LIBRARY(...), but that didn't seem to work.
Example:
tl/src/CMakeLists.txt:
SET(SRCS "x1.cpp" "x2.cpp")
SET(HDRS "../include/tl/x1.h" "../include/tl/x2.h")
INCLUDE_DIRECTORIES("../include")
ADD_LIBRARY(test_lib ${SRCS} ${HDRS})
tl/CMakeLists.txt:
PROJECT(TEST_LIB VERSION 0.1)
ADD_SUBDIRECTORY("src")
tl/examples/CMakeLists.txt:
INCLUDE_DIRECTORIES("../include")
ADD_EXECUTABLE(e1 e1.cpp)
TARGET_LINK_LIBRARIES(e1 test_lib)
Edit: I believe that INCLUDE_DIRECTORIES(...) is only necessary one per each directory throughout the tree.
Just add the INCLUDE_DIRECTORIES command at the top level. No need to explicitly add included files then.
tl/CMakeLists.txt:
PROJECT(TEST_LIB VERSION 0.1)
INCLUDE_DIRECTORIES("include")
ADD_SUBDIRECTORY("src")
ADD_SUBDIRECTORY("examples")
tl/src/CMakeLists.txt:
ADD_LIBRARY(test_lib "x1.cpp" "x2.cpp")
tl/examples/CMakeLists.txt:
ADD_EXECUTABLE(e1 e1.cpp)
TARGET_LINK_LIBRARIES(e1 test_lib)
How about this? tl/CMakeLists.txt
SET(SRCS "x1.cpp" "x2.cpp")
SET(HDRS "../include/tl/x1.h" "../include/tl/x2.h")
INCLUDE_DIRECTORIES("${CMAKE_PROJECT_DIR}/include")
ADD_LIBRARY(test_lib ${SRCS} ${HDRS})
You do not need to add headers to ADD_LIBRARY or ADD_EXECUTABLE if you want to compile your programs and libs. Only source files "cpp,c,cxx,..." are required because through the include macro #include you tell the compiler where it finds the header files.
With INCLUDE_DIRECTORIES(...) you only add a search path to the compiler where to look for headers. If you have your headers in the same directory as your source you don't need another search path. Also subpaths with include macro like this #include "../../include" is possible. So it really depends on the structure of your source files. Also remember, compiler settings setups know where some of the system headers are found. That is why you also do not need to define them.
And last but not least there are cmake scripts and pkg search files where adding paths to specific libraries is done automatically.
This is how I did it in a project of mine:
file(GLOB_RECURSE SRC
engine/*.cpp
platfoorm/*.cpp
)
file(GLOB_RECURSE INCLUDES
engine/*.h
platform/*.h
)
This generate an internal "hardcoded" list of files that the generated makefil will use, so if you add a new source file you will need to re-run cmake.
Of course you can change and add paths, the one in the example are the one I used in my project.
I am looking for a way to tell CMake to make an include directory appear under another name to the compiler.
Let's say I have a project that needs code from a foreign library. This code resides in a directory foreignLib-1.5.0_build123456 in my project's root directory. From time to time I will want to update this library and in this process change the library directory name.
I want to reference this directory as foreignLib in my C++ source files. I want to be able to write
#include "foreignLib/include/lib.h"
and CMake should tell my compiler to translate this to
#include "foreignLib-1.5.0_build123456/include/lib.h"
Now I am wondering:
Does a feature like this exist in CMake?
If yes, how do I use it?
If yes, which compilers are supported?
I'd probably just copy the entire include directory into my build tree and make that available.
A decent way of doing that is to use file(GLOB_RECURSE ...) to gather a list of files in the includes folder, then use configure_file(<input> <output> COPYONLY) to copy them to the build tree.
By using configure_file, the files in the build tree are only replaced as required. This means that re-running CMake won't automatically make these files appear out-of-date to the build tool, hence avoiding an unnecessary recompilation.
set(ForeignLibName foreignLib-1.5.0_build123456)
set(ForeignLibRoot ${CMAKE_SOURCE_DIR}/${ForeignLibName})
file(GLOB_RECURSE IncludeFiles RELATIVE ${ForeignLibRoot} ${ForeignLibRoot}/*)
foreach(IncludeFile ${IncludeFiles})
configure_file(${ForeignLibRoot}/${IncludeFile}
${CMAKE_BINARY_DIR}/${ForeignLibName}/foreignLib/${IncludeFile}
COPYONLY)
endforeach()
include_directories(${CMAKE_BINARY_DIR}/${ForeignLibName})
This should allow you to do:
#include "foreignLib/include/lib.h"
When you update the foreign library, you'd have to ensure that you also updated the CMakeLists.txt so that CMake re-runs the next time you go to build. Updating the CMakeLists.txt should only involve changing the single line set(ForeignLibName ...).
You could have a look at Cmake's configure_file: Rename your source file into yourfile.cpp.in and do
#include ${DIR_TO_LIB}/include/xy.h
In your CMakeLists, you set the variable DIR_TO_LIB somehow (by parsing command line or something) and issue
configure_file(yourfile.cpp.in, yourfile.cpp)
This will yield yourfile.cpp with the correct path set.
This is probably not exactly what you intended, but I think it would work.
As part of the build process generate an include file at a well known location (later on called "boilerplate/foreignLib_lib.h") with the real include path.
your code file:
#include "boilerplate/foreignLib_lib.h"
boilerplate/foreignLib_lib.h:
#include "foreignLib-1.5.0_build123456/include/lib.h"
Use CMake's include_directories statement or add an -I switch to the *_CXX_FLAGS to add the current foreignLib path to your include path.
I have been struggling with this for quite a while, and my adventures with cmake have only resulted in hackish solutions that I am pretty sure are not correct.
I created a library that consists of several files, as follows:
-libfolder
-codepart1folder
-CMakeLists.txt
-codepart1.cpp
-codepart1.hpp
-codepart2folder
-codepart3folder
-lib.cpp
-lib.hpp
-CMakeLists.txt
I wrote a CMakeLists file to compile the library (after some experimentation), and I can generate a lib.a file. Now I would like to include this code as a library in other projects, and access it through the interface in lib.hpp. What is the best way to do this, in terms of directory structure, and what I need to put into CMakeLists.txt in my root project?
My current attempt has been to add -libfolder as a subfolder to my current project, and add the commands:
include_directories(${PROJECT_SOURCE_DIR}/libfolder)
link_directories(${PROJECT_BINARY_DIR}/libfolder)
add_subdirectory(libfolder)
target_link_libraries(project lib)
When I run make, the library compiles fine, but when project.cpp compiles, it complains that it cannot find codepart1.hpp (which is included in lib.hpp, included from project.cpp).
I suspect that this is the wrong way about doing this, but I cannot wade through the CMake documentation and find a good tutorial on setting up projects like this. Please help, CMake gurus!
The clean way to import one CMake project into another is via the find_package command. The package declaration is done by using the export command. An advantage of using find_package is that it eliminates the need to hard-code paths to the package's files.
Regarding the missing hpp file, you didn't include codepart1folder, so it's not on the include path.
Ok, so after consulting a coworker of mine who is a CMake guru, it seems CMake does not have support for what I am trying to do, leaving one with 3 options:
Add all of the dependencies to the parent projects CMakeLists.txt - not very clean, but it will get the thing to work. You'll have to do this for every project you add the code to, and go back and fix things if your library changes.
clean up your library headers. This is done through some compiler hackery. The idea is to forward-declare every class, and use only pointers or boost::shared_ptr, and then include the dependencies only in the cpp file. That way you can build the cpp file using all the findpackage stuff, and you get the bonus of being able to use the lib by only including the header and linking to the library.
Look into build systems. Having portable code and fast code compilation with complex dependencies is not a solved problem! From my investigations it turned out to be quite complicated. I ended up adopting my coworkers build system which he created himself in cmake, using things he picked up from Google.
Looking at your post you don't seem to add 'codepart1folder' to the includes anywhere. How are you including codepart1.hpp as:
#include <codepart1.hpp>
#include "codepart1folder/codepart1.hpp"
I don't think there is a standard accepted way to structure cmake projects. I've looked at a bunch of cmake repos and they tend to have differences. Personally I do the following:
-project
CMakeLists.txt
-build
-cmake
OptionalCmakeModule.cmake
-src
-Main
Main.cpp
Main.hpp
-DataStructs
SomeTree.hpp
SomeObject.hpp
-Debug
Debug.hpp
-UI
Window.hpp
Window.cpp
Basically that dumps all the source code into 1 directory, then you perform an out of source build with: 'mkdir build && cd build && cmake .. && make' in the projects root folder.
If you have separate libs as part of your project, then you might want a separate libs directory with another subfolder for your specific lib.
I have some of my repos on: https://github.com/dcbishop/ if you want to look at the CMakeLists.txt files.
The main problems with my project structure are that I use the FILE_GLOB which is apparently the 'wrong' way to do things (if you add files after running 'cmake ..' then they won't be picked up hen you do a 'make'). I haven't figured out what the 'right' way to do it is (from what I can see it involves keeping a separate list of files) I also only use 1 CMakeLists.txt file.
Some projects also choose to separate their cpp and hpp files into separate directories. So you would have an include and src folders (at least for the hpp files that are intended to be used externally). I think that would mainly be for projects that are mainly large libraries. Would also make installing header files much easier.
You are probably missing
include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder)
In such a case you might want to set( CMAKE_INCLUDE_CURRENT_DIR on) to add all folders to the include directory path variable.
Check cmake's output on the command line whether the correct include folders are set or not. Additionally you can always use message() as "print debugging" for cmake variables.
In case of include directories however you need to read the directory property to see what is actually in the include directories.
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("inc_dirs = ${inc_dirs}")
I hope this helps you figuring out what is missing.
Edit
I just saw your comment about added codepart1folder in the libfolder. It is only available in the libfolder's include_directory path and not propagated to the root folder.
Since the include codepart1.hpp is present in the lib.hpp however you need to have it also available in the project path otherwise you will get missing declaration errors when you build your project.
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?
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.
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.
I'm not an expert on CMake but since there are no other answers I'll take a look at the documentaton and give it a go. Organizing source and include files in different directories is pretty much the norm.
It looks like CMake allows you to give a list of include directories:
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories
So something like:
include_directories("src/top1/mid1/bot1" "src/top1/mid1/bot2/" ... )
These are passed to the compiler so it can find the header files and will be passed for each of the source files. So any of your source files should be able to include any of the header files (which I think is what you're asking for).
Similar to that you should be able to list all your source files in the add_executable command:
add_executable(name "src/top1/mid1/bot1/src1.cpp" "src/top1/id1/bot2/src2.cpp" ...)
So this would be a naive way of getting everything to build. Each source file will be compiled and will look for headers in all those directories and then the object files will get linked together. Consider if there is any way of simplifying this such that you don't need so many include folders, maybe there are only a few common header files that need to be referenced by all source files. If things get more complex you can buiild sub-hierarchies into libraries etc. Also consider seperating source files and headers (e.g. in src and include).