从定义各种xml内容文件的.csproj开始。 让代码生成Target获取一些xml文件(目标输入)并生成.cs文件,其名称由xml文件(目标输出)的转换确定。 为了让MSBuild确定构建Target的代码是否需要运行,它需要检查目标输入和输出。 因此我假设这些目标输入和输出必须是全局的。
如果这不正确,则应该有另一个问题,即如何创建一个基于动态项目的输出目标;尝试过但目标不断被召唤。
如果它是正确的,那么如何在全球范围内过滤内容? 具体来说,我想过滤项目中的内容项,以便只使用特定目录中的内容。内容项将由其他开发人员通过IDE添加。
这可以使用Target创建动态项目,在Condition属性中进行过滤来实现。这需要目标批处理,这在全球范围内不可用。使用MSBuild 3.5和Visual Studio 2008。
<?xml version="1.0" encoding="utf-8"?>
<Project
DefaultTargets="Show" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="badxml\somebadxml1.xml" />
<!-- Note xml\somexml2.xml exists on disk, it just isn't used in this project. -->
<Content Include="xml\somexml1.xml" />
<Content Include="xml\somexml3.xml" />
</ItemGroup>
<!-- Foo should only be defined for Content Items in the "xml" directory. -->
<ItemGroup>
<Foo Include="@(Content->'%(Filename)')"/>
<!-- The line below doesn't work -->
<!-- TestFilter.proj(10,10): error MSB4090: Found an unexpected character '%' at position 3 in condition " '%(Content.RelativeDir)'=='xml' ". -->
<!-- <Foo Condition=" '%(Content.RelativeDir)'=='xml' " Include="@(Content->'%(Filename)')"/> -->
</ItemGroup>
<Target Name="ShowContent">
<Message Text="Content: %(Content.Identity)" />
<Message Text="Content RelDir: %(Content.RelativeDir)" />
</Target>
<Target Name="ShowFoo">
<Message Text="Foo: %(Foo.Identity)" />
</Target>
<Target Name="Show">
<CallTarget Targets="ShowContent;ShowFoo" />
</Target>
</Project>
Why doesn't MSBuild ItemGroup conditional work in a global scope解决了同样的问题,但是从询问为什么这不起作用的角度出发,而不是寻找替代方法。
Filtering Item's Metadata in msbuild使用目标中的动态项和虚拟输出名称。
我最好的猜测是,这不能在不使用目标中的动态项目的情况下完成,并且解决方法将是使用需要条件的项目来编写具有预定义名称的文件并使用该项目作为输出占位符。