MSBuild:比较项目组或按索引访问 对于一个C++项目,我想用项目定义自动生成一个 DEFS.H./Cux>文件,如日期、Git提交、…自动化应用程序的版本控制过程

MSBuild:比较项目组或按索引访问 对于一个C++项目,我想用项目定义自动生成一个 DEFS.H./Cux>文件,如日期、Git提交、…自动化应用程序的版本控制过程,msbuild,Msbuild,因此,我试图创建一个MSBuild目标,该目标将提取最新的git标记、git commit和当前日期,并将其保存到一个临时的gitinfo.txt文件中。 另一个构建目标将依赖于该文件并生成一个.h文件。 为了避免对我的项目进行不必要的重新编译,.h文件以及基于此原因,gitinfo.txt文件只能在任何信息发生更改时重写 因此,我的想法如下: 计算git和日期信息 如果可用,请阅读现有的gitinfo.txt 将计算值与txt文件中的值进行比较 如果有任何更改,请重写gitinfo.txt 我

因此,我试图创建一个MSBuild目标,该目标将提取最新的git标记、git commit和当前日期,并将其保存到一个临时的
gitinfo.txt
文件中。 另一个构建目标将依赖于该文件并生成一个.h文件。 为了避免对我的项目进行不必要的重新编译,.h文件以及基于此原因,
gitinfo.txt
文件只能在任何信息发生更改时重写

因此,我的想法如下:

  • 计算git和日期信息
  • 如果可用,请阅读现有的
    gitinfo.txt
  • 将计算值与txt文件中的值进行比较
  • 如果有任何更改,请重写
    gitinfo.txt
  • 我已经掌握了第一步。和2.,但我不确定读取值后如何处理

    <!-- The purpose of this target is to update gitinfo.txt if git information (commit...) has changed -->
    <Target
      Name="GetHeaderInfos"
      BeforeTargets="ClCompile"
      Outputs="$(IntDir)\gitinfo.txt"
    >
    
      <!-- Get information about the state of this repo-->    
      <GitDescribe>
        <Output TaskParameter="Tag" PropertyName="NewGitTag" />
        <Output TaskParameter="CommitHash" PropertyName="NewGitCommitHash" />
        <Output TaskParameter="CommitCount" PropertyName="NewGitCommitCount" />
      </GitDescribe>
    
      <!-- Get the 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 TO DO IT PROPERLY -->
      <PropertyGroup>
         <TagChanged> <!-- `$(NewGitTag)` == `$(Version)[0]` --> </TagChanged>
         <!-- Other comparisons -->
      </PropertyGroup>
    </Target>
    
    我现在不太确定如何比较这些值。我需要将
    $(NewGitTag)
    $(Version)
    版本变量中的第一个值进行比较,依此类推

    我还没有找到一个实例,它实际上是在从文件中读取变量之后访问变量的。没有提供任何帮助,我也没有在stackoverflow之类的网站上找到任何东西


    我只知道
    $(Version)
    变量包含一个列表,我可以批处理它。如何将其内容与定义的变量
    $(NewGitTag)
    $(NewGitCommitHash)
    $(NewGitCommitCount)
    $(NewBuildDate)
    进行比较?

    假设我们从以下数据开始:

    <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>
    
    然后还可以比较其他项目并合并结果

    使用内联任务按索引访问项目

    这与您的问题最接近,但它确实需要一些内联代码

    <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>
    
    
    
    
    真的
    假的
    
    另一种方法:将git信息和日期写入文件,使用Exec任务比较这些文件以调用窗口的fc.exe,并使用其返回值确定文件是否相等,如果不相等,则复制文件。类似于这里:是的,这是一种有效的方法。我试试看。然而,我真的很想知道它是如何实现的,对于未来的用例也是如此。也许还可以编辑你的问题/标题,让未来的访问者更容易发现它:基本上是“如何通过索引从项目组访问项目”,甚至只是“如何比较项目组”。也可以让它更简单:你只需要从一个项目组和一堆项目开始,然后你想要比较它们。这些项目是来自文件还是来自GitDescripte都无关紧要,这使得测试代码变得更加困难,因为不是每个人都有GitDescripte。关于第二个,如果一切都改变了,那么它将是
    真的;是的;是的;正确
    ,因此它会被错误地标记为“未更改”?至于第三个,我不知道它会这么复杂,但至少我知道它是如何使用的;是的;是的;如果版本以某种方式等于“v4.1.4;v4.1.4;v4.1.4;v4.1.4”
    <Target Name="Compare1">
      <PropertyGroup>
        <VersionChanged>True</VersionChanged>
        <VersionChanged Condition="'@(Version)' == '$(GitTag);$(GitSHA);$(Count);$(Date)'">False</VersionChanged>
      </PropertyGroup>
      <Message Text="VersionChanged = $(VersionChanged)" />
    </Target>
    
    <Target Name="Compare2">
      <PropertyGroup>
        <TagChanged>True</TagChanged>
        <TagChanged Condition="'@(Version->Contains($(GitTag))->Distinct()->Count())' == '2'">False</TagChanged>
      </PropertyGroup>
      <Message Text="TagChanged = $(TagChanged)" />
    </Target>
    
    <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>