根据编译器版本有条件地包含源文件?

jww*_*jww 4 c++ msbuild visual-studio

我们正在测试一个项目设置,该设置要求我们根据编译器的版本包含或排除源文件。测试项目位于 GitHub 上的CRC-Test。对于 PoC,我们正在使用 CRC-32C 开发流程,因为 Intel 和 ARM 都有它。稍后将应用于 AES、CLMUL、SHA、AVX{2}、BMI{2}、ARMv7a NEON、ARMv8 等(MS 编译器通过内在函数支持 NEON 和 ARMv8)。

\n\n

我试图有条件编译的源文件是crc-simd.cpp. 它具有使用 SSE4.2 内在函数和 ARMv8 内在函数的实现(crc.cpp提供通用的 C++ 实现)。

\n\n

我在crc-test.vcxproj添加了一个 VCX 项目文件。有一个ItemGroupfor ClCompile

\n\n
<ItemGroup>\n  <ClCompile Include="main.cpp" >\n    <PrecompiledHeader />\n  </ClCompile>\n  <ClCompile Include="crc.cpp" >\n    <PrecompiledHeader />\n  </ClCompile>\n  <ClCompile Include="crc-simd.cpp" >\n    <PrecompiledHeader />\n  </ClCompile>\n</ItemGroup>\n
Run Code Online (Sandbox Code Playgroud)\n\n

我需要一个条件<ClCompile Include="crc-simd.cpp" >“如果cl.exe是 15.00 或更大,则包含源文件”。在预处理器中我会检查_MSC_VER >= 1500. 在 MSBuild 中,我想我正在寻找类似的东西:

\n\n
<ItemGroup Condition="\'$(CL_VERSION)\'>=\'15.00\'" Label="SSE4.2 acceleration">\n  <ClCompile Include="crc-simd.cpp" >\n    <PrecompiledHeader />\n  </ClCompile>\n</ItemDefinitionGroup>\n
Run Code Online (Sandbox Code Playgroud)\n\n

我找到了MSBuild 内置变量列表,但我不知道$(CL_VERSION)现实生活中是什么。搜索“cl”并没有产生有趣的结果。我在MSBuild vs compiler中发现了一个问题,但它提出了一个不同的问题。

\n\n

我的问题是,如何cl.exe在 MSBuild 条件中引用版本?

\n\n

一个相关的问题是,有时我需要完整版本。例如,VS2005 SP1cl.exe版本 15.00.30729 ( _MSC_FULL_VER >= 150030729) 添加了 AES 支持。我的相关问题是,如何在 MSBuild 条件中引用cl.exe 完整版本?

\n\n
\n\n

尝试从开发人员提示中使用以下内容:

\n\n
<ItemDefinitionGroup Condition="\'$(CL_VERSION)\'>=\'15.00\'" Label="SSE4.2 acceleration">\n  <ClCompile Include="crc-simd.cpp" >\n    <PrecompiledHeader />\n  </ClCompile>\n</ItemDefinitionGroup>\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果是:

\n\n
> cls && msbuild\n\nMicrosoft (R) Build Engine version 4.6.1087.0\n[Microsoft .NET Framework, version 4.0.30319.42000]\nCopyright (C) Microsoft Corporation. All rights reserved.\n\nBuild started 7/25/2017 1:23:31 PM.\nProject "C:\\Users\\Test\\CRC-Test\\crc-test.vcxproj" on node 1 (default ta\nrgets).\nC:\\Users\\Test\\CRC-Test\\crc-test.vcxproj(127,14): error MSB4066: The att\nribute "Include" in element <ClCompile> is unrecognized.\nDone Building Project "C:\\Users\\Test\\CRC-Test\\crc-test.vcxproj" (defaul\nt targets) -- FAILED.\n\nBuild FAILED.\n\n"C:\\Users\\Test\\CRC-Test\\crc-test.vcxproj" (default target) (1) ->\n  C:\\Users\\Test\\CRC-Test\\crc-test.vcxproj(127,14): error MSB4066: The a\nttribute "Include" in element <ClCompile> is unrecognized.\n\n    0 Warning(s)\n    1 Error(s)\n\nTime Elapsed 00:00:00.11\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

该项目当前针对 Visual Studio 2010 设置。如果您使用不同的版本,请更改此版本以适合您的口味。不需要VCUpgrade

\n\n
<PlatformToolset>v100</PlatformToolset>\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  • VS2010\xe2\x86\x92 v100
  • \n
  • VS2012\xe2\x86\x92 v110
  • \n
  • VS2013\xe2\x86\x92 v120
  • \n
  • VS2015 \xe2\x86\x92 v130
  • \n
  • VS2017\xe2\x86\x92 v140
  • \n
\n\n
\n\n

这是 Linux 上的项目的精华GNUmakefile。当编译器和平台支持硬件加速时,我们引入该crc-simd.cpp文件以加快实现速度。这就是我们想要用 MSBuild 做的事情。

\n\n
<PlatformToolset>v100</PlatformToolset>\n
Run Code Online (Sandbox Code Playgroud)\n

sti*_*ijn 5

可以使用与 makefile 类似的方法:运行 cl.exe,使用正则表达式获取版本,如果版本大于某个数字,则包含源文件。在代码中:

<Target Name="GetClVersion">
  <!-- Run cl, store output in variable -->
  <Exec Command="cl.exe" ConsoleToMSBuild="True" IgnoreExitCode="True">
    <Output TaskParameter="ConsoleOutput" PropertyName="ClOut" />
  </Exec>
  <PropertyGroup>
    <!-- cl.exe version number is something like 18.00.31101 -->
    <ClVersion>$([System.Text.RegularExpressions.Regex]::Match('$(ClOut)','(\d+\.\d+\.\d+)'))</ClVersion>
    <!-- Turn it into an integer like 180031101 by getting rid of dots -->
    <ClVersion>$([System.String]::Copy('$(ClVersion)').Replace('.', ''))</ClVersion>
  </PropertyGroup>
</Target>

<!-- This will run early in the build, before compilation,
     so we can modify the ClCompile ItemGroup. Needs to be done
     in a target, else we cannot use results from other targets
     (GetClVersion in this case) -->
<Target Name="ShowClVersion" DependsOnTargets="GetClVersion"
        BeforeTargets="BuildGenerateSources">
  <!-- &gt; = escaped > sign -->
  <ItemGroup Condition="$(ClVersion) &gt; 180031100">
    <ClCompile Include="somefile.cpp" />
  </ItemGroup>
</Target>
Run Code Online (Sandbox Code Playgroud)

注意:您找到的内置变量列表适用于 msbuild(构建系统),它与编译器是分开的;这就是为什么没有 CL_VERSION 就像 makefile 默认没有 GCC_VERSION 一样。也值得尝试使用

<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
Run Code Online (Sandbox Code Playgroud)

与其坚持单个项目或保留多个项目,不如每个 VS 版本一个。它还可以防止 VS 要求升级(因为它看到正在使用它的默认平台工具集)。我没有 2012 年以下的 VS 版本来测试它是否可以正常工作,但从 VS2012 开始就可以了,所以已经有 4 个版本了,而且还在增加。