In MSBuild 3.5, is it possible to reverse the order elements in an ItemGroup?
Example
I have 2 projects. One can be built independently the other is dependent on the first. Each project references its specific items in a .targets file.
project_A.targets
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<AssembliesToRemove Include="@(AssembliesToRemove)" />
<AssembliesToRemove Include="Assembly_A.dll">
<ApplicationName>App_A</ApplicationName>
</AssembliesToRemove>
</ItemGroup>
<ItemGroup>
<AssembliesToDeploy Include="@(AssembliesToDeploy)" />
<AssembliesToDeploy Include="Assembly_A.dll">
<AssemblyType>SomeType</AssemblyType>
<ApplicationName>App_A</ApplicationName>
</AssembliesToDeploy>
</ItemGroup>
</Project>
project_B.targets
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<AssembliesToRemove Include="@(AssembliesToRemove)" />
<AssembliesToRemove Include="Assembly_B.dll">
<ApplicationName>App_B</ApplicationName>
</AssembliesToRemove>
</ItemGroup>
<ItemGroup>
<AssembliesToDeploy Include="@(AssembliesToDeploy)" />
<AssembliesToDeploy Include="Assembly_B.dll">
<AssemblyType>SomeType</AssemblyType>
<ApplicationName>App_B</ApplicationName>
</AssembliesToDeploy>
</ItemGroup>
</Project>
project_A.proj
<Project DefaultTargets="Start" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="project_A.targets" />
<Import Project="Common.targets" />
</Project>
project_B.proj
<Project DefaultTargets="Start" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="project_A.targets" />
<Import Project="project_B.targets" />
<Import Project="Common.targets" />
</Project>
The Problem
In this scenario the problem arises during the Task processing @(AssembliesToDeploy)
because Assembly_B.dll needs to be deployed before Assembly_A.dll.
Processing @(AssembliesToRemove)
works fine because here the assemblies are in the right order (remove Assembly_A.dll before Assembly_B.dll).
What I tried to do
I tried to influence the order of @(AssembliesToDeploy)
by modifying project_B.targets like this:
<ItemGroup>
<AssembliesToDeploy Include="Assembly_B.dll">
<AssemblyType>SomeType</AssemblyType>
<ApplicationName>App_B</ApplicationName>
</AssembliesToDeploy>
<AssembliesToDeploy Include="@(AssembliesToDeploy)" />
</ItemGroup>
but when using project_B.targets inside project_B.proj the order inside @(AssembliesToDeploy)
still remained Assembly开发者_StackOverflow_A.dll;Assembly_B.dll.
Edit
As MadGnome points out this cannot work because I'll end up with duplicates in @(AssembliesToDeploy)
Is there a solution which would allow to reuse my .targets i.e not copying all ItemGroup elements to all .targets files?
You just have to include project_B.targets
before project_A
.
<Project DefaultTargets="Start" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="project_B.targets" />
<Import Project="project_A.targets" />
<Import Project="Common.targets" />
</Project>
I think there is a mistake in this code :
<ItemGroup>
<!-- Generates duplicates if used with Import -->
<AssembliesToDeploy Include="@(AssembliesToDeploy)" />
<AssembliesToDeploy Include="Assembly_B.dll">
<AssemblyType>SomeType</AssemblyType>
<ApplicationName>App_B</ApplicationName>
</AssembliesToDeploy>
</ItemGroup>
You are using Import
, so you if you use the code above you'll have duplicates in AssembliesToDeploy
.
Adopting from MadGnomes answer I decided to split the ItemGroups into separate .target files.
project_A_REMOVE.targets
<Project xmlns="...">
<ItemGroup>
<AssembliesToRemove Include="@(AssembliesToRemove)" />
<AssembliesToRemove Include="Assembly_A.dll">
<ApplicationName>App_A</ApplicationName>
</AssembliesToRemove>
</ItemGroup>
</Project>
project_A_DEPLOY.targets
<Project xmlns="...">
<ItemGroup>
<AssembliesToDeploy Include="@(AssembliesToDeploy)" />
<AssembliesToDeploy Include="Assembly_A.dll">
<AssemblyType>SomeType</AssemblyType>
<ApplicationName>App_A</ApplicationName>
</AssembliesToDeploy>
</ItemGroup>
</Project>
and the same for project_B.targets.
The project_B.proj now looks like this
<Project DefaultTargets="Start" xmlns="...">
<Import Project="project_A_REMOVE.targets" />
<Import Project="project_B_REMOVE.targets" />
<Import Project="project_B_DEPLOY.targets" />
<Import Project="project_A_DEPLOY.targets" />
<Import Project="Common.targets" />
</Project>
Since my real solution consist of some 58 projects this will result in a lot of .targets. Even more so because I have to keep a common .targets for every project.
精彩评论