While chasing incremental build time improvements, I found that .btproj files and thus all other projects that depend on these are rebuilt (partly) on each incremental build. Tracking this all the way to BizTalkCommon.targets, I found that it does a 2 pass compilation of the assembly - but only the first pass respects already built artifacts, thus breaking the incremental part of the dependency chain. The offending target can be seen in BizTalkCommon.targets (line 228):
<!-- Delete the assembly and rerun the build process -->
<Target Name="SecondPass"
Condition="$(SecondBuild)!=true and $(TempAssemblyOnly)!=true">
<Delete Files="@(IntermediateAssembly)" />
<MSBuild Projects="$(MSBuildProjectFile)" Properties="SecondBuild=true"/>
</Target>
I realize 开发者_JAVA百科that there's a reason for the 2 pass build, but simply cannot believe it wouldn't be possible to specify appropriate in- and outputs for the target to handle incremental builds correctly.
Does anyone know if there's a patch for the .targets file, or if there's another good reason that incremental builds aren't supported?
You can enable incremental compilation of MSBuild BizTalk project with a couple of very simple changes. Basically, you need to override two targets that are defined in the BizTalkCommon.targets
file.
Those targets can be overriden in your own .btproj files and do not require modifying the original .targets file that ships with BizTalk.
How To
First Create you own .targets file to host your customizations, for instance BizTalkCustom.targets
:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\BizTalk\BizTalkC.targets" />
<!-- Rerun the build process (second pass) -->
<Target Name="SecondPass" Condition="$(SecondBuild)!=true and $(TempAssemblyOnly)!=true and @(XLang)!=''">
<MSBuild Projects="$(MSBuildProjectFile)" Properties="SecondBuild=true" />
</Target>
<!-- Compile XLang/s orchestration -->
<Target
Name="CompileODX"
Condition="$(SecondBuild)==true"
Inputs="@(XLang);$(MSBuildAllProjects);$(ClrTypesAssembly)"
Outputs="$(BuildDone)">
<!-- Delete previously generated C# files from XLang compilation -->
<Delete Files="@(IntermediateAssembly)" />
<Delete Files="@(CSharpOutputFromXLang)" />
<XLangTask XLangItems="@(XLang)"
ProjectReferences="@(ReferencePath)"
WarningLevel="$(WarningLevel)"
BpelCompliance="$(BpelCompliance)"
DefineConstants="$(DefineConstants)"
TreatWarningsAsErrors="$(TreatWarningsAsErrors)"
TempAssembly="$(ClrTypesAssembly)"
OutputDirectory="$(XLangOutputPath)">
</XLangTask>
</Target>
Then, replace the last Import
statement in your .btproj file:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(MyCustomExtensions)\BizTalkCustom.targets" />
How doe it work
BizTalk Server projects need somehow to be compiled in two passes. The first pass compiles schemas, maps and pipelines, whereas the second pass compiles orchestrations.
You'll notice that the overriden targets are very very similar than the original ones, defined inside the BizTalkCommon.targets file
. In fact, I made two simple changes:
The first change involves modifying the
SecondPass
Target and adding an extra test in theCondition
attribute. This test is usefull to prevent the second pass from occurring if your project does not even have Orchestrations.Unfortunately, if your project contains Orchestrations, the original
SecondPass
Target deletes the intermediate assemblies and then proceed to compile the Orchestrations. However, theCompileODX
Target does not need to run if all files are already up to date. Therefore, the second change involves moving theDelete
Task from theSecondPass
Target to theCompiledODX
Target.
That's all there is to it.
This is something my team ran into a while back and simply backed off customizing the build files and went with the BizTalk deployment framework instead, located here. BizTalk does lots of "funny" things from a VS level, since 2009 was the first version BizTalk didn't use an external build process. But I'm not sure why the second pass is needed, except maybe from a designer perspective.
精彩评论