MSBuild: Compare ItemGroups or access by index -


for c++ project, want autogenerate defs.h file project definitions, such date, git commit, ... automate versioning process of application.

therefore trying create msbuild target extract latest git tag, git commit, , current date , save temporary gitinfo.txt file. build target depend on file , generate .h file. in order avoid unnecessary recompiles of project, .h file , reason gitinfo.txt file shall rewritten, if of information has changes.

so idea following:

  1. calculate git , date info
  2. if available, read in existing gitinfo.txt
  3. compare calculated values in txt file
  4. if has changed, rewrite gitinfo.txt

i've mastered steps 1. , 2., not sure how process values after reading them.

<!-- purpose of target update gitinfo.txt if git information (commit...) has changed --> <target   name="getheaderinfos"   beforetargets="clcompile"   outputs="$(intdir)\gitinfo.txt" >    <!-- information state of repo-->       <gitdescribe>     <output taskparameter="tag" propertyname="newgittag" />     <output taskparameter="commithash" propertyname="newgitcommithash" />     <output taskparameter="commitcount" propertyname="newgitcommitcount" />   </gitdescribe>    <!-- current date -->   <time format="dd.mm.yyyy">     <output taskparameter="formattedtime" propertyname="newbuilddate" />   </time>    <readlinesfromfile file="$(intdir)\gitinfo.txt" condition="exists('$(intdir)\gitinfo.txt')">     <output taskparameter="lines" itemname="version" />   </readlinesfromfile>     <!-- comparison here! how -->   <propertygroup>      <tagchanged> <!-- `$(newgittag)` == `$(version)[0]` --> </tagchanged>      <!-- other comparisons -->   </propertygroup> </target> 

and content of gitinfo.txt

v4.1.4 04fe34ab 1 31.07.2016 

i not quite sure how compare values now. need compare $(newgittag) first value in $(version) version variable, , on.

i haven't found example, accesses variables after reading them file. official documentation provides no help, nor have found on stackoverflow or likes.

i know $(version) variable holds list, , can batch process it. how can compare content defined variables $(newgittag), $(newgitcommithash), $(newgitcommitcount) , $(newbuilddate)?

suppose start data:

<itemgroup>   <version include="v4.1.4;04fe34ab;1;31.07.2016"/> </itemgroup>  <propertygroup>   <gittag>v4.1.4</gittag>   <gitsha>04fe34ab</gitsha>   <count>1</count>   <date>31.07.2016</date> </propertygroup> 

then here at least 3 ways achieve comparision (apart 1 mentioned in comment) , there other ways (i'll post them if can come else):

just compare items

i'm not sure why want compare seperately when works well: compare whole itemgroup @ once.

<target name="compare1">   <propertygroup>     <versionchanged>true</versionchanged>     <versionchanged condition="'@(version)' == '$(gittag);$(gitsha);$(count);$(date)'">false</versionchanged>   </propertygroup>   <message text="versionchanged = $(versionchanged)" /> </target> 

batch , check if there's 1 difference

each item of version compared e.g. gittag via batching. result false;false;false;false if there's difference, else true;false;false;false. count distinct elements , if it's 2 means got latter gittag did not change. note obviousle works if each of source items can never have same value 1 of other items.

<target name="compare2">   <propertygroup>     <tagchanged>true</tagchanged>     <tagchanged condition="'@(version->contains($(gittag))->distinct()->count())' == '2'">false</tagchanged>   </propertygroup>   <message text="tagchanged = $(tagchanged)" /> </target> 

you can compare other items , combine result.

use inline task access items index

this comes closest what's in question, need bit of inline code.

<usingtask taskname="indexitemgroup" taskfactory="codetaskfactory" assemblyfile="$(msbuildtoolspath)\microsoft.build.tasks.v4.0.dll" >   <parametergroup>     <items required="true" parametertype="microsoft.build.framework.itaskitem[]"/>     <index required="true" parametertype="system.int32"/>     <item output="true" parametertype="microsoft.build.framework.itaskitem"/>   </parametergroup>   <task>     <code type="fragment" language="cs">       <![cdata[item = items[ index ];]]>     </code>   </task> </usingtask>  <target name="compare3">   <indexitemgroup items="@(version)" index="1">     <output propertyname="oldgitsha" taskparameter="item"/>   </indexitemgroup>    <propertygroup>     <shachanged>true</shachanged>     <shachanged condition="'$(gitsha)' == '$(oldgitsha)'">false</shachanged>   </propertygroup>    <message text="oldgitsha = $(oldgitsha), changed = $(shachanged)" /> </target> 

Comments