c++ c制造+ vcpkg:如何验证VC/Windows版本平台工具集?

nnt7mjpx  于 2023-03-05  发布在  Windows
关注(0)|答案(1)|浏览(358)

我有一个同时面向windows和linux的cmake项目,对于windows构建,我使用VCPKG_TARGET_TRIPLET指定v142平台工具集,并使用一个自定义三元组指定适当的VCPKG_PLATFORM_TOOLSET,因为我的库的用户仍然使用VS 2019和v142工具集进行构建。
这是我自定义的三胞胎:

set(VCPKG_TARGET_ARCHITECTURE x86)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_PLATFORM_TOOLSET "v142")

通过将VCPKG_TARGET_TRIPLET缓存变量设置为与我的自定义三元组的名称相等,它将通过cmake传递给vcpkg(是的,我删除了cmake缓存,并在再次构建之前运行了configure)。
我的项目中的一切都构建得很好,vcpkg输出显示它正在使用我的三元组。当试图将我的静态库链接到使用它的应用程序中时,它适用于调试构建;但发布版本失败,并出现以下错误:

1>LINK : fatal error C1007: unrecognized flag '-Zc:nrvo' in 'p2'
1>LINK : fatal error LNK1257: code generation failed

我没有明确设置这个标志,但是根据this documentation,当使用permissive-(我正在使用)时,它在最新的工具集版本中自动启用。这个特殊的链接器标志只在VS 2022版本17.4或更高版本(v143工具集)中支持。所以我只能得出结论,不知何故,我的库是用错误的工具集构建的。
关于如何排除故障/修复这个问题有什么想法吗?我尝试过将--debug传递给vcpkg来排除故障,但是当我查看vcpkg-manifest-install.log时,我没有看到任何指示发生了什么的内容。v143工具集只显示在与vcpkg用于编译器检测的主机三元组相关的日志文件中。当构建目标时,它似乎使用了我的自定义三元组。我甚至尝试为VCPKG_HOST_TRIPLET变量指定我的自定义三元组,但这似乎对我得到的错误没有任何影响(尽管它确实删除了日志中显示的对v143工具集的引用)。

sgtfey8w

sgtfey8w1#

所以我现在基本上已经开始工作了,我想我应该把我的发现记录下来,因为在网络上关于这个主题的很少。
第一个问题是,当使用CMakePresets.json时,当VSCode或Visual Studio等IDE打开您的项目时,它们会根据预设中的属性配置构建环境。因此,如果预设中没有任何内容告诉IDE要使用的工具集,您将安装最新的工具集。
第二个也是更大的问题是,即使VCPKG知道如何正确配置平台工具集和其他变量,但在cmake/ninja/vcpkg构建的情况下,它实际上并没有这样做。VCPKG将使用现有环境,并使用错误的平台工具集进行静默构建。在ninja中使用cmake时,设置三个一组的VCPKG_PLATFORM_TOOLSET/VCPKG_PLATFORM_TOOLSET_VERSION对构建没有影响。
我不知道是否有什么冗长复杂的解释,或者这只是一个bug,但至少,我真的认为如果VCPKG检测到当前的构建环境与指定的三元组中的内容不匹配,它应该创建一个警告或错误。
对于IDE场景,我发现了一些不同的建议,但实际上并不奏效。如果你想指定平台工具集,你需要将以下部分添加到你的CMakePreset(使用适合你需要的版本号-在我的情况下,这是VS 2019中最新的v142平台工具集):

"toolset": { "value": "version=14.29", "strategy": "external" }

这是IDE了解所需生成环境的唯一方法。
从命令提示符进行构建稍微困难一些。例如,如果您安装了带有v142和v143工具集的VS 2022,则无法使用Visual Studio安装程序创建的任何开发人员命令提示符快捷方式进入命令提示符以使用v142进行构建。我发现加载正确环境的唯一方法是调用:

%ProgramFiles%\Microsoft Visual Studio\2022\Professional\Common7\Tools\VsDevCmd.bat -vcvars_ver="14.29"

此时,您正处于可以使用正确工具集进行构建的命令提示符下。
不幸的是,没有简单的方法将这些变量加载到Powershell中。Launch-VsDevShell.ps1不支持"-vcvars_ver"参数;运行VsDevCmd.bat将进入cmd.exe命令提示符,这意味着当您退出返回Powershell时,环境变量将消失。
由于我使用Powershell脚本在命令行上(以及在CI中)进行构建,这确实是一个真实的的麻烦。我发现的唯一方法是使用Powershell用户社区扩展中的Invoke-Batchfile cmdlet。这基本上是有效的,尽管看起来比必要的麻烦更多。
VCPKG也有一个“cmd”命令,它将为您加载构建环境,但它会启动一个新的cmd.exe会话来创建环境,这意味着不能从脚本使用此功能(除非您将脚本分解并将“内部”脚本传递给vcpkg命令,但这只是一个丑陋的黑客攻击,应该工作得更好IMHO)。
TLDR:总而言之,如果您想使用cmake/ninja/vcpkg构建,使用的平台工具集不是最新安装的,您需要执行以下操作:

  • 将“toolset”属性添加到CMakePreset,以便IDE知道要加载哪个工具集
  • 调用VsDevCmd.bat -vcvars_var=“14.xx”设置命令行构建环境。
  • 不必麻烦设置三个一组的VCPKG_PLATFORM_TOOLSET/VCPKG_PLATFORM_TOOLSET_VERSION,它们不起作用。

相关问题