I'm trying to populate an ItemGroup
with directory basenames, pass it through a transform to create absolute paths from them and import the files residing there. It works flawlessly in a Message
element, but fails to do anything in an Import
. What am I missing?
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MyDependencies Include="Dir1" />
<MyDependencies Include="Dir2" />
</ItemGroup>
<!-- "Expansion: C:\path\Dir1\import.targets;C:\some\path\Dir2\import.targets" -->
<Target Name="TestMessage" BeforeTargets="PrepareForBuild">
<Message
Importance="High"
Text="Expansion: @(MyDependencies -> 'C:\path\%(Identity)\import.targets')"
/>
</Target>
<!-- Uncomment to trigger error -->
<!--<Import Project="@(MyDependencies -> 'C:\path\%(Identity)\import.targets')" />-->
</Project>
The Import
's path remains unexpanded and leads to:
error MSB4102: The value "@(MyDependencies -> 'C:\path\%(Identity)\import.targets')" of the "Project" attribute in element <Import> is invalid. Illegal characters in path.
This happens because the ItemGroup gets evaluated after Import only. See https://learn.microsoft.com/en-us/visualstudio/msbuild/comparing-properties-and-items?view=vs-2022#property-and-item-evaluation-order:
During the evaluation phase of a build, imported files are incorporated into the build in the order in which they appear. Properties and items are defined in three passes in the following order:
In other words an Import
is almost the same as copy-pasting the content of the file at the location of that import, and only after that MSBuild begins to evaluate properties and items.