4

我有一个自定义.targets文件,用于支持编译后代码生成。我重写了一些目标,目的是让AfterBuild任务运行代码生成器,CoreBuild再次调用,然后进行尾递归,直到结果收敛到一个定点或需要太多迭代。(我认为我从未见过它需要超过 3 次编译才能收敛,但我使用 5 作为限制。)

在某些方面,这是一个笨拙的 hack,尤其是通过CycleDepth同时使用来打破无限循环并防止 MSBuild 因为属性没有更改而跳过重复的任务,但它适用于其主要预期用例:生成代码以实现对象序列化方法并通过部分类机制将它们合并,作为一种优化以避免在运行时基于反射的序列化。但是,我遇到了一种中断的情况:如果使用/m(parallel) 选项针对解决方案调用 MSBuild,则构建会可怕地死掉:在我看来,好像应该是迭代被同时调用。

有没有办法在不破坏并行 MSBuild 的情况下实现这种递归?

由于需要同时针对标准和紧凑框架,我在某种程度上锁定了 3.5 版本;优化对于在较慢的 Compact Framework 设备上实现足够的速度是必要的。

  <Target Name="BeforeCompile" Condition="Exists('$(ProjectDir)CodeGenerationPostBuild.xml')">
    <PropertyGroup>
      <AssemblyTimestampBeforeCompile>%(IntermediateAssembly.ModifiedTime)</AssemblyTimestampBeforeCompile>
    </PropertyGroup>
  </Target>

  <Target Name="AfterCompile" Condition="Exists('$(ProjectDir)CodeGenerationPostBuild.xml')">
    <PropertyGroup>
      <AssemblyTimestampAfterCompile>%(IntermediateAssembly.ModifiedTime)</AssemblyTimestampAfterCompile>
    </PropertyGroup>
  </Target>

  <Target Name="AfterBuild" Condition="Exists('$(ProjectDir)CodeGenerationPostBuild.xml') and ('$(AssemblyTimestampBeforeCompile)'!='$(AssemblyTimestampAfterCompile)')">
    <Exec WorkingDirectory="$(ProjectDir)" Command="&quot;$(SolutionDir)..\CodeGen\CodeGeneration.Engine\bin\$(ConfigurationName)\CodeGeneration.Engine.exe&quot; &quot;$(ProjectDir)CodeGenerationPostBuild.xml&quot;  Command=Build ConfigurationName=$(ConfigurationName)" IgnoreExitCode="true">
      <Output TaskParameter="ExitCode" PropertyName="PostBuildExitCode" />
    </Exec>
    <Error Condition="$(PostBuildExitCode) == 2" Code="BS0002" Text="Read-only generated code file found; did it get checked in again?" />
    <Error Condition="$(PostBuildExitCode) == 99" Code="BS0099" Text="Error in code generation; see detailed build output." />
    <Error Condition="'$(CycleDepth)' == 'xxxxx' And $(PostBuildExitCode) != 0" Code="BS1000" Text="Compilation taking too many iterations to converge.  Do you have [AssemblyVersion(&quot;1.0.*&quot;)] in your AssemblyInfo.cs?" />
    <MSBuild Condition="'$(CycleDepth)' != 'xxxxx' And $(PostBuildExitCode) == 1" Projects="$(ProjectPath)" Targets="CoreBuild; AfterBuild" Properties="CycleDepth=$(CycleDepth)x" />
  </Target>
4

0 回答 0