C++ 多目录大型项目的CMakList?

C++ 多目录大型项目的CMakList?,c++,cmake,C++,Cmake,我正在写一个游戏引擎,进展很顺利。但我遇到了一个问题,我的CMakeLists.txt太乱了,我对CMake了解不够。我的项目使用多个(CMake)库,这些库是使用add_子目录添加的,然后使用target_link_库添加的。我的项目由引擎(可执行)、编辑器(库)和一些测试/示例组成。以下是我的文件结构: C:. | CMakeLists.txt | tree.txt | +---Editor | | README.md | | | \---src |

我正在写一个游戏引擎,进展很顺利。但我遇到了一个问题,我的CMakeLists.txt太乱了,我对CMake了解不够。我的项目使用多个(CMake)库,这些库是使用add_子目录添加的,然后使用target_link_库添加的。我的项目由引擎(可执行)、编辑器(库)和一些测试/示例组成。以下是我的文件结构:

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})
我包含了很多完全无用或不再需要的东西。 下面是我的问题:

  • 是否每个目录都需要一个CMakeLists文件,就像我在很多项目中看到的那样
  • 我是否需要提供包含源文件的每个目录,或者我可以让它在目录中自动搜索源文件和头文件
  • 我还看到许多其他CMake项目分别提供每个源/头文件,为什么?每次添加文件不是都要做很多工作吗
  • 有谁有大型CMake项目的例子可以作为指导
  • 还有什么我可以改进的吗
  • 谢谢

  • 是否每个目录都需要一个CMakeLists文件
  • 不,没有必要

    每个子模块和库都有一个CMakeLists.txt,项目本身在根目录中也有一个,这可能是个好主意

  • 我是否需要提供包含源文件的每个目录,或者我可以让它在目录中自动搜索源文件和头文件
  • 首先,看问题3的答案

    其次,我不明白你为什么要搜索头文件。只需指定include目录

    最后,如果您想使用globbing,可以将所有源文件放在一个目录下,并使用一个glob

  • 我还看到许多其他的CMake项目提供了每个源。。。分开归档,为什么
  • 这些文件是这样说的:

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


  • 。。。每个头文件是分开的,为什么
  • 我从没见过这个

  • 还有什么我可以改进的吗

  • 使用
    target\u include\u目录
    而不是
    include\u目录
    。通常,请始终使用
    target\u X
    指令。

    谢谢您的回答!让我来回答你所说的:子模块的示例是什么?什么是子模块?我还想添加头文件,因为我有时使用VisualStudio,它显示的文件与其他IDE不同。每当我添加一个文件时,我总是重新配置并重新生成我的项目,我想这应该没问题。但是,在CMakeLists文件中添加每个文件不是需要很多工作吗,或者人们是否以某种方式实现了自动化?现在我将使用target_include_目录表单。@TimLeijten模块是一个自包含的单元。子模块是另一个模块的一部分。可执行文件是模块的示例,库是子模块的示例。我提到它只是为了防止您有一个子模块,而您不会将其描述为库。@TimLeijten在我看来,每次添加/删除源文件时更改CMakeLists.txt文件并不需要很多工作,但我同意这很烦人,而且会重复文件系统中的信息。但这就是CMake的设计,尽管它可能有缺陷。有些IDE会自动编辑CMakeLists.txt。问题是,我的项目并没有真正使用模块作为基础,物理之类的东西是它自己的模块,但是渲染、基类、场景管理、资源管理等都在同一个项目/模块中。这是否意味着我使用了一个CMakeLists?您是否知道任何自动修改CMakeLists的IDE?或者一个插件。(对于VS或CLion)在“大型项目”中使用CMake没有通用的方法。但是大多数这样的项目使用不止一个
    CMakeLists.txt
    (在不同的目录中)。您在一个问题帖子中问了太多问题,这在堆栈溢出时是不受欢迎的。您可以先将
    CMakeLists.txt
    拆分为几个目录,然后询问您将面临的具体问题。@Tsyvarev但我该如何做,它会是什么样子?很抱歉在一篇文章中问了太多问题,我想如果我把它分成单独的问题,它会被视为垃圾邮件。位于子目录中的
    CMakeLists.txt
    通常只处理该子目录中的文件,例如
    Editor/CMakeLists.txt
    可以编译
    Editor/src/main.cpp
    源代码。根据第一个问题,您已经看到许多项目在每个目录中使用
    CMakeLists.txt
    。为什么不直接关注这样的项目呢?@Tsyvarev谢谢你的回复。嗯,我知道的唯一使用CMake的大型库/项目是GLFW和Bullet,我想不出其他的。你知道一些吗?