MSBuild - Force Expansion of Wildcards in Transforms

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • peridian
    New Member
    • Dec 2006
    • 72

    MSBuild - Force Expansion of Wildcards in Transforms

    Hi,

    Some MSBuild joyness, I have a range of unit test libraries, that actually reference each other (extended tests, mocks, etc.). As a result, the build on the server has multiple *.Tests.dll files in their bin directories.

    To select the Test dlls to run the tests as part of the build, we previously did this:

    Code:
    <ItemGroup>
      <TestFiles Include="$(RootDir)*.Tests\**\*.Tests.dll" />
    </ItemGroup>
    However, this would result in a number of test dlls being run multiple times. To try and clear this up, I wanted to use a transform to select only the test file that matches the project name.

    Code:
    <ItemGroup>
      <TestProjects Include="$(RootDir)*.Tests\**\*.Tests.csproj" />
      <TestFiles Include="@(TestProjects->'%(directory)bin\**\*.%(filename).dll')" />
    </ItemGroup>
    When output in messages, this produces the correct string and only once for each relevant dll. However (as documented elsewhere) transforms do not result in the wildcard being expanded.

    Now the three main solutions I have seen have been to:

    a) Use CreateItem to expand the wildcard (http://stackoverflow.c om/questions/9055659/expand-msbuild-properties-containing-wildcard-into-items). I have not been able to get this to work, as the resulting output of CreateItem is always empty (possibly due to the deprecated nature of CreateItem, I don't know if it would cause an error if our MSBuild version no longer supports it).

    Sample:

    Code:
    <CreateItem Include="@(TestFiles)">
    	<Output TaskParameter="Include" ItemName="UseTests"/>
    </CreateItem>
    b) Put the transform in a second ItemGroup before assigning it to the correct ItemGroup. This just results in the same output as if I had not done this.

    Sample:

    Code:
    <ItemGroup>
      <TestFolders Include="$(RootDir)*.Tests\**\*.Tests.csproj" />
    </ItemGroup>
    <ItemGroup>
      <TestFiles Include="@(TestFolders->'%(directory)bin\**\*.%(filename).dll')" />
    </ItemGroup>
    <ItemGroup>
      <UseTests Include="@(TestFiles)" />
    </ItemGroup>
    c) Put the transform through a custom target that assigns the ItemGroup to a PropertyGroup and then creates a new ItemGroup by accessing the PropertyGroup (http://stackoverflow.c om/questions/6537454/can-msbuild-resolve-wildcard-expressions-resulting-from-a-transform). This also does not work as the output appears to be empty.

    Sample:

    Code:
    <Target Name="TransformWithWildcards" Outputs="%(UseTests.Identity)">
      <PropertyGroup>
        <TempFiles>@(TestFiles)</TempFiles>
      </PropertyGroup>
      <ItemGroup>
        <UseTests Include="$(TempFiles)" />
      </ItemGroup>
    </Target>
    I've toyed with trying to get rid of the wildcards, but unfortunately that pretty much results in an individual file entry per test assembly, which is not ideal.

    Can anybody suggest what I might have missed? What other ways could I force the wildcards to be expanded?

    Regards,
    Rob.
  • peridian
    New Member
    • Dec 2006
    • 72

    #2
    Never mind, went a rather indirect route in the end.

    Code:
    <PropertyGroup>
      <TempTestFolder>$(RootDir)_UnitTests</TempTestFolder>
    </PropertyGroup>
    
    <Target Name="CopyUniqueTestFiles">
      <MakeDir Directories="$(TempTestFolder)" Condition="!Exists('$(TempTestFolder)')" />
      <Copy SourceFiles="$(RootDir)*.Tests\**\*.dll" DestinationFolder="$(TempTestFolder)" ContinueOnError="true" />
      <ItemGroup>
        <UseTests Include="$(TempTestFolder)\*.Tests.dll" />
      </ItemGroup>
    </Target>
    This essentially copies all the dlls (both test and dependancies) into a single folder, relying on the file system to distinct the files by overwriting each other.

    Regards,
    Rob.

    Comment

    Working...