我有一个C++程序,我正在构建与Clang3.9的配置文件引导优化功能。下面是应该发生的事情:
prof.raw创建一个文件。llvm-profdata将prof.raw转换为一个新文件prof.data。-fprofile-use=prof.data。-fprofile-use。
我有一个Gnu Makefile为这个,它的工作很好。现在出现了问题,因为我正在尝试将Makefile移植到CMake (3.7,但我可以升级)。我需要使用(至少) Unix生成器的解决方案,但理想情况下,它适用于所有生成器。
在CMake中,我定义了两个可执行目标:foo-gen和foo-use
foo-gen时,它会创建prof.raw文件。add_custom_command创建一个规则,从prof.raw创建prof.data。,我的问题是,我不知道如何告诉CMake,foo-use所依赖的每个对象文件都依赖于文件prof.data。
.o文件( foo-use所依赖的),然后(2)遍历每个.o文件,为每个文件调用add_dependency。
这种方法的问题在于,我无法在CMakeLists.txt文件中找到一种惯用的方法来枚举可执行文件所依赖的对象文件列表。这可能是是CMake的一个开放问题。set_source_files_properties在OBJECT_DEPENDS使用的每个.cpp文件上设置foo-use属性,将prof.data添加到该属性的列表中。
问题是,我的每个.cpp文件都用于创建两个不同的.o文件:一个用于foo-gen,另一个用于foo-use。我希望链接到foo-use的foo-use文件具有对prof.data的编译时依赖关系;但是链接到foo-gen的.o文件不能对prof.data.And AFAIK具有编译时依赖关系,set_source_files_properties不允许我将OBJECT_DEPENDS属性设置为两个值之一,这取决于foo-gen还是foo-use是当前感兴趣的目标。有什么建议可以使这项工作干净利落吗?
发布于 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-use的foo-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的,那么您将回到起点。
拟议解决方案
下面是我发现的在配置文件数据更改时重新编译源代码的工作方法:
COMMAND,它生成一个c++头文件,其中包含注释中的时间戳。如果您希望支持非PGO构建,请将时间戳标头包装在一个标头中,该标头检查它是否与__has_include一起存在,并且只在它存在时才包含它。
我非常肯定,使用这种方法,CMake不会对概要文件数据执行TUs的依赖检查,而是由生成的buildsystem的标头依赖跟踪完成这项工作。将时间戳注释包含在头文件中而不是仅仅“触摸”它以更改文件系统中时间戳的基本原理是,生成的构建系统可能通过文件内容而不是文件系统时间戳来检测更改。
建议的解决方案的所有缺点
这种方法的明显缺点是,需要在所有要重新编译的.cpp文件中添加一个标头包含。有几个问题可能由此产生(从至少到最令人震惊的):
ExternalProject步骤执行patch步骤,可能会有一些解决办法,但我不知道。不幸的是,我不知道如何解决这些问题。对于我的个人项目,#1和#2是可以接受的,而#3恰好不是一个问题。
https://stackoverflow.com/questions/42125009
复制相似问题