有条件地包括基于编译器版本的源文件吗? [英] Conditionally include source file based on compiler version?

查看:67
本文介绍了有条件地包括基于编译器版本的源文件吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We are testing a project setup that requires us to include or exclude a source file based on the compiler's version. The test project is located on GitHub at CRC-Test. For the PoC, we are developing the process with CRC-32C since both Intel and ARM have it. Later it will be applied to AES, CLMUL, SHA, AVX{2}, BMI{2}, ARMv7a NEON, ARMv8, etc. (MS compilers support NEON and ARMv8 through intrinsics).

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

The source file I am trying to conditionally compile is crc-simd.cpp. It has implementations using SSE4.2 intrinsics and ARMv8 intrinsics (crc.cpp provides the generic, C++ implementation).

我在 crc-test中添加了VCX项目文件. vcxproj . ClCompile有一个ItemGroup:

<ItemGroup>
  <ClCompile Include="main.cpp" >
    <PrecompiledHeader />
  </ClCompile>
  <ClCompile Include="crc.cpp" >
    <PrecompiledHeader />
  </ClCompile>
  <ClCompile Include="crc-simd.cpp" >
    <PrecompiledHeader />
  </ClCompile>
</ItemGroup>

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

I need a conditional for <ClCompile Include="crc-simd.cpp" > that says, "if cl.exe is 15.00 or greater, then include the source file". In the preprocessor I would check for _MSC_VER >= 1500. In MSBuild I think I am looking for something like:

<ItemGroup Condition="'$(CL_VERSION)'>='15.00'" Label="SSE4.2 acceleration">
  <ClCompile Include="crc-simd.cpp" >
    <PrecompiledHeader />
  </ClCompile>
</ItemDefinitionGroup>

我找到了 MSBuild内置变量列表,但我不知道$(CL_VERSION)到底是什么生活.搜寻"cl"并没有引起有趣的点击.我在 MSBuild与编译器中发现了一个问题,但它提出了另一个问题.

I found List of MSBuild built-in variables, but I don't know what $(CL_VERSION) is in real life. Seraching for "cl" did not result in interesting hits. I found one question at MSBuild vs compiler, but its asking a different question.

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

My question is, how do I reference the cl.exe version in a MSBuild conditional?

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

A related problem is, sometimes I need the full version. For example, AES support was added at VS2005 SP1, cl.exe version 15.00.30729 (_MSC_FULL_VER >= 150030729). My related question is, how do I reference the cl.exe full version in a MSBuild conditional?

尝试在开发者提示下使用以下内容:

Trying to use the following from a developer prompt:

<ItemDefinitionGroup Condition="'$(CL_VERSION)'>='15.00'" Label="SSE4.2 acceleration">
  <ClCompile Include="crc-simd.cpp" >
    <PrecompiledHeader />
  </ClCompile>
</ItemDefinitionGroup>

结果:

> cls && msbuild

Microsoft (R) Build Engine version 4.6.1087.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 7/25/2017 1:23:31 PM.
Project "C:\Users\Test\CRC-Test\crc-test.vcxproj" on node 1 (default ta
rgets).
C:\Users\Test\CRC-Test\crc-test.vcxproj(127,14): error MSB4066: The att
ribute "Include" in element <ClCompile> is unrecognized.
Done Building Project "C:\Users\Test\CRC-Test\crc-test.vcxproj" (defaul
t targets) -- FAILED.

Build FAILED.

"C:\Users\Test\CRC-Test\crc-test.vcxproj" (default target) (1) ->
  C:\Users\Test\CRC-Test\crc-test.vcxproj(127,14): error MSB4066: The a
ttribute "Include" in element <ClCompile> is unrecognized.

    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:00.11


该项目当前为Visual Studio 2010设置.如果您使用其他版本,请更改此版本以适合您的口味.不需要VCUpgrade:

<PlatformToolset>v100</PlatformToolset>

  • VS2010→v100
  • VS2012→v110
  • VS2013→v120
  • VS2015→v130
  • VS2017→v140
    • VS2010 → v100
    • VS2012 → v110
    • VS2013 → v120
    • VS2015 → v130
    • VS2017 → v140
    • 这是 GNUmakefile .当编译器和平台支持硬件加速时,我们引入crc-simd.cpp文件以实现更快的实现.这是我们要使用MSBuild进行的操作.

      Here is the essence of the project on Linux in a GNUmakefile. When the compiler and platform support hardware acceleration, we bring-in the crc-simd.cpp file for the faster implementation. Its what we want to do with MSBuild.

      HAS_ARMV8 ?= $(shell uname -m | $(EGREP) -i -c 'aarch32|aarch64')
      HAS_SSE42 ?= $(shell uname -m | $(EGREP) -i -c 'amd64|x86_64|i*86')
      GCC43_OR_LATER := $(shell $(CXX) -v 2>&1 | $(EGREP) -i -c "gcc version (4\.[3-9]|[5-9]\.)")
      GCC48_OR_LATER := $(shell $(CXX) -v 2>&1 | $(EGREP) -i -c "gcc version (4\.[8-9]|[5-9]\.)")
      ...
      
      OBJECTS = main.o crc.o
      
      ifeq ($(HAS_ARMV8)$(GCC48_OR_LATER),11)
      OBJECTS += crc-simd.o
      endif
      
      ifeq ($(HAS_SSE42)$(GCC43_OR_LATER),11)
      OBJECTS += crc-simd.o
      endif
      ...
      
      ifeq ($(HAS_ARMV8)$(GCC48_OR_LATER),11)
      crc-simd.o : crc-simd.cpp
          $(CXX) $(CXXFLAGS) -march=armv8-a+crc -c $<
      endif
      
      ifeq ($(HAS_SSE42)$(GCC43_OR_LATER),11)
      crc-simd.o : crc-simd.cpp
          $(CXX) $(CXXFLAGS) -msse4.2 -c $<
      endif
      ...
      

      推荐答案

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

      A similar approach as for makefiles can be used: run cl.exe, use a regex to get the version, include source file if version is greater than some number. In code:

      <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>
      

      注意:发现的内置变量列表是针对msbuild(构建系统)的,它与编译器有所不同;这就是为什么没有CL_VERSION就像默认情况下makefile没有GCC_VERSION一样的原因.另外值得尝试使用

      Notes: the lists of built-in variables you found are for msbuild, the build system, which is sort of seperate from the compiler; that's why there's no CL_VERSION just like a makefile has no GCC_VERSION by default. Also it's worth trying to use

      <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
      

      而不是坚持一个项目或保留多个项目,每个VS版本一个.这也使VS不再要求升级(因为它看到使用的是默认平台工具集).我没有VS版本< 2012可以测试它是否可以在这里工作,但是从VS2012起,它可以正常工作,因此已经有4个了,并且还在继续.

      instead of sticking to a single one or keeping multiple projects, one for each VS version. It also keeps VS from asking to upgrade (since it sees it's default platform toolset being used). I don't have VS versions < 2012 to test if it works there though, but it does from VS2012 and onwards so that's already 4 of them, and counting.

      这篇关于有条件地包括基于编译器版本的源文件吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆