我有一个自定义.targets
文件,用于支持编译后代码生成。我重写了一些目标,目的是让AfterBuild
任务运行代码生成器,再次调用CoreBuild
,然后尾递归,直到结果收敛到定点或过多的迭代是必要的。 (我认为我从未见过它需要超过3次汇编才能收敛,但我使用5作为限制。)
在某些方面这是一个笨拙的黑客,特别是通过使用CycleDepth
来打破无限循环并阻止MSBuild跳过重复的任务,因为属性没有改变,但它适用于其主要用途case:生成代码以实现对象序列化方法并通过部分类机制将它们合并,作为优化以避免在运行时基于反射的序列化。我遇到了一个崩溃的情况:如果使用/m
(并行)选项对解决方案调用MSBuild,则构建可怕地死掉:它看起来好像应该是什么迭代是同时被调用。
有没有办法在不破坏并行MSBuild的情况下实现这种递归?
由于需要同时针对标准和Compact Framework,我在某种程度上被修订锁定为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=""$(SolutionDir)..\CodeGen\CodeGeneration.Engine\bin\$(ConfigurationName)\CodeGeneration.Engine.exe" "$(ProjectDir)CodeGenerationPostBuild.xml" 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("1.0.*")] in your AssemblyInfo.cs?" />
<MSBuild Condition="'$(CycleDepth)' != 'xxxxx' And $(PostBuildExitCode) == 1" Projects="$(ProjectPath)" Targets="CoreBuild; AfterBuild" Properties="CycleDepth=$(CycleDepth)x" />
</Target>