CMAKE library / application structure - c++

I have the following project structure:
root/
CMakeLists.txt
src/
CMakeLists.txt
engine/
CMakeLists.txt
*.h
*.cpp
console/
CMakeLists.txt
*.h
*.cpp
Now in src/engine/CMakeLists.txt I call add_library(engine ${SOURCES}) and it works out fine, compiles and everything. Now over in console, I would like my includes to the engine be #include "engine/foo.h" and not just #include "foo.h".
Now the question is, are there any elegant way to add the includes so I have to prepend engine to my includes in the console project?
Currently what I do is have the following in src/console/CMakeLists.txt:
add_executable(console ${SOURCES})
target_include_directories(console PUBLIC ${lib_incl_path})
target_link_libraries(console PRIVATE engine)
and then define set(lib_incl_path ${CMAKE_CURRENT_SOURCE_DIR}) in src/CMakeLists.txt. But that seems overkill (and hacky), to add the entire src folder to the includes.

The answer is to use
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
See CMake how to correctly create dependencies between targets

Related

cmake add external library without a separate CMakeLists.txt

I'm having the following project structure in a C++ project. I am depending on an external library (libA as for the following) and I'm cloning the external library into the include folder using a shell script.
include/
libA
src/
source.c
lib/
include/
libA.a
src/
fileA.cpp
main.cpp
CMakeLists.txt
The command given to compile the program is
clang -I include/libA/lib/include main.cpp fileA.cpp include/libA/src/source.c include/libA/src/libA.a
I have seen on stackoverflow that in order to add this external library I have to create a separate CMakeLists.txt in the external library folder and use add_library(). And in the main CMakeLists.txt file use add_subdirectory().
Is there a way to do this without a seperate CMakeLists.txt.
My current main CMakeLists.txt file. (This works but I think I'm missing something)
cmake_minimum_required(VERSION 3.16.3)
project(test)
add_executable(${PROJECT_NAME} src/main.cpp src/fileA.cpp include/libA/src/source.c )
include_directories(include/libA/lib/include)
target_link_libraries(${PROJECT_NAME} /include/libA/libA.a )
target_include_directories(${PROJECT_NAME} PUBLIC include/libA/lib/include)

Integrating GTest with existing CMake Project: share the same target_sources

I have a large C++ library, and want to do some testing with GTest.
At the moment, the build is handled with CMake, in particular there is one CMakeLists.txt file in the root directory like the following
make_minimum_required(VERSION 3.13.0)
project(mylib)
find_package(PkgConfig REQUIRED)
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
set(CMAKE_INSTALL_RPATH "${CMAKE_CURRENT_SOURCE_DIR}/lib/protobuf/src/.libs/")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
SET(BASEPATH "${CMAKE_SOURCE_DIR}")
INCLUDE_DIRECTORIES("${BASEPATH}")
add_executable(mylib run.cpp)
add_subdirectory(src)
add_subdirectory(proto)
target_include_directories(mylib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/lib/math
${CMAKE_CURRENT_SOURCE_DIR}/lib/protobuf/src
... some dirs ...
)
target_link_directories(mylib PRIVATE
... some libs ..
)
target_link_libraries(mylib
${CMAKE_CURRENT_SOURCE_DIR}/lib/math
${CMAKE_CURRENT_SOURCE_DIR}/lib/protobuf/src
.....
)
target_compile_options(mylib PUBLIC -D_REENTRANT -fPIC)
Then in the src directory and every sub-directory there is a CMakeLists.txt file, for example this is in src/
target_sources(mylib
PUBLIC
includes.hpp
)
add_subdirectory(algorithms)
add_subdirectory(collectors)
add_subdirectory(hierarchies)
add_subdirectory(mixings)
add_subdirectory(runtime)
add_subdirectory(utils)
My question here is the following: what is the least painful way to integrate GTest in the current project? I was thinking of having a test/ subdirectory, like I've seen here: Adding Googletest To Existing CMake Project
However this example requires that for each executable you manually list all the files it includes. Is there a quicker way to use the sources that are already added to 'mylib'?
You can split the current mylib executable target into two targets
mylib, a library target that is very much like the current mylib target, but without the run.cpp file
mylib_exe an executable target that compiles run.cpp and links to mylib
Now your test files can link to mylib.

Linking two libraries together with CMake

File Structure:
CMakeLists.txt
src/
evolution.cpp
evolution.h
main.cpp
helpers/
disposable.h
engine/
game.h
game.cpp
CMakeLists.txt:
cmake_minimum_required(VERSION 3.17)
project(evolution)
add_library(helpers
src/helpers/disposable.h)
set_target_properties(helpers PROPERTIES LINKER_LANGUAGE CXX)
add_library(engine
src/engine/game.h
src/engine/game.cpp)
add_executable(evolution src/main.cpp)
target_link_libraries(evolution engine helpers)
The Game class (game.h) inherits from Diposable (disposable.h), but I am unable to build the project with a simple #include "disposable.h" in the game.h file.
How do I configure CMake so that the engine library can see the helpers library?
CMake error:
[ 20%] Building CXX object CMakeFiles/engine.dir/src/engine/game.cpp.o
In file included from /home/shane/projects/evolution/src/engine/game.cpp:1:
/home/shane/projects/evolution/src/engine/game.h:4:10: fatal error: disposable.h: No such file or directory
4 | #include "disposable.h"
| ^~~~~~~~~~~~~~
compilation terminated.
Adding headers to a project really only helps IDEs find the headers. It doesn't change the build instructions. Instead you need to use target_include_directories() with a INTERFACE or PUBLIC section to get any libraries that link to this to add the include directories to itself.
Your helpers library is more of an interface for now. To get this minimum example working do this:
cmake_minimum_required(VERSION 3.17)
project(evolution)
add_library(helpers INTERFACE) # INTERFACE is good for header-only libraries
target_include_directories(helpers INTERFACE src/helpers)
add_library(engine
src/engine/game.h
src/engine/game.cpp)
add_executable(evolution src/main.cpp)
target_link_libraries(evolution engine helpers)
Now include with angular brackets: #include <disposable.h>
If your library becomes more complicated (more than just header files), then replace INTERFACE in add_library with your sources. To make include directories available to the helpers library and any library that links to it, change INTERFACE to PUBLIC in target_include_directories.
cmake_minimum_required(VERSION 3.17)
project(evolution)
add_library(helpers src/helpers/helper.cpp)
target_include_directories(helpers PUBLIC src/helpers)
add_library(engine
src/engine/game.h
src/engine/game.cpp)
add_executable(evolution src/main.cpp)
target_link_libraries(evolution engine helpers)

Should I use only add_executable() with raw cpp files or make a library via add_library()?

I'm learning CMake and I'm struggling with it a little. My "project" is using JsonCpp "library" that was provided as one .cpp file and two .h files. The structure looks like this:
myProject
build/
json/
CMakeLists.txt
jsoncpp.cpp
include/
json.h
json-forward.h
CMakeLists.txt
main.cpp
build/CMakeLists.txt:
cmake_minimum_required(VERSION 3.6.0)
project(myProject)
add_subdirectory(json)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE json)
# add_executable(app main.cpp json/jsoncpp.cpp json/include/json.h json/include/json-forwards.h)
json/CMakeLists.txt:
cmake_minimum_required(VERSION 3.6.0)
add_library(
json
jsoncpp.cpp
include/json.h
include/json-forwards.h
)
target_include_directories(json PUBLIC '${CMAKE_CURRENT_SOURCE_DIR}/include')
What's a difference between using only add_executable() with all .cpp files and using target_link_libraries that transforms jsoncpp into static library and then link it? What approach should I choose?
A next thing confusing me is a target_include_directories(). What are the benefits using this function? If I comment it, and run cmake (then makefile and launch the app) everything still works fine. If I delete "include/json.h" "include/json-forward.h" from add_library(), everything still works.
What's a difference between using only add_executable() with all .cpp files and using target_link_libraries that transforms jsoncpp into static library and then link it? What approach should I choose?
Using add_library is required when you have 2 executables using the same jsoncpp code. In this case, if you list jsoncpp sources in both add_executable() calls, you'd have to compile it twice. Grouping them into add_library() will make it compile only once and then linked to both executables.
Another reason to use add_library is purely logical composition of modules.

CMakeLists.txt add subfolder which represents namespace (just for organization)

Consider the following setup:
-project
--src
---CMakeLists.txt
---main.cpp
---Application.cpp
---Application.hpp
---subfolder
----SomeClass.cpp
----SomeClass.hpp
--bin
And consider this CMakeLists.txt
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
# Include directories
INCLUDE_DIRECTORIES("subfolder")
# Executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
Now, as long as I had all my classes in the same folder (src) everything worked perfectly fine.
But now I want to restructure my application a bit. I want to build a folder-hierarchy that represents the namespaces.
Of course in my includes I would then use
#include "subfolder/SomeClass.hpp"
but it doesn't work that way. I had a look at the manpage but there are so many options in CMake and it's often talking about standalone libraries that have their own CMakeLists.txt... I'm not that far yet. I just want to add a subfolder, that's all.
Until now I've used QMake for my C++ projects, but I wanted to dive into CMake now.
Are there any useful tutorials out there? I've found a few, but they they don't cover the basics.
The recommened way is to use a CMakeLists.txt for every subdirectory in existence. If you want to have subdirectories and organize them without having to create multiple CMakeLists.txt files, you can create one in the main directory with those contents:
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
include_directories(src)
file(GLOB_RECURSE SRC_LIST *.c* *.h*)
# Executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
Using aux_source_directory is used mainly for template related things. Also it's common practice to use a toplevel CMakeLists.txt, which includes the further files, has common project settings etc.:
<project>
|
+- CMakeLists.txt
|
+- src/
|
+-- CMakeLists.txt
|
+-- main.cpp
|
…
So this would look like:
CMakeLists.txt (Project dir):
project(SampleProject)
cmake_minimum_required(VERSION 2.8)
include_directories(src) # Add 'src' to include paths
subdirs(src) # Includes the 'src' directory and its cmake file
# ...
Now you can use the include path as expected.
CMakeLists.txt (src dir):
# Better add src files this way:
add_executable(${PROJECT_NAME} main.cpp Application.cpp)
subdirs(subfolder) # TODO: handle subfolder
The subfolder can be added through an additional library target, that is linked to your executable. Usually there's another CMakeLists.txt file in there.
Also make sure your cmake cache is updated; best you recreate it.