c++ - Conditionally include source file based on compiler version? -
we testing project setup requires include or exclude source file based on compiler's version. test project located on github @ crc-test. poc, developing process crc-32c since both intel , arm have it. later applied aes, clmul, sha, avx{2}, bmi{2}, armv7a neon, armv8, etc. (ms compilers support neon , armv8 through intrinsics).
the source file trying conditionally compile crc-simd.cpp
. has implementations using sse4.2 intrinsics , armv8 intrinsics (crc.cpp
provides generic, c++ implementation).
i added vcx project file @ crc-test.vcxproj. there itemgroup
clcompile
:
<itemgroup> <clcompile include="main.cpp" > <precompiledheader /> </clcompile> <clcompile include="crc.cpp" > <precompiledheader /> </clcompile> <clcompile include="crc-simd.cpp" > <precompiledheader /> </clcompile> </itemgroup>
i need conditional <clcompile include="crc-simd.cpp" >
says, "if cl.exe
15.00 or greater, include source file". in preprocessor check _msc_ver >= 1500
. in msbuild think looking like:
<itemgroup condition="'$(cl_version)'>='15.00'" label="sse4.2 acceleration"> <clcompile include="crc-simd.cpp" > <precompiledheader /> </clcompile> </itemdefinitiongroup>
i found list of msbuild built-in variables, don't know $(cl_version)
in real life. seraching "cl" did not result in interesting hits. found 1 question @ msbuild vs compiler, asking different question.
my question is, how reference cl.exe
version in msbuild conditional?
a related problem is, need full version. example, aes support added @ vs2005 sp1, cl.exe
version 15.00.30729 (_msc_full_ver >= 150030729
). related question is, how reference cl.exe
full version in msbuild conditional?
trying use following developer prompt:
<itemdefinitiongroup condition="'$(cl_version)'>='15.00'" label="sse4.2 acceleration"> <clcompile include="crc-simd.cpp" > <precompiledheader /> </clcompile> </itemdefinitiongroup>
results in:
> cls && msbuild microsoft (r) build engine version 4.6.1087.0 [microsoft .net framework, version 4.0.30319.42000] copyright (c) microsoft corporation. 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: att ribute "include" in element <clcompile> 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: ttribute "include" in element <clcompile> unrecognized. 0 warning(s) 1 error(s) time elapsed 00:00:00.11
the project setup visual studio 2010. if using different version, change suite tastes. there no need vcupgrade
:
<platformtoolset>v100</platformtoolset>
- vs2010 → v100
- vs2012 → v110
- vs2013 → v120
- vs2015 → v130
- vs2017 → v140
here essence of project on linux in gnumakefile
. when compiler , platform support hardware acceleration, bring-in crc-simd.cpp
file faster implementation. want 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 ...
a similar approach makefiles can used: run cl.exe, use regex version, include source file if version greater 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 18.00.31101 --> <clversion>$([system.text.regularexpressions.regex]::match('$(clout)','(\d+\.\d+\.\d+)'))</clversion> <!-- turn integer 180031101 getting rid of dots --> <clversion>$([system.string]::copy('$(clversion)').replace('.', ''))</clversion> </propertygroup> </target> <!-- run in build, before compilation, can modify clcompile itemgroup. needs done in target, else cannot use results other targets (getclversion in case) --> <target name="showclversion" dependsontargets="getclversion" beforetargets="buildgeneratesources"> <!-- > = escaped > sign --> <itemgroup condition="$(clversion) > 180031100"> <clcompile include="somefile.cpp" /> </itemgroup> </target>
notes: lists of built-in variables found msbuild, build system, sort of seperate compiler; that's why there's no cl_version makefile has no gcc_version default. it's worth trying use
<platformtoolset>$(defaultplatformtoolset)</platformtoolset>
instead of sticking single 1 or keeping multiple projects, 1 each vs version. keeps vs asking upgrade (since sees it's default platform toolset being used). don't have vs versions < 2012 test if works there though, vs2012 , onwards that's 4 of them, , counting.
Comments
Post a Comment