在 CMake 中具有依赖关系的自定义对象

Posted

技术标签:

【中文标题】在 CMake 中具有依赖关系的自定义对象【英文标题】:Custom object with dependencies in CMake 【发布时间】:2017-05-30 20:08:52 【问题描述】:

我正在为一个使用 CMake 并具有单独的源目录和构建目录的项目贡献一个自定义功能(例如,MyFeature)。 MyFeature 由单个二进制文件组成。 (MyFeature 实际上是一个自定义 Simulink 库,所以我必须调用 MATLAB 来创建它——这里重要的是创建对象不涉及 GCC 或 CMake 使用的其他标准构建工具默认情况下。)所以我有一个特殊的规则来构建对象——比如说myRule。我希望 ma​​ke 仅在 (a) MyFeature 不存在或 (b) 所在的一个源文件时运行 myRule MyFeature 取决于——例如,MySource——比当前存在的 MyFeature 更新。一个小的额外皱纹是我只需要在源代码树中的 MyFeature,这是 myRule 通常放置它的地方。我怎样才能完成这一切?

据我所知,我不能使用 add_executableadd_library,因为它们是为您使用 GCC 构建的对象(或者已经 -配置)工具链。我无法使用 add_custom_target,因为生成的目标总是过时。到目前为止,我使用 add_custom_targetadd_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 文件的命令似乎足以让 ma​​ke 不重建(在源代码树中),这实现了我的目标之一。但是,一旦这个假文件存在,即使我在源代码树中更新 MySourcema​​ke 也不会重建 MyFeature。这就是我卡住的地方。这似乎特别令人费解,因为我可以在 CMakeFiles 内部看到 MyFeature 的目标确实列出了 MySource (路径正确--在源代码树中!)作为依赖项。如果我要尝试在单个目录中使用更简单的(玩具)Makefile 来复制这种情况,如果我更新目标所依赖的源文件之一,即使目标输出文件已经存在,ma​​ke 会做正确的事——它将从更新的源重建对象,然后重建整个目标。那么为什么这种情况下的构建行为会有所不同呢?我能做些什么来实现目标(b)和目标(a)?谢谢!

【问题讨论】:

假设add_custom_rule 你的意思是add_custom_command,你的方法应该有效。尝试在 DEPENDSOUTPUT 选项中使用绝对路径。 “一个小问题是我真的只需要源树中的 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,然后再次运行 MakeMake 不会重新生成 MyFeature,因为伪造的 MyFeature 仍然存在于构建树中。我该如何克服这个问题?

【讨论】:

以上是关于在 CMake 中具有依赖关系的自定义对象的主要内容,如果未能解决你的问题,请参考以下文章

数据流分析软件SQLFlow的自定义配置

用在张量流中具有变量依赖性的自定义操作替换图中的节点

CMake基础教程(30)CMake构建系统概览

CMake基础教程(30)CMake构建系统概览

如何为依赖于关系的自定义 Core Data 属性发布通知?

CMake:如何添加仅针对一种配置执行的自定义命令?