具有多个目录的大型项目的CMakeLists?

时间:2018-10-24 12:34:05

标签: c++ cmake

我正在编写一个运行良好的游戏引擎。但是我遇到了一个问题,我的CMakeLists.txt太乱了,而我对CMake的了解还不够。我的项目使用多个(CMake)库,这些库是使用add_subdirectory,然后使用target_link_libraries添加的。我的项目由Engine(可执行文件),Editor(库)和一些测试/示例组成。这是我的文件结构:

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

如您所见,我一开始就有一个CMakeLists,它加载了所有项目。然后我有了库,也有CMakeLists。每个目录只有一个文件以使树变小,但是一个目录中有多个文件。另外,这是我当前的,混乱的,几乎没有用的CMakeLists文件:

    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})

我包含了很多完全没用或不再需要的东西。 所以这是我的问题:

  1. 每个目录是否都需要一个CMakeLists文件,就像我在许多项目中看到的那样?
  2. 我是否需要提供每个包含源文件的目录,还是可以自动搜索目录中的源文件和头文件?
  3. 我还看到许多其他CMake项目分别提供每个源文件/头文件,为什么?每次添加文件不是很多工作吗?
  4. 有人可以作为指导使用大型CMake项目的例子吗?
  5. 还有什么我可以改善的吗?

谢谢!

1 个答案:

答案 0 :(得分:3)

  
      
  1. 每个目录都需要一个CMakeLists文件
  2.   

不,那不是必需的。

对每个子模块和库都有一个CMakeLists.txt可能是一个好主意-在项目本身的根目录中有一个。

  
      
  1. 我是否需要提供每个包含源文件的目录,还是可以自动搜索目录中的源文件和头文件?
  2.   

首先,查看问题3的答案。

其次,我不明白为什么您要搜索头文件。只需指定包含目录即可。

最后,如果您想对建议使用通配符,则可以将所有源文件放在一个目录下,并使用一个通配符。

  
      
  1. 我还看到许多其他CMake项目分别提供每个源...文件,为什么?
  2.   

因为CMake在全局缓存方面存在问题,并且在添加新文件或删除旧文件时​​无法重新编译。 CMake文档说:

  

注意

     

我们不建议使用GLOB从源代码树中收集源文件列表。如果在添加或删除源时没有CMakeLists.txt文件更改,则生成的生成系统无法知道何时要求CMake重新生成。 CONFIGURE_DEPENDS标志可能无法在所有生成器上可靠地工作,或者如果将来添加了不支持它的新生成器,使用该生成器的项目将被卡住。即使CONFIGURE_DEPENDS能够可靠地工作,在每次重新构建上执行检查仍然会产生成本。


  
      
  1. ...每个头文件分开,为什么?
  2.   

我从未见过。

  
      
  1. 还有什么我可以改善的吗?
  2.   

使用target_include_directories代替include_directories。通常,请始终使用target_X指令。