有条件地包括基于编译器版本的源文件吗? [英] Conditionally include source file based on compiler version?
问题描述
我们正在测试一个项目设置,该设置要求我们基于编译器的版本包含或排除源文件.该测试项目位于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">
<!-- > = escaped > sign -->
<ItemGroup Condition="$(ClVersion) > 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屋!