我正在考虑将跨平台项目从 Visual C++、XCode 和 makefile 中的单独构建管理系统切换到 CMake。
我需要的一项基本功能是将目录中的所有文件自动添加到目标。虽然使用 make 很容易做到这一点,但使用 Visual C++ 和 XCode 却不容易做到(如果我错了,请纠正我)。是否可以直接在 CMake 中完成?如何?
从 CMake 3.1+ 开始,开发人员 强烈反对 用户使用file(GLOB或file(GLOB_RECURSE收集源文件列表。
file(GLOB
file(GLOB_RECURSE
注意: 我们不建议使用 GLOB 从源代码树中收集源文件列表。如果在添加或删除源时没有 CMakeLists.txt 文件更改,则生成的构建系统无法知道何时要求 CMake 重新生成。CONFIGURE_DEPENDS 标志可能无法在所有生成器上可靠地工作,或者如果将来添加不能支持它的新生成器,使用它的项目将被卡住。即使 CONFIGURE_DEPENDS 工作可靠,在每次重建时执行检查仍然是有成本的。
请参阅此处的文档。
这里有两个很好的答案([1]
CMake 的创建者自己建议不要使用通配符。
见:https ://cmake.org/cmake/help/v3.15/command/file.html?highlight=glob#file
(我们不建议使用 GLOB 从源代码树中收集源文件列表。如果在添加或删除源代码时没有更改 CMakeLists.txt 文件,则生成的构建系统无法知道何时要求 CMake 重新生成。)
当然,您可能想知道缺点是什么 -请继续阅读!
globbing 的最大缺点是创建/删除文件不会自动更新构建系统。
如果您是添加文件的人,这似乎是一个可以接受的权衡,但是这会给构建您的代码的其他人带来问题,他们从版本控制更新项目,运行构建,然后联系您,抱怨 “构建的破碎的”。
更糟糕的是,失败通常会给出一些链接错误,而这些错误并没有给出问题原因的任何提示,并且会浪费时间来解决问题。
在我从事的一个项目中,我们开始使用 globbing,但在添加新文件时收到了很多抱怨,因此有足够的理由明确列出文件而不是 globbing。
这也破坏了常见的 git 工作流程 (git bisect以及功能分支之间的切换)。
git bisect
所以我不能推荐这个,它导致的问题远远超过了方便,当有人因此无法构建你的软件时,他们可能会浪费很多时间来追踪问题或者干脆放弃。
另一个注意事项,仅仅记住触摸CMakeLists.txt并不总是足够的,对于使用 globbing 的自动构建,我必须在每次构建cmake之前运行,因为自上次构建以来可能已经添加/删除了文件*.
CMakeLists.txt
cmake
有时使用 globbing 更可取:
*是的,我本可以编写代码来比较更新前后磁盘上的文件树,但这不是一个很好的解决方法,最好留给构建系统。
[2]),详细说明了手动列出源文件的原因。
有可能的。例如file(GLOB:
cmake_minimum_required(VERSION 2.8) file(GLOB helloworld_SRC "*.h" "*.cpp" ) add_executable(helloworld ${helloworld_SRC})
请注意,如果添加或删除源文件,这需要 手动 重新运行cmake,因为生成的构建系统不知道何时要求 CMake 重新生成,并且在每次构建时都这样做会增加构建时间。
从 CMake 3.12 开始,您可以将CONFIGURE_DEPENDS标志传递给以file(GLOB在调用构建时自动检查和重置文件列表。你会写:
CONFIGURE_DEPENDS
cmake_minimum_required(VERSION 3.12) file(GLOB helloworld_SRC CONFIGURE_DEPENDS "*.h" "*.cpp")
这至少可以避免每次添加文件时手动重新运行 CMake。