【问题标题】:CMake alternative to 'add_executable' by file names [duplicate]CMake通过文件名替代“add_executable”[重复]
【发布时间】:2021-03-18 23:28:16
【问题描述】:

我对 CMake 完全陌生,从未使用过它,总是像普通人一样依赖 VS 自动管理系统。我正在做一个学校作业,我正在制作一个游戏,我正在使用 CLion,因为已经为它制作了模板。

我必须将我创建的每个新文件都添加到 CMake 'add_executable' 关键字中才能编译,并且列表变得相当长。

# project
add_executable(project
        src/project/main.cpp
        src/project/Scenes/SceneMenu/SceneMenu.cpp
        src/project/Scenes/SceneMenu/SceneMenu.h
        src/project/Objects/Object.h
        src/project/Camera/Camera.h
        src/project/Camera/CameraGame/CameraGame.cpp
        src/project/Camera/CameraGame/CameraGame.h
        src/project/Scenes/SceneGame/SceneGame.cpp
        src/project/Scenes/SceneGame/SceneGame.h
        src/project/Scenes/Scene.h
        src/project/Scenes/SceneController.h
        src/project/Objects/Menu/Ball/Ball.h
        src/project/Objects/Menu/Ball/Ball.cpp
        src/project/Objects/Game/Church/Church.h
        src/project/Objects/Game/Church/Church.cpp
        src/project/Objects/Game/Leg/Leg.h
        src/project/Objects/Game/Leg/Leg.cpp
        src/project/Objects/Game/Ground/Ground.h
        src/project/Objects/Game/Ground/Ground.cpp
        src/project/Objects/Axial/Axis.h
        src/project/Objects/Axial/Axis.cpp
        src/project/Objects/Game/Leg/LegLower.h
        src/project/Objects/Game/Leg/LegLower.cpp
        src/project/Objects/Game/Skybox/Skybox.cpp
        src/project/Objects/Game/Skybox/Skybox.h
        src/project/Objects/Game/Mountain/Mountain.cpp
        src/project/Objects/Game/Mountain/Mountain.h
        src/project/Objects/Game/Mountain/MountainSpawner.h
        src/project/resources.h
        src/project/Animations/Bezierpath.h
        src/project/Camera/CutsceneCamera/CutsceneCamera.cpp
        src/project/Camera/CutsceneCamera/CutsceneCamera.h
        src/project/Scenes/SceneCut/SceneCut.cpp
        src/project/Scenes/SceneCut/SceneCut.h)

target_link_libraries(project ppgso shaders)
install(TARGETS project DESTINATION .)

file(COPY "data/" DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
install(DIRECTORY data/ DESTINATION .)

有什么方法可以改进吗?.. 也许是我不必添加我创建的每个新源文件的方法,或者这是唯一的方法?

这样做很烦人,因为它在重构或重构期间发生在我身上几次,由于 CMakeLists.txt 中某些文件的错误顺序或某些未重命名,它无法编译自动,甚至被删除

【问题讨论】:

  • 你希望 CMake 收集目录中的所有源(或目录)吗?如果是,请查看该问题:stackoverflow.com/questions/3201154/…。否则,不清楚您想在长长的源文件列表中改进什么。
  • 这正是我想要的。 GLOB_RECURSE 是我的救星。谢谢,我很难找到这个
  • @JackAvante 不要全局查找源文件。 The documentation even tells you not to do it.
  • Verbatim:“我们不建议使用 GLOB 从源代码树中收集源文件列表。如果在添加或删除源时没有 CMakeLists.txt 文件更改,则生成的构建系统无法知道何时要求 CMake 重新生成。CONFIGURE_DEPENDS 标志可能无法在所有生成器上可靠地工作,或者如果将来添加了一个不能支持它的新生成器,使用它的项目将被卡住。即使 CONFIGURE_DEPENDS 可靠地工作,每次重建都需要进行检查。”

标签: cmake


【解决方案1】:

您必须以一种或另一种方式指定源文件列表。

根据我的经验,最好的方法是将单个二进制文件拆分为较小的部分,每个部分都有自己的命名空间或目录,然后将它们组合在一起。

小贴士:

  • 将 CMakeLists.txt 放在 every 目录中,然后在父级 CMakeLists.txt 中使用 add_subdirectory(dir)
  • OBJECT 库用于主库/二进制文件的“部分”。
  • 将所有h/hpp文件放入include目录(任意目录结构)
  • 将所有cpp文件放入src目录(目录结构镜像include
  • 永远不要将h/hpp文件添加到add_{executable,library},它没有效果。
  • install 仅限 include 目录

您的项目可能如下所示:

.
├── CMakeLists.txt
├── include
│   └── projname
│       ├── myexe.hpp
│       └── mylib
│           └── mylib.hpp
└── src
    ├── CMakeLists.txt
    ├── myexe.cpp
    └── mylib
        ├── CMakeLists.txt
        └── mylib.cpp

根 CMakeLists.txt 所在的位置:

include_directories(include)
add_subdirectory(src)

src/mylib/CMakeLists.txt 有:

add_library(mylib OBJECT
  mylib.cpp
  )

那么src/CMakeLists.txt 有:

add_subdirectory(mylib)

add_executable(myexe 
  # this adds all cpps from mylib as if you enumerate them here
  $<TARGET_OBJECTS:mylib>
  myexe.cpp
  )

然后,要包含您的标题,请执行以下操作:

#include <projname/mylib/mylib.hpp>
#include <projname/myexe.hpp>

附:我专业地做 C++/CMake,这是我几年后最终形成的结构。 你可以看到实现了这个here的repo。

【讨论】:

  • 我的理解是,将标头添加到目标的源属性确实有效果。生成 Xcode/VS 项目时很重要,否则它们不会在其 GUI 中显示这些文件。
  • 另外,除非OBJECT 库在多个目标之间共享,否则我更喜欢target_sources,因为它不那么复杂。但是OTOH,如果生成了其中一个源,那将不起作用。啊,CMake。
  • @AlexReinking OBJECT 库有一个优势——您可以通过 target_include_directories/target_compile_options/ 放置专用的编译/链接器标志、包含等...在大型项目中非常有用。
  • 那时我开始在静态库中工作。
  • @AlexReinking 如果您想为主库添加install 步骤,您可能希望避免创建太多静态库。在这种情况下,您需要为 every 静态库添加install 步骤,并在安装主库时安装所有这些。使用对象库,它会更好地工作 - 您只需指定单个 install 步骤(用于主库)
猜你喜欢
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
  • 2018-10-22
  • 1970-01-01
  • 1970-01-01
  • 2017-11-12
  • 2016-10-08
  • 1970-01-01
相关资源
最近更新 更多