Reputation: 14021
I am seeing some strange behavior with the ItemGroup
tag.
My application depends on several DLLs, and I am copying these DLLs as well as the executable to a deploy directory, which is used by NSIS to create an install package from a fresh build. However, I am running into an odd issue with this.
I define my ItemGroup
as follows (at the top of the file before I define my build target:
<MyAppFiles Include="$(ProjectRoot)\$(OutputPath)\*.dll;$(ProjectRoot)\$(OutputPath)\MyApp.exe" />
So, this grabs all the DLLs in the directory as well as the binary MyApp.exe
. But, if the project has been cleaned (i.e., there are no files in $(OutputPath)
). The DLLs are not included in the ItemGroup
list of files. Now, if I follow this up with another build, (i.e., there are files from the previous build in $(OutputPath)
) the ItemGroup
contains all the files I want.
Also, I have checked the output of the build script and the DLLs are copied to $(OutputPath)
whether a clean happened or not.
So, my question is, how do I correct my build script such that ItemGroup
always contains the DLLs? It seems like the ItemGroup
populates with files before the build happens, so if the files aren't there before the build, they aren't included in the list, but if they exist before the build then they are.
For reference, here is the build target that I am using:
<PropertyGroup>
<MyAppRoot>..\MyApp</MyAppRoot>
<MyAppProject>$(MyAppRoot)\MyApp.csproj</MyAppProject>
<PropertyGroup>
<Target Name="BuildProject">
<Message Text="BEFORE: @(ProjectFiles)" />
<MSBuild Projects="$(MyAppProject)" Targets="Build" Properties="Configuration=$(Configuration)">
<Output TaskParameter="TargetOutputs" ItemName="MyAppAssembly"/>
</MSBuild>
<Message Text="AFTER: @(ProjectFiles)" />
</Target>
Upvotes: 1
Views: 1180
Reputation: 9938
Presumably your item array is declared at the root level in your project, in XML as a child of the <Project> element. This means that MSBuild will evaluate the membership in the item array when the project file is first loaded. Whether or not the existance of those files changes during execution is irrelevant. If you want to populate the item array at a particular point in your build, you need to change the declaration from a static item array to a dynamic one, which means moving it inside a target, to the exact spot where you want to gather the files, as:
<Target Name="BuildProject">
...before message
...msbuild task
<ItemGroup>
<ProjectFiles Include="$(ProjectRoot)\$(OutputPath)\*.dll" />
<ProjectFiles Include="$(ProjectRoot)\$(OutputPath)\MyApp.exe" />
</ItemGroup>
...after message
</Target>
(excerpted from trick #62 in the book "MSBuild Trickery")
Upvotes: 9