I have a project files collection:
<ItemGroup>
<ApplicationToDeploy
Include="Frontend.WebSite.csproj;11.WebServices.csproj;22.WebServices.csproj"/>
<ApplicationToDeploy
Include="33.WebServices.csproj;44.WebServices.csproj;Workflow55Svc.csproj"/>
</ItemGroup>
I'm trying to get collection of .config-files of these projects:
<Target Name="111">
<PropertyGroup>
<Cfgs>@(ApplicationToDeploy->'%(RootDir)%(Directory)*.config')</Cfgs>
</PropertyGroup>
<ItemGroup>
<InputConfigs Include="$(Cfgs)" />
</ItemGroup>
<Message Text="Cfgs: @(InputConfigs)"/>
</Target>
Inside the Target block all works fine (I see collection of Web.Configs, App.Configs, Log4net.Configs etc.):
Cfgs: C:\Sources\WebServices\11\WebServices\11.WebServices\Web.config;C:\Sources\WebServices\22\WebServices\22.WebServices\web.log4net.config;C:\Sources\WebServices\33\WebServices\33.WebServices\web.environment.config
But I want to initialize this ItemGroup outside of the Target block. Like this:
<PropertyGroup>
<Cfgs>@(ApplicationToDeploy->'%(RootDir)%(Directory)*.config')</Cfgs>
</PropertyGroup>
<ItemGroup>
<InputConfigs Include="$(Cfgs)" />
</ItemGroup>
<Target Name="111">
<Message Text="Cfgs: @(InputConfigs)"/>
</Target>
And when I do this outside of the Target block I get this:
Cfgs: C:\Sources\WebServices\11\WebServices\11.WebServices\*.config;C:\Sources\WebServices\22\WebServices\22.WebServices\*.config;C:\Sources\WebServices\33\WebServices\33.WebServices\*.config
I don't understand what's happens. Is it possible to get the same result outside Target block?
I don't understand what's happens.
This behavior is an effect of the MSBuild evaluation order:
During the evaluation phase of a build:
During the execution phase of a build:
There's another key point on that link "(...) The string expansion is dependent on the build phase.".
You're using the property 'Cfgs' to recursively map your projects' folders AND to define a wildcard to config files (*.config)
. When you define 'Cfgs' INSIDE the target, the InputConfigs receives the expanded value of Cfgs (semicolon-separated string list of folders), and just resolve the wildcards. On the other hand, when you define 'Cfgs' OUTSIDE the target, the InputConfigs receives the unexpanded value of Cfgs (@(ApplicationToDeploy->'%(RootDir)%(Directory)*.cs')
. When the InputConfigs expands it, it results on the semicolon-separated string list of folders, but it doesn't resolve the wildcards (*.config)
.
Is it possible to get the same result outside Target block?
I think that InputConfigs should always receive the expanded list of directories. The expansion is made during the execution phase of the build. During this phase, only properties and items defined within targets are evaluated. So, I would keep all the initialization inside an 'Initialization' Target block. I don't mean it is impossible to do it outside a Target block, but for the reasons mentioned it does not seems logical. =]
Hope this helps,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With