Share files between multiple groups under CMake - c++

I`m trying to create a CMake setup for a project with the following structure:
workshop
| CMakeLists.txt
| utilities
| | utilities.h
| | utilities.cpp
| | CMakeLists.txt
| week_1
| | week_1.h
| | week_1.cpp
| | main.cpp
| | CMakeLists.txt
| week_2
| | main.h
| | week_2.cpp
| | main.cpp
| | CMakeLists.txt
Everything depends on OpenCV and the programs in week_X depend also on utilities.
I was able to do everything except the connection with utilities.
My trial:
File workshop\CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
PROJECT(workshop)
SET(OpenCV_DIR OPENCV_DIR)
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS})
add_subdirectory(${CMAKE_SOURCE_DIR}/utilities)
add_subdirectory(${CMAKE_SOURCE_DIR}/week_1)
add_subdirectory(${CMAKE_SOURCE_DIR}/week_2)
File week_1\CMakeLists.txt (week_2\CMakeLists.txt is identical just changing 1 by 2)
cmake_minimum_required(VERSION 2.8.12)
include_directories( ${OpenCV_INCLUDE_DIRS})
set(SRCFILES week_1.cpp week_1.h main.cpp)
source_group(week_1 FILES ${SRCFILES})
add_executable(week_1 ${SRCFILES})
target_link_libraries(week_1 ${OpenCV_LIBS})
All is okay until the utilities. How would be the utilities\CMakeLists.txt?

I think you want utilities to be a library.
In the utilities CMakeLists.txt
# This will create libutilities.a
add_library(utilities
utilities.cpp
)
target_include_directories( utilities PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
# Third party libs
${OpenCV_INCLUDE_DIRS}
)
target_link_libraries(utilities
${OpenCV_LIBRARIES}
)
In week_X you'll use it as a library like so:
include_directories(
${OpenCV_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/utilities # Include utilities header
)
set(SRCFILES week_1.cpp week_1.h main.cpp)
source_group(week_1 FILES ${SRCFILES})
add_executable(week_1 ${SRCFILES})
target_link_libraries(
${OpenCV_LIBS}
utilities # Link to libutilites.a
)

Related

CMake - No rule exists to target

In Ubuntu, I have downloaded a third-party shared library (liba1.so), placed in /lib/extern/lib . The associated header files I placed in /lib/extern/include. My own header files are placed in /include/public/ and /include/private/ . And now (to test mylib) I want to link this in my main.cpp code, using CMake.
My structure:
**My structure:**
|
|
+---CMakeLists.txt
|
+---lib
| |
| +---extern
| |
| +---lib
| | |
| | +---liba.so
| | +---libb.so
| | +---liba12.so
| |
| +---include
| |
| +...headers.h
|
+---include
| |
| +---public
| | |
| | +---file1.hpp
| | +...
| |
| +---private
| |
| +---file2.hpp
| +...
|
+---src
|
+---public
| |
| +---file1.cpp
| +...
|
+---private
| |
| +---file2.cpp
| +...
|
+---main.cpp
My CMakeLists.txt:
cmake_minimum_required(VERSION 3.9...3.19)
if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_VERSION})
endif()
project(mylib VERSION 0.0.1 DESCRIPTION "Test" LANGUAGES CXX )
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -DTPM_POSIX")
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_library(${PROJECT_NAME} STATIC src/private/file2.cpp src/public/file1.cpp )
add_library(lib SHARED IMPORTED)
set_target_properties(lib PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/lib/extern/lib/liba.so)
set_target_properties(lib PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/lib/extern/lib/libb.so)
set_target_properties(lib PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/lib/extern/lib/liba12.so)
target_link_libraries(${PROJECT_NAME} PUBLIC lib)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<INSTALL_INTERFACE:lib/extern/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib/extern/include>
$<INSTALL_INTERFACE:include/public>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/public>
$<INSTALL_INTERFACE:include/private>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/private>
)
add_executable(test src/main.cpp)
target_link_libraries(test PRIVATE mylib)
ERROR:
[build] Consolidate compiler generated dependencies of target mylib
[build] [ 60%] Built target mylib [build] Consolidate compiler generated dependencies of target test
[build] gmake[2]: *** No rule exists to target „lib/extern/lib/liba12.so“,
[build] required by „test“ to create. Ending.
[build] gmake[1]: *** [CMakeFiles/Makefile2:111: CMakeFiles/test.dir/all] Error 2
[build] gmake: *** [Makefile:91: all] Error 2
[proc] The command: /usr/bin/cmake --build /home/mathew/proj/build --config Debug --target all -j 10 -- exited with code: 2 and signal: null [build] Build finished with exit code 2
Your imported files are relative to the source directory, not the build directory. You need to use CMAKE_CURRENT_SOURCE_DIR instead of CMAKE_CURRENT_BINARY_DIR when setting IMPORTED_LOCATION.

Building with CMake adds prefix "OFF" to the tests. How to get rid of that?

I have a CMake project with following structure:
project
|- src
| |- plugins
| | |- class1
| | | |- class1.hpp
| | | |- class1.cpp
| | | |- CMakeLists.txt
| | |- class2
| | |- class2.hpp
| | |- class2.cpp
| | |- CMakeLists.txt
| |- tests
| |- CMakeLists.txt
| |- test_1
| | |- test.cpp
| | |- CMakeLists.txt
| |- test_2
| |- test.cpp
| |- CMakeLists.txt
|- CMakeLists.txt
The contents of the CMakeLists is as follows:
project/CMakeLists:
cmake_minimum_required (VERSION 3.7)
project(project-name)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
add_subdirectory(src/plugins/class1)
add_subdirectory(src/plugins/class2)
## Tests
option(CMAKE_BUILD_TESTS "Build tests" ON)
if(CMAKE_BUILD_TESTS)
enable_testing()
add_subdirectory(src/tests)
endif()
project/src/plugins/class1/CMakeLists.txt (similarly for class2):
project(plugin_1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
add_library(class1 SHARED class1.cpp class1.hpp)
target_compile_options(class1 PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wall>)
install(TARGETS class1
COMPONENT bin
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
project/src/tests/CMakeLists.txt:
cmake_minimum_required (VERSION 3.7)
project(unit-tests)
add_subdirectory(test_1)
add_test(NAME test_1 COMMAND test_1)
add_subdirectory(test_2)
add_test(NAME test_2 COMMAND test_2)
project/src/tests/test_1/CMakeLists.txt (similarly for test_2):
cmake_minimum_required (VERSION 3.7)
project(test_1)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include_directories(${CMAKE_SOURCE_DIR}/src/plugins/class1)
add_executable(test_1 test.cpp)
target_compile_definitions(test_1 PUBLIC UNIT_TESTS)
target_link_libraries(test_1 class1)
install(TARGETS test_1
COMPONENT bin
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
I am building the project as follows:
$ mkdir build && cd build
$ cmake -DCMAKE_BUILD_TESTS=ON ..
$ make && make install
Question:
Whilst building the project, it builds the tests as: OFFtest_1 and OFFtest_2. How to get rid if the 'OFF' prefix? Where is it coming from?

How to Create Packages with CMake

.
+-- MyPack
| +-- Lib1
| | +-- include
| | | +-- Lib1.h
| | +-- src
| | | +-- Lib2.cpp
| | +-- CMakeLists.txt
| +-- Lib2
| | +-- include
| | | +-- Lib2.h
| | +-- src
| | | +-- Lib2.cpp
| | +-- CMakeLists.txt
| +-- CMakeLists.txt
+-- SubProject1
| +-- CMakeLists.txt
+-- SubProject2
| +-- CMakeLists.txt
+-- CMakeLists.txt
Hi all.
I'm new to CMake and I'm trying to obtain something like the following.
Considering the above directory tree of my C++ project:
I have a directory (let's say "MyPack") that contains several subdirectories (Lib1, Lib2...) and each one represents a C++ Library that I wrote.
How can I setup everything so I can write find_package(MyPack)in the other subprojects?
Every subproject is a stand-alone project, and does not depend on other subprojects, but just on libraries in "MyPack".
Your drawing is a bit confusing because there is a CMakeLists.txt after Lib2 which belongs to no folder...
Anyway : is MyPack
Lib1 and Lib2 ?
Lib1/Lib2/Subproj1/Subproj2 ?
in the 2nd case :
The top directory CMakeLists.txt gives you access to targets of Lib1 and Lib2 that you can use in SubProject1 and SubProject2 if you have something like this :
project(MyPack)
add_subdirectory(Lib1) # Building Lib1
add_subdirectory(Lib2) # Building Lib2
add_subdirectory(SubProject1) # you can use Lib1 & Lib2 targets here
add_subdirectory(SubProject2) # you can use Lib1 & Lib2 targets here
If it is the 1st case, MyPack is only Lib1 and Lib2 :
Using find_package(MyPack) means that you need to create a Config file and install() your project:
project(MyPack)
add_subdirectory(Lib1)
add_subdirectory(Lib2)
in Lib1/CMakeLists.txt :
add_library(lib1 "")
add_library(MyPack::lib1 ALIAS lib1)
[...]
include(GNUInstallDirs)
install(
TARGET lib1
EXPORT MyPackTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
in Lib2/CMakeLists.txt :
add_library(lib2 "")
add_library(MyPack::lib2 ALIAS lib2)
[...]
include(GNUInstallDirs)
install(
TARGET lib2
EXPORT MyPackTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
Now you have lib1 and lib2 in the export MyPackTargets. You have to install that export as well.
anywhere after above :
install(
EXPORT MyPackTargets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyPack
NAMESPACE MyPack::
FILE MyPackTargets.cmake # Not sure if this is still needed
)
include(CMakePackageConfigHelpers)
configure_package_config_file(
"Config.cmake.in"
"MyPackConfig.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyPack
PATH_VARS
CMAKE_INSTALL_LIBDIR
)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/MyPackConfigVersion.cmake
VERSION 1.0.0
COMPATIBILITY SameMajorVersion
)
### Install Config and ConfigVersion files
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/MyPackConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/MyPackConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/MyPack"
)
create a file Config.cmake.in with :
#PACKAGE_INIT#
include( "${CMAKE_CURRENT_LIST_DIR}/MyPackTargets.cmake" )
Now if you build and install your project MyPack, find_package(MyPack) from other project should find it and import the targets you've created.
Here is some documentation :
https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html
https://blog.kitware.com/cmake-superbuilds-git-submodules/
Hope that helps

CMakeLists for large project with multiple directories?

I am writing a Game Engine, which is going very well. But I am running into a problem where my CMakeLists.txt is just too messy, and I don't know enough about CMake. My project uses multiple (CMake) libraries, which are added using add_subdirectory and then target_link_libraries. My project consists of the Engine(executable), the Editor(library), and some tests/examples. Here is my file structure:
C:.
| CMakeLists.txt
| tree.txt
|
+---Editor
| | README.md
| |
| \---src
| main.cpp
|
+---Engine
| | README.md
| |
| +---src
| | | main.cpp
| | |
| | +---API
| | | Core.h
| | |
| | +---App
| | | Application.cpp
| | |
| | +---ExtApp
| | | | AppInterface.cpp
| | | |
| | | +---Engine
| | | | ExtAppLoader.cpp
| | | |
| | | \---Game
| | | InfoExport.cpp
| | |
| | +---Framework
| | | Asset.cpp
| | |
| | +---Managing
| | | AssetLoader.cpp
| | |
| | +---Rendering
| | | | Renderer.cpp
| | | |
| | | \---Renderables
| | | Canvas2DRenderable.cpp
| | |
| | \---Types
| | Vector3f.cpp
| |
| \---TestResources
| \---Shaders
| Canvas2DTexturedTriangle.f
| Canvas2DTexturedTriangle.v
| Canvas2DUntexturedTriangle.f
| Canvas2DUntexturedTriangle.v
| ImTest.f
| ImTest.v
|
+---Libraries
| +---glfw
| | CMakeLists.txt
| |
| \---glm
| CMakeLists.txt
|
\---Tests
\---TestGame
\---src
main.cpp
As you can see I have one CMakeLists at the begin, which loads all the projects. Then I have libraries, which have a CMakeLists too. Every directory has only one file to make the tree less big, but there are multiple fies in a directory. Also, here is my current, messy, almost-useless CMakeLists file:
cmake_minimum_required(VERSION 3.6)
#project(3DEngine)
add_subdirectory(Libraries/glfw) #Add glfw to the project
# Make sure we're running C++17 so all features(like std::filesystem) are present.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
option(BUILD_ENGINE_FOR_EDITOR "Build the engine as DLL/SO for the editor and add editor specific things. Otherwise build engine as game exec" OFF)
option(BUILD_ENGINE_FOR_DLL_APPS "Have the Engine load the game(and plugins) from dll's." ON)
project (Engine)#project engine
include_directories(Libraries/whereami/src)
include_directories(Engine/src/)
include_directories(Libraries/glfw/include)
include_directories(Libraries/glm)
include_directories(Libraries/glad/include)
include_directories(Libraries/stb)
file(GLOB EngineRootSOURCES "Engine/src/*.cpp" "Engine/src/*.h")
file(GLOB EngineRenderingSOURCES "Engine/src/Rendering/*.cpp" "Engine/src/Rendering/*.h")
file(GLOB EngineAppSOURCES "Engine/src/App/*.cpp" "Engine/src/App/*.h")
file(GLOB EngineRenderingRenderablesSOURCES "Engine/src/Rendering/Renderables/*.cpp" "Engine/src/Rendering/Renderables/*.h")
file(GLOB EngineManagingSOURCES "Engine/src/Managing/*.cpp" "Engine/src/Managing/*.h")
file(GLOB EngineTypesSOURCES "Engine/src/Types/*.cpp" "Engine/src/Types/*.h")
file(GLOB EngineGameEssentialsSOURCES "Engine/src/GameEssentials/*.cpp" "Engine/src/GameEssentials/*.h")
file(GLOB EngineLibsSOURCES "Libraries/whereami/src/whereami.c" "Libraries/glad/src/glad.c")
file(GLOB EngineFrameworkSOURCES "Engine/src/Framework/*.h" "Engine/src/Framework/*.cpp")
file(GLOB APISOURCES "Engine/src/API/*.cpp" "Engine/src/API/*.h")
file(GLOB EngineExtAppSOURCES "Engine/src/ExtApp/*.cpp" "Engine/src/ExtApp/*.h"
"Engine/src/ExtApp/Interface/*.cpp" "Engine/src/ExtApp/Interface/*.h")
file(GLOB EngineExtAppGameSOURCES "Engine/src/ExtApp/Game/*.cpp" "Engine/src/ExtApp/Game/*.h")
source_group("ExtApp" FILES ${EngineExtAppGameSOURCES})
file(GLOB EngineExtAppEngineSOURCES "Engine/src/ExtApp/Engine/*.cpp" "Engine/src/ExtApp/Engine/*.h")
source_group("ExtApp" FILES ${EngineExtAppEngineSOURCES})
if(BUILD_ENGINE_FOR_EDITOR)
file(GLOB EngineEditorSOURCES "Engine/src/ExtApp/*.cpp" "Engine/src/ExtApp/*.h"
"Engine/src/ExtApp/Interface/*.cpp" "Engine/src/ExtApp/Interface/*.h")
if(BUILD_ENGINE_FOR_DLL_APPS)
add_library(Engine SHARED ${EngineRootSOURCES} ${EngineRenderingSOURCES} ${EngineTypesSOURCES} ${EngineRenderingRenderablesSOURCES} ${EngineManagingSOURCES} ${EngineGameEssentialsSOURCES} ${EngineLibsSOURCES} ${EngineEditorSOURCES} ${EngineExtAppSOURCES} ${EngineAppSOURCES} ${APISOURCES} ${EngineExtAppEngineSOURCES} ${EngineFrameworkSOURCES})
source_group("ExtApp" FILES ${EngineExtAppSOURCES})
elseif(NOT BUILD_ENGINE_FOR_DLL_APPS)
add_library(Engine SHARED ${EngineRootSOURCES} ${EngineRenderingSOURCES} ${EngineTypesSOURCES} ${EngineRenderingRenderablesSOURCES} ${EngineManagingSOURCES} ${EngineGameEssentialsSOURCES} ${EngineLibsSOURCES} ${EngineEditorSOURCES} ${EngineExtAppSOURCES} ${EngineAppSOURCES} ${APISOURCES} ${EngineExtAppEngineSOURCES} ${EngineFrameworkSOURCES})
endif()
target_link_libraries(Engine glfw)
source_group("Rendering" FILES ${EngineRenderingSOURCES})
source_group("Rendering/Renderables" FILES ${EngineRenderingRenderablesSOURCES})
source_group("Managing" FILES ${EngineManagingSOURCES})
source_group("App" FILES ${EngineAppSOURCES})
source_group("Types" FILES ${EngineTypesSOURCES})
source_group("GameEssentials" FILES ${EngineGameEssentialsSOURCES})
source_group("Libs" FILES ${EngineLibsSOURCES})
source_group("ExtApp" FILES ${EngineEditorSOURCES})
source_group("API" FILES ${APISOURCES})
source_group("Framework" FILES ${EngineFrameworkSOURCES})
elseif(NOT BUILD_ENGINE_FOR_EDITOR)
if(BUILD_ENGINE_FOR_DLL_APPS)
file(GLOB EngineExtAppSOURCES "Engine/src/ExtApp/*.cpp" "Engine/src/ExtApp/*.h"
"Engine/src/ExtApp/Interface/*.cpp" "Engine/src/ExtApp/Interface/*.h")
add_executable(Engine ${EngineRootSOURCES} ${EngineRenderingSOURCES} ${EngineTypesSOURCES} ${EngineRenderingRenderablesSOURCES} ${EngineManagingSOURCES} ${EngineGameEssentialsSOURCES} ${EngineLibsSOURCES} ${EngineExtAppSOURCES} ${EngineAppSOURCES} ${APISOURCES} ${EngineExtAppEngineSOURCES} ${EngineFrameworkSOURCES})
source_group("ExtApp" FILES ${EngineExtAppSOURCES})
elseif(NOT BUILD_ENGINE_FOR_DLL_APPS)
add_executable(Engine ${EngineRootSOURCES} ${EngineRenderingSOURCES} ${EngineTypesSOURCES} ${EngineRenderingRenderablesSOURCES} ${EngineManagingSOURCES} ${EngineGameEssentialsSOURCES} ${EngineLibsSOURCES} ${EngineExtAppSOURCES} ${EngineAppSOURCES} ${APISOURCES} ${EngineExtAppEngineSOURCES} ${EngineFrameworkSOURCES})
endif()
target_link_libraries(Engine glfw)
source_group("Rendering" FILES ${EngineRenderingSOURCES})
source_group("Rendering/Renderables" FILES ${EngineRenderingRenderablesSOURCES})
source_group("Managing" FILES ${EngineManagingSOURCES})
source_group("App" FILES ${EngineAppSOURCES})
source_group("Types" FILES ${EngineTypesSOURCES})
source_group("GameEssentials" FILES ${EngineGameEssentialsSOURCES})
source_group("Libs" FILES ${EngineLibsSOURCES})
source_group("API" FILES ${APISOURCES})
source_group("Framework" FILES ${EngineFrameworkSOURCES})
endif()
#add_library(Engine SHARED ${EngineSOURCES})
## END project engine
project (Module_OpenGL_Renderer_Input)#project module_renderer_opengl3
include_directories(Libraries/glfw/include)
include_directories(Libraries/glm)
include_directories(Libraries/glad/include)
include_directories(Libraries/stb)
file(GLOB Module_OpenGL_Renderer_InputSOURCES "Modules/Module_OpenGL_Renderer_Input/src/*.cpp" "Modules/Module_OpenGL_Renderer_Input/src/*.h" "Libraries/glad/src/glad.c")
add_library(Module_OpenGL_Renderer_Input SHARED ${Module_OpenGL_Renderer_InputSOURCES})
target_link_libraries(glfw)
##END project module_renderer_opengl3
project (Test1)#project test | This project is used to test the engine functionality.
include_directories(Libraries/imgui)
file(GLOB Test1SOURCES "Tests/Test1/src/*.cpp" "Tests/Test1/src/*.h" "Libraries/imgui/imgui*.cpp" ${APISOURCES})
add_executable(Test1 ${Test1SOURCES})
target_link_libraries(Test1 ${CMAKE_DL_LIBS})
project (TestGame)#project test | This project is used to test the engine functionality.
include_directories(Libraries/imgui)
file(GLOB TestGameSOURCES "Tests/TestGame/src/*.cpp" "Tests/TestGame/src/*.h" "Libraries/imgui/imgui*.cpp" ${EngineRenderingSOURCES} ${EngineTypesSOURCES} ${EngineRenderingRenderablesSOURCES} ${EngineManagingSOURCES} ${EngineGameEssentialsSOURCES} ${EngineLibsSOURCES} ${EngineAppSOURCES} ${APISOURCES} ${EngineExtAppSOURCES} ${EngineExtAppGameSOURCES} ${EngineFrameworkSOURCES})
add_library(TestGame SHARED ${TestGameSOURCES})
target_link_libraries(TestGame glfw)
project (Editor)#project editor | This is used to make projects and build projects(using the engine)
include_directories(Libraries/imgui)
file(GLOB EditorSOURCES "Editor/src/*.cpp" "Editor/src/*.h" "Libraries/imgui/imgui*.cpp" ${APISOURCES})
add_executable(Editor ${EditorSOURCES})
I contains lot's of things that are completely useless, or not needed anymore.
So here are my questions:
Does every directory NEED a CMakeLists file, like I see in a lot of projects?
Do I need to provide every directory containing source files, or can I have it search automatically for source and header files in directories?
I also see that a lot of other CMake projects provide each source/header file seperately, why? Isn't that a lot of work every time you add a file?
Does anyone have examples of large CMake projects that I can use as a guide?
Is there ANYTHING else I can improve?
Thanks!
Does every directory NEED a CMakeLists file
No, that is not necessary.
It's probably a good idea to have a CMakeLists.txt for each submodule and library - and one in the root for the project itself.
Do I need to provide every directory containing source files, or can I have it search automatically for source and header files in directories?
Firstly, see the answer to your question 3.
Secondly, I don't see why you'd want to search for header files. Simply specify the include directories.
Finally, if you want to use globbing, it is possible to put all your source files under a single directory, and use a single glob.
I also see that a lot of other CMake projects provide each source ... file seperately, why?
This is what the docs say:
Note
We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate. The CONFIGURE_DEPENDS flag may not work reliably on all generators, or if a new generator is added in the future that cannot support it, projects using it will be stuck. Even if CONFIGURE_DEPENDS works reliably, there is still a cost to perform the check on every rebuild.
... each header file separately, why?
I've never seen this.
Is there ANYTHING else I can improve?
Use target_include_directories instead of include_directories. In general, always use target_X directives.

CMake with include and source paths - basic setup

I'm trying to set up a test project looking like my own project just to get things working first and it looks like this:
/MainProject/inc/main.h
/MainProject/src/main.cpp
/LibProject/inc/test.h
/LibProject/src/test.cpp
I've found some tutorials, but I cant find out how to set up this when I have the inc and src folder? How would the CMakeLists.txt files look? Would I have one in /, one in each of the project folders? It seems like I dont need to have one in the inc and src folders?
You need a CMakeLists.txt for each source subdirectory. Your structure should look something like this:
root
|-MainProject
| |-inc
| | '-main.h
| |-src
| | |-main.cpp
| | '-CMakeLists.txt
| '-CMakeLists.txt
|-LibProject
| |-inc
| | '-test.h
| |-src
| | |-test.cpp
| | '-CMakeLists.txt
| '-CMakeLists.txt
'-CMakeLists.txt
Content of root/CMakeLists.txt:
project(MyProject)
add_subdirectory(MainProject)
add_subdirectory(LibProject)
Content of LibProject/CMakeLists.txt and MainProject/CMakeLists.txt:
add_subdirectory(src)
Content of LibProject/src/CMakeLists.txt:
# Notice name prefix of this variable, set by CMake according
# to value given with "project()" in the root CMakeLists.txt.
include_directories(${MyProject_SOURCE_DIR}/LibProject/inc)
add_library(LibProject test.cpp)
Content of MainProject/src/CMakeLists.txt:
include_directories(${MyProject_SOURCE_DIR}/MainProject/inc)
# I assume you want to use LibProject as a library in MainProject.
include_directories(${MyProject_SOURCE_DIR}/LibProject/inc)
link_directories(${MyProject_SOURCE_DIR}/LibProject/src)
add_executable(MainProject main.cpp)
target_link_libraries(MainProject LibProject)
Then configure and build with:
$ cd root
$ mkdir build
$ cd build
$ cmake ..
$ make
You could do it like following.
CMakeLists.txt in your MainProject directory:
project(MainProject)
add_subdirectory(LibProject/src)
add_subdirectory(MainProject/src)
CMakeLists.txt in your LibProject/src directory:
include_directories(${PROJECT_SOURCE_DIR}/LibProject/inc/)
add_library(LibProject test.cpp)
CMakeLists.txt in your MainProject/src directory:
include_directories(${PROJECT_SOURCE_DIR}/MainProject/inc/)
add_executable(MainProject main.cpp)
target_link_libraries(MainProject LibProject)
In my case I wanted to do it with a single CMakeList. And it worked for me. I add my solution in case it serves to anyone.
This is what I did in my case:
My structure:
Project
|CMakeLists.txt
|-src
| |*.cpp
| |*.c
|-include
| |*.hpp
| |*.h
My CMakeLists.txt have to main parts:
include_directories(
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/src
)
^ Enables .cpp files to add headers in the include folder.
file(GLOB all_SRCS
"${PROJECT_SOURCE_DIR}/include/*.h"
"${PROJECT_SOURCE_DIR}/include/*.hpp"
"${PROJECT_SOURCE_DIR}/src/*.cpp"
"${PROJECT_SOURCE_DIR}/src/*.c"
)
^ Just add whatever is in those folders.
add_executable(MyTarget ${all_SRCS})
^ Build the target from the list of all sources
PS: if you want to see the full CMakeLists.txt go the the project link NEGU93/ForbiddenDesert.