在 CMake 中具有依赖关系的自定义对象
Posted
技术标签:
【中文标题】在 CMake 中具有依赖关系的自定义对象【英文标题】:Custom object with dependencies in CMake 【发布时间】:2017-05-30 20:08:52 【问题描述】:我正在为一个使用 CMake 并具有单独的源目录和构建目录的项目贡献一个自定义功能(例如,MyFeature)。 MyFeature 由单个二进制文件组成。 (MyFeature 实际上是一个自定义 Simulink 库,所以我必须调用 MATLAB 来创建它——这里重要的是创建对象不涉及 GCC 或 CMake 使用的其他标准构建工具默认情况下。)所以我有一个特殊的规则来构建对象——比如说myRule。我希望 make 仅在 (a) MyFeature 不存在或 (b) 所在的一个源文件时运行 myRule MyFeature 取决于——例如,MySource——比当前存在的 MyFeature 更新。一个小的额外皱纹是我只需要在源代码树中的 MyFeature,这是 myRule 通常放置它的地方。我怎样才能完成这一切?
据我所知,我不能使用 add_executable 或 add_library,因为它们是为您使用 GCC 构建的对象(或者已经 -配置)工具链。我无法使用 add_custom_target,因为生成的目标总是过时。到目前为止,我使用 add_custom_target 和 add_custom_command 的组合取得了一些进展,如下:
add_custom_target(fakeTarget
DEPENDS MyFeature)
add_custom_command(OUTPUT MyFeature
COMMAND myRule && touch $CMAKE_CURRENT_BINARY_DIR/MyFeature
DEPENDS mySource)
add_dependencies(targetThatAlwaysRuns fakeTarget)
如果真正的 MyFeature 存在,那么在构建树中创建一个空 MyFeature 文件的命令似乎足以让 make 不重建(在源代码树中),这实现了我的目标之一。但是,一旦这个假文件存在,即使我在源代码树中更新 MySource,make 也不会重建 MyFeature。这就是我卡住的地方。这似乎特别令人费解,因为我可以在 CMakeFiles 内部看到 MyFeature 的目标确实列出了 MySource (路径正确--在源代码树中!)作为依赖项。如果我要尝试在单个目录中使用更简单的(玩具)Makefile 来复制这种情况,如果我更新目标所依赖的源文件之一,即使目标输出文件已经存在,make 会做正确的事——它将从更新的源重建对象,然后重建整个目标。那么为什么这种情况下的构建行为会有所不同呢?我能做些什么来实现目标(b)和目标(a)?谢谢!
【问题讨论】:
假设add_custom_rule
你的意思是add_custom_command
,你的方法应该有效。尝试在 DEPENDS 和 OUTPUT 选项中使用绝对路径。 “一个小问题是我真的只需要源树中的 MyFeature” - 没有什么能阻止您在源树中创建文件。
糟糕!是的,我的意思是 add_custom_command - 已编辑以解决此问题。没错,没有什么能阻止我在源代码树中创建文件。我正在解释我将一个空文件放入构建树中的原因。 CMake确实阻止我在源树中定义目标,因此,add_custom_command 中的输出文件也不能在源树中。
将绝对路径添加到 add_custom_command 中的 DEPENDS 选项有效!谢谢!
现在的问题是如何避免将虚拟 MyFeature 文件写入构建树以使 Make 跳过构建规则是否存在真正的 MyFeature。这个 hack 的问题在于,如果用户删除了源树中的真实 MyFeature:只要假的 MyFeature 仍在构建树,Make 不会重新生成 MyFeature。
不太明白:如果需要MyFeature
在源码树中生成,为什么要在二叉树中创建呢? ? add_custom_command
的 OUTPUT 也可以在源代码树中,使用绝对路径即可。
【参考方案1】:
正如 Tsyvarev 在他的评论中建议的那样,我所要做的就是用绝对路径指定 DEPENDS 依赖项:
add_custom_target(fakeTarget
DEPENDS MyFeature)
add_custom_command(OUTPUT MyFeature
COMMAND myRule && touch $CMAKE_CURRENT_BINARY_DIR/MyFeature
DEPENDS $CMAKE_CURRENT_SOURCE_DIR/mySource)
add_dependencies(targetThatAlwaysRuns fakeTarget)
但是,现在假设用户从源代码树中删除了真正的 MyFeature,然后再次运行 Make。 Make 不会重新生成 MyFeature,因为伪造的 MyFeature 仍然存在于构建树中。我该如何克服这个问题?
【讨论】:
以上是关于在 CMake 中具有依赖关系的自定义对象的主要内容,如果未能解决你的问题,请参考以下文章