为啥 cmake 文件 GLOB 是邪恶的?
Posted
技术标签:
【中文标题】为啥 cmake 文件 GLOB 是邪恶的?【英文标题】:Why is cmake file GLOB evil?为什么 cmake 文件 GLOB 是邪恶的? 【发布时间】:2015-12-01 10:23:39 【问题描述】:CMake 文档中提到了命令 file GLOB:
我们不建议使用 GLOB 从源代码树中收集源文件列表。如果在添加或删除源时没有 CMakeLists.txt 文件发生更改,则生成的构建系统无法知道何时要求 CMake 重新生成。
网络上的几个讨论线程秒,通配源文件是邪恶的。
但是,要让构建系统知道某个源已被添加或删除,只需说明一下
touch CMakeLists.txt
对吗?
这比编辑CMakeLists.txt
来插入或删除源文件名要省力。也不是更难记住。所以我看不出有什么好的理由反对file GLOB
。
这个论点有什么问题?
【问题讨论】:
另见讨论here。正如我的回答中所述,我使用了一种混合方法:在CMakeLists.txt
文件中列出所有源文件(也因为有时我会为不同的构建配置手动挑选源文件)和头文件的通配符(出于方便使用它们在 VS 项目中)。我建议了一个解决方法,例如git
与 configure_file($CMAKE_SOURCE_DIR/.git/index $PROJECT_BINARY_DIR/git_index.tmp)
类似。
【参考方案1】:
问题是当你不是一个人在做一个项目时。
假设项目有开发者 A 和 B。
A 添加一个新的源文件x.c
。他不会更改 CMakeLists.txt
并在他完成实现 x.c
后提交。
现在 B 做了一个 git pull
,由于没有对 CMakeLists.txt
进行修改,CMake 不会再次运行,并且 B 在编译时会导致链接器错误,因为 x.c
尚未添加到其源文件中列表。
2020 年编辑:CMake 3.12 向 file(GLOB
引入了 CONFIGURE_DEPENDS
参数,这使得 globbing 扫描新文件:https://cmake.org/cmake/help/v3.12/command/file.html#filesystem
然而,这不是可移植的(因为 Visual Studio 或 Xcode 解决方案不支持该功能)所以请仅将其用作第一个近似值,否则其他人可能无法在他们选择的 IDE 下构建您的 CMake 文件!
【讨论】:
好点,谢谢。在我接受这个答案(并可能开始考虑解决方法)之前,请让我等一下,看看是否会提出更多问题。 @Jean-MichaëlCelerier 解决方法#1:在 git pull 之后运行 cmake(严重),解决方法#2:在CMakeLists
中,将 globbing 的结果写入文件(有条件地,如果它没有'不存在)并将其置于源代码控制之下。使CMakeLists
包含该文件。添加新文件时,删除 globresult 文件。
我不同意这些变通方法:第一种方法是在添加文件的人以外的人身上工作(根据经验,这不适用于 >3 人)。第二个为开发人员增加了更多的精神开销(在我的 CMakeLists 中添加文件和记住创建/删除文件之间......)。
@Jean-MichaëlCelerier :嗯,这是没有免费午餐的事情。我认为 sw 开发人员是聪明人,可以相信记住 #1 或进行心理飞跃 #2。但当然,选择应该取决于项目、观众和品味。每个替代方案(包括手动编辑CMakeList
)都有其缺点。
@Uri:不,因为 globbing 本身的概念不能移植到 CMake 支持的所有构建类型 - 例如,它在 Visual Studio 解决方案或 XCode 项目中如何工作?【参考方案2】:
这不是 固有的 邪恶 - 它有优点和缺点,在 *** 上的 this answer 中得到了较好的介绍。但是如果你不小心使用它,你最终可能会忽略依赖关系的变化,并需要对大部分代码库进行干净的重建。
我个人赞成在较小的项目中或在较大项目的某些子目录中使用它,以避免必须手动将每个文件输入到构建文件中。 编辑:我的偏好发生了变化,目前我倾向于避免它。
【讨论】:
有许多微妙的情况,在某些情况下,您必须将干净的构建作为唯一的救援。我认为它不适合大型项目 @Fei:这取决于你正在构建什么。在一个大型项目中,您可能会为其中的一小部分设置全局变量,但对于整个项目来说肯定不是。 我的偏好也发生了变化,但从避免 globbing 到到处使用它,至少在同事允许的地方。我敢打赌你会再次改变你的偏好并编写一些脚本来让 globbing 更安全。 @PatrickFromberg:所以,答案的那一部分谈到了个人偏好;一般部分代表我是否喜欢更多,更少或根本不...... 我支持你的观点,手动添加文件色调很糟糕。不要告诉我有关 aux_source_directory 的事情。【参考方案3】:除了其他人在这里发布的原因之外,恕我直言,glob 最糟糕的问题是它可以在不同的平台上产生不同的文件列表。在我看来,这是一个错误。在 OSX glob 中会忽略大小写,而在 ubuntu 中则不会。
【讨论】:
这听起来令人担忧——您能在 CMake 开发人员邮件列表中提出它吗? 我听从了您的建议并试图打开问题,但是,我发现有人在 3 年前就已经这样做了 :-) gitlab.kitware.com/cmake/cmake/issues/15941【参考方案4】:通配符会破坏诸如 CLion 之类的所有代码检查,否则它们会理解 CMakeLists.txt 的有限子集,并且不会也永远不会支持通配符,因为它是不安全的。
编写脚本转储 globbed 列表并将其粘贴进去,非常简单,然后 CLion 可以实际找到引用的文件并推断它们是否有用。甚至可以将这样的脚本放入树中,以便其他开发人员可以运行它而不是白痴,或者设置 git 挂钩来实现它。
在任何情况下,掉入某个目录的随机文件都不应该被自动链接,这就是特洛伊木马的发生方式。
此外,没有上下文跳转到已知定义的 CLion 就像赤脚徒步旅行 /// 何必呢。
【讨论】:
甚至没有脚本:只是 Vim 中的:read ! ls *.cc *.hh
,bam,就是你的文件列表。以上是关于为啥 cmake 文件 GLOB 是邪恶的?的主要内容,如果未能解决你的问题,请参考以下文章
C++学习(四九二)cmake file的GLOB和GLOB_RECURSE
C++学习(四九二)cmake file的GLOB和GLOB_RECURSE