首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在CMake 3.7中表达PGO依赖关系?

如何在CMake 3.7中表达PGO依赖关系?
EN

Stack Overflow用户
提问于 2017-02-08 22:39:50
回答 1查看 897关注 0票数 6

我有一个C++程序,我正在构建与Clang3.9的配置文件引导优化功能。下面是应该发生的事情:

  1. 我在启用仪器的情况下构建程序。
  2. 我运行这个程序,用profile-data:prof.raw创建一个文件。
  3. 我使用llvm-profdataprof.raw转换为一个新文件prof.data
  4. 我创建了同一个程序的新版本,并做了一些更改:
    • 当将每个.cpp文件编译为.o文件时,我使用编译器标志-fprofile-use=prof.data
    • 在链接可执行文件时,我还指定了-fprofile-use

我有一个Gnu Makefile为这个,它的工作很好。现在出现了问题,因为我正在尝试将Makefile移植到CMake (3.7,但我可以升级)。我需要使用(至少) Unix生成器的解决方案,但理想情况下,它适用于所有生成器。

在CMake中,我定义了两个可执行目标:foo-genfoo-use

  • 执行foo-gen时,它会创建prof.raw文件。
  • 我使用add_custom_command创建一个规则,从prof.raw创建prof.data

,我的问题是,我不知道如何告诉CMake,foo-use所依赖的每个对象文件都依赖于文件prof.data

  • 我最有希望的想法是:(1)找到一种方法来枚举所有.o文件( foo-use所依赖的),然后(2)遍历每个.o文件,为每个文件调用add_dependency。 这种方法的问题在于,我无法在CMakeLists.txt文件中找到一种惯用的方法来枚举可执行文件所依赖的对象文件列表。这可能是是CMake的一个开放问题
  • 我还考虑使用set_source_files_propertiesOBJECT_DEPENDS使用的每个.cpp文件上设置foo-use属性,将prof.data添加到该属性的列表中。 问题是,我的每个.cpp文件都用于创建两个不同的.o文件:一个用于foo-gen,另一个用于foo-use。我希望链接到foo-usefoo-use文件具有对prof.data的编译时依赖关系;但是链接到foo-gen.o文件不能对prof.data.And AFAIK具有编译时依赖关系,set_source_files_properties不允许我将OBJECT_DEPENDS属性设置为两个值之一,这取决于foo-gen还是foo-use是当前感兴趣的目标。

有什么建议可以使这项工作干净利落吗?

EN

回答 1

Stack Overflow用户

发布于 2022-09-01 18:39:17

论作者的思想#1

我最有希望的想法是:(1)找到一种方法来枚举所有.o文件( foo-use所依赖的),然后(2)遍历每个.o文件,为每个文件调用add_dependency

根据add_dependencies的文档,这不应该起作用,该文档声明:

使顶级的依赖于其他顶级目标,以确保它们在此之前构建。

即。您不能使用它来使目标依赖于文件--只依赖于其他目标。

论作者的思想#2

我还考虑使用set_source_files_properties在OBJECT_DEPENDS使用的每个.cpp文件上设置foo-use属性,将prof.data添加到该属性的列表中。 问题是,我的每个.cpp文件都用于创建两个不同的.o文件:一个用于foo-gen,另一个用于foo-use。我希望链接到foo-usefoo-use文件具有对prof.data的编译时依赖性;但是链接到foo-gen.o文件不能对prof.data具有编译时依赖关系。 而且,set_source_files_properties不允许我将OBJECT_DEPENDS属性设置为两个值中的一个,这取决于foo-gen还是foo-use是当前感兴趣的目标。

在注释部分,您提到如果OBJECT_DEPENDS支持生成器表达式,您可以解决这个问题,但它不支持。你可以向它竖起大拇指,描述你的用例,供他们参考。

在评论部分,您还提到了一种可能的解决方案:

可能的其他解决方案a)双项目系统,主用户调用项目将设置转发给第二个pgo项目,再次编译相同的设置。

实际上,您可以通过CMake将其放入ExternalProject项目中,从而使其成为生成的构建系统的一部分:使顶级项目本身包含为外部项目。外部项目可以传递一个缓存变量,将其配置为-gen版本,顶层可以是-use版本。

从经验来看,如果您以前从未使用ExternalProject手动调用或做过任何事情,那么这就是另一个冗长的CMake文档阅读和整理过程,因此这个答案可能属于一个专门针对它的新问题。

这可以解决在OBJECT_DEPENDS中没有生成器表达式的问题,但是如果您想为顶级项目拥有多个配置,并且在多配置配置中的一些配置不是针对PGO的,那么您将回到起点。

拟议解决方案

下面是我发现的在配置文件数据更改时重新编译源代码的工作方法:

  1. 在运行培训可执行文件并生成和重新格式化培训数据的自定义命令中,添加另一个COMMAND,它生成一个c++头文件,其中包含注释中的时间戳。
  2. 如果培训已经重新运行,请将该头包含在希望重新编译的所有源中。

如果您希望支持非PGO构建,请将时间戳标头包装在一个标头中,该标头检查它是否与__has_include一起存在,并且只在它存在时才包含它。

我非常肯定,使用这种方法,CMake不会对概要文件数据执行TUs的依赖检查,而是由生成的buildsystem的标头依赖跟踪完成这项工作。将时间戳注释包含在头文件中而不是仅仅“触摸”它以更改文件系统中时间戳的基本原理是,生成的构建系统可能通过文件内容而不是文件系统时间戳来检测更改。

建议的解决方案的所有缺点

这种方法的明显缺点是,需要在所有要重新编译的.cpp文件中添加一个标头包含。有几个问题可能由此产生(从至少到最令人震惊的):

  1. 从美学的角度来看,你可能不喜欢它。
  2. 它无疑为人为错误打开了一个漏洞,因为它忘记了包含新的.cpp文件的头。我不知道该怎么解决。
  3. 您可能无法更改需要重新编译的一些源,例如库所依赖的第三方静态库中的源。如果您通过使用ExternalProject步骤执行patch步骤,可能会有一些解决办法,但我不知道。

不幸的是,我不知道如何解决这些问题。对于我的个人项目,#1和#2是可以接受的,而#3恰好不是一个问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42125009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档