CMake inlucde project file without folder prefix - c++

My project structure is the following:
-Engine
|-Shaders
| '-shader.glsl
|-source
| |-Math
| |'- matrix.hpp
| | - vector.hpp
| '-Lua
| |'-lua_state.hpp
'-CMakeLists.txt
I am using CMake as build system and my question is :
How can I include for example matrix.hpp into lua_state.hpp without using the prefix for folder path ? i mean instead to use in lua_state.hpp #include "../Math/matrix.hpp" , just included like this -> #include "matrix.hpp" , there is any way to do this with CMake ?

You can specify the include path for compiler (-I option)
To include it for all targets (docs)
include_directories(source/Math)
or use target properties (docs)
target_include_directories(yourAppOrLibTargetName PRIVATE source/Math)

Add the directory to the include path by calling the include_directories command.
You'll also need to make sure the header files are declared as dependencies of the library or executable you're creating, either using add_library or add_executable. I can't quite tell what you'll need based on the files you listed.

Related

cmake shared lib with Qt

I created two default projects with QtCreator v6.0.1: MyApp and MyLib for Linux(Ubuntu).
I changed the folders structure to
MyApp
├──build
│ ├──Debug
| └──Release
├──src
├──libs
| └──MyLib
| ├──build
| ├──src
| ├──include
| └──CMakeLists.txt
├──include
├──src
└──CMakeLists.txt
What kind of changes I need to make with both of CMakeLists.txt to make MyLib as shared library and use it in MyApp?
First of all, as already mentioned, you'll need to add the MyLib directory with add_subdirectory in the top-level CMakeLists.txt:
...
add_subdirectory(libs/MyLib)
...
Then, defining a shared/dynamic library with CMake is pretty straight forward. You use add_library providing the name of the library, the source files and some flags. By default it will create a static library, but with the keyword SHARED you can change that:
add_library(MyLib SHARED
MySource1.cpp
MySource2.cpp
...
)
Have a look here: https://cmake.org/cmake/help/latest/command/add_library.html
By the way, all generated code (including the library) will end up in the one and only build directory (which you either specify with cmake -B $BUILD_DIR or which is the working directory for running cmake). So you won't have an additional one in your libs/MyLib folder.

CMake target_include_directories does not affect header files

My project is roughly structured like this:
├CMakeLists.txt
|
├───ExampleApp
| ├───CMakeLists.txt
| ├───header.hpp
| └───main.cpp
|
└───ExampleLibrary
├───CMakeLists.txt
├───mylib.hpp
└───mylib.cpp
In the root CMakeLists.txt I call
add_subdirectory(ExampleLibrary)
add_subdirectory(ExampleApp)
To build the library I call:
add_library(ExampleLibrary
mylib.hpp mylib.cpp
)
And finally, in the executable, I try to do:
add_executable(ExampleApp
header.hpp main.cpp
)
target_include_directories(ExampleApp
PRIVATE ${PROJECT_SOURCE_DIR}/ExampleLibrary
)
target_link_libraries(ExampleApp
Path/To/The/Binary/Directory
)
Now the build files generate just fine, and the project also builds with no errors. However, when I now try to include mylib.hpp in header.hpp, I get build errors because it can't find the file mylib.hpp. But I actually can include mylib.hpp in main.cpp and the project builds and compiles.
Am I missing something? I thought target_include_directories() works for both .cpp and .hpp files.
It seems like you may not have added the correct directory as an include directory for the ExampleApp. The PROJECT_SOURCE_DIR variable evaluates to the directory in which the last project() call was made in your CMake project. You have not shown where this is, but you could use the root directory of the CMake project to be sure it is correct; try using ${CMAKE_SOURCE_DIR}/ExampleLibrary in the target_include_directories call instead:
target_include_directories(ExampleApp
PRIVATE ${CMAKE_SOURCE_DIR}/ExampleLibrary
)
A couple more notes:
If you aren't using an IDE such as Visual Studio for compilation, there is no need to add header files to calls like add_library() and add_executable(). Doing this only ensures they are shown in an IDE.
Instead, specify directories within which the headers can be found, using target_include_directories(). In your case, it sounds like you should have both directories listed here.
To link the ExampleLibrary target to the executable, you can simply use the target name in target_link_libraries(). There is no need to list out the binary directory (unless you are linking other libraries from there).
So with this in mind, the ExampleApp CMake file could look something like this:
add_executable(ExampleApp
main.cpp
)
target_include_directories(ExampleApp PRIVATE
${PROJECT_SOURCE_DIR}/ExampleLibrary
${CMAKE_CURRENT_LIST_DIR}
)
target_link_libraries(ExampleApp PRIVATE
ExampleLibrary
)

add root directory as include directory

During compilation certain header files aren't found, although I added the respective include directories in CMake. Unfortunately this is the code and directory structure I am stuck with and I can't change anything on the include statements.
I have the following directory structure:
projectfolder
+--source1
| |--prog.cpp
| |--anotherHeader.h
| |--CMakeLists
|
+--includefolder
| +--source1_include
| | |--header.h
|
|--CMakeLists
CMakeLists in projectfolder looks like this:
project (project)
include_directories(includefolder)
add_subdirectory(source1)
prog.cpp has:
#include "source1_include/header.h"
and header.h has:
#include "anotherHeader.h"
(don't ask me why, I don't know myself, maybe it has something to do with the fact that originally this is a Visual Studio project)
I thought I could fix this, by adding
include_directories(.)
to the CMakeLists in the source1 directory but unfortunately it wont work that way. anotherHeader.h isn't found.
I'm assuming that "." is "projectfolder"
If I understand correctly, you added -I "projectfolder", so now "source1_include/header.h" correctly finds "projectfolder/source1_include/header.h"
Now, "header.h" tries to include "anotherHeader.h", which is not in its folder and not in any of the included folders. It is actually in "source1". So cmake is correct to error out.
You need to either move "anotherHeader.h" into your includes folder (my recommendation), or edit "header.h" to find it by the correct relative path "../source1/anotherHeader.h" (not recommended), or add include_directories("source1"), which is where it actually is.

Modular C++ Project Build with CMake

I'm trying to find a way to build a big modular C++ project with CMake.
The structure of the project is the following:
--project_root
--src
--folder_1
--source_1.h
--source_1.cc
--test_source_1.cc // file containing a main with unit tests
--folder_2
--source_2.h
--source_2.cc
--test_source_2.cc // file containing a main with unit tests
--folder_3
...
And so on.
Each folder represent a project module and each module might depend on other modules, so for example source_1.h may include source_2.h.
Every module folder may also contains a test file so the whole project will have multiple executables.
How can I build the whole project with CMake? How should I write my CMakeLists.txt file?
Thank you a lot.
There are many, many examples out there of how to structure CMake projects for C++, many of which are referenced by the tutorial #user2485710 suggested in his comment, so I'm not going to go super in-depth here, but I'll at least give you a good starting point based on the way you want to lay out you folder structure.
The nice thing about CMake is that it can essentially do a tree-decent using the add_subdirectory command. This lets us easily divide up our CMake code to only do what is required at any specific directory level. In otherwords, each CMakeLists.txt file should only do the minimal amount of work needed to properly set up things at the current depth in the directory tree. In you example, your CMake tree might look like this:
--project_root
--src
--CMakeLists.txt
--folder_1
--CMakeLists.txt
--source_1.h
--source_1.cc
--test_source_1.cc // file containing a main with unit tests
--folder_2
--CMakeLists.txt
--source_2.h
--source_2.cc
--test_source_2.cc // file containing a main with unit tests
...
In src/CMakeLists.txt you do all of your project-level initialization, I.E. find_package, setting up your include-path, etc. Then you simply add the following at the end:
add_subdirectory(folder_1)
add_subdirectory(folder_2)
...
This tells CMake that it should look in those folders for additional stuff to do. Now in src/folder_1/CMakeLists.txt, we do the actual work of whatever combination of add_executable and add_library you need to properly build source_1.cc and test_source_1.cc, and likewise in src/folder_2/CMakeLists.txt for source_2.cc, etc.
The other nice thing is that any CMake variables you set higher up the tree are propagated down through add_subdirectory. So, for example, in src/CMakeLists.txt you can check for some sort of 'build unit-test' flag and set the CMake variable there, and then all you have to do in the other CMakeLists.txt files is check for that variable. This can also be super useful to do if you have a project where CMake is dynamically generating header files for you based on checking environment variables for path-names and the like.
If the structure of the project is well-regulated, you could write custom macros or function of cmake to define the modules and their dependencies.
The cmake scripts in OpenCV project is a good reference:
/libs/opencv-2.4.8/sources/
|+cmake/
|+doc/
|~modules/
| |+core/
| | |+doc/
| | |+include/
| | |+perf/
| | |+src/
| | |+test/
| | `-CMakeLists.txt
| |~imgproc/
| | |+doc/
| | |+include/
| | |+perf/
| | |+src/
| | |+test/
| | `-CMakeLists.txt
| |+ml/
| |+...
| |-CMakeLists.txt
|-CMakeLists.txt
root/modules/imgproc/CMakeLists.txt
set(the_description "Image Processing")
ocv_define_module(imgproc opencv_core)
You will need a CMakeLists.txt in each folder where building will occur.
project() is used to set the name of your overall project.
add_subdirectory() is used to command the configuration to process the CMakeLists.txt in that directory.
add_executable() is used to create an executable from included sources.
add_library() is used to create a static or dynamic library that can be added to executables or libraries as a dependency.
Using a build script (.bat, .cmd, or .sh) will allow you to automate some of the cmake process, such as setting up an out-of-source configuration or build.
You should look up the documentation for these commands on the cmake website, https://cmake.org/cmake/help/latest/

Describing header file locations in makefile

In a new project I am working on I have the following dir structure:
Project_base
|---- src
|---- bin
|---- h
| Makefile
And in my source files I have includes that look like so:
#include "../h/SomeHeaderFile.h"
instead of the more correct form:
#include "SomeHeaderFile.h"
What do I need to add to my makefile so that I can removed the relative path includes so they will look normal?
ADDITION: also, where do I set this in CDT (C++ for eclipse) so that in design time this is reflected as well?
You need to add -I../h in the list of parameters you pass to gcc.
Add a flag to your CFLAGS so that the root of the headers is part of the headers search path:
-IProject_base/h
That way gcc/g++ will also look here in addition to the default headers directories.