Msbuild 如何在目标之间传递带有元数据的ItemGroup?

Msbuild 如何在目标之间传递带有元数据的ItemGroup?,msbuild,Msbuild,根据我的理解,使用DependsOnTargets在目标之间传递ItemGroup是必要的。我不确定是否有其他方法可以在不依赖目标的情况下通过目标 我已测试ItemGroup无法从CallTarget或MSBuild任务传递。解决方案是将项目组转换为属性(展平),并使用Properties传递 我定义了文件的项目组。文件具有值元数据。我想为每个递归循环执行target并删除一个文件项。这是我的剧本: <Target Name="MyGroup"> <ItemGroup>

根据我的理解,使用
DependsOnTargets
在目标之间传递ItemGroup是必要的。我不确定是否有其他方法可以在不依赖目标的情况下通过目标

我已测试ItemGroup无法从
CallTarget
MSBuild
任务传递。解决方案是将项目组转换为属性(展平),并使用
Properties
传递

我定义了
文件
项目组
文件
具有
元数据。我想为每个递归循环执行target并删除一个
文件
项。这是我的剧本:

<Target Name="MyGroup">
  <ItemGroup>
    <File Include="5">
      <Value>5a</Value>
    </File>
    <File Include="4">
      <Value>4a</Value>
    </File>
    <File Include="3">
      <Value>3a</Value>
    </File>
    <File Include="2">
      <Value>2a</Value>
    </File>
    <File Include="1">
      <Value>1a</Value>
    </File>
  </ItemGroup>
</Target>

<Target Name="Recursive" DependsOnTargets="MyGroup" Condition="$(Value) > 0">
  <ItemGroup>
    <File Remove="$(Value)" />
  </ItemGroup>

  <PropertyGroup>
    <Value>$([MSBuild]::Subtract($(Value), 1))</Value>
  </PropertyGroup>

  <Message Text="File: @(File->'%(Value)') Value=$(Value)" Importance="High" />
  <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value)"/>
</Target>

<Target Name="Build" DependsOnTargets="MyGroup">
  <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
</Target>
我预计产出为:

File: 4a;3a;2a;1a Value=4
File: 3a;2a;1a Value=3
File: 2a;1a Value=2
File: 1a Value=1
File: Value=0

有解决方案吗?

不太可能,您试图绕过msbuild的思想,只构建一次目标(除非输入\输出发生更改)。 并且不能在MSBuild上下文之间传递项组(当调用MSBuild任务时,将创建新上下文)。此外,在脚本中,ItemGroup的作用域为target,您需要全局定义它,以便其他目标可以使用它。 您可以做的是:

  • 定义全局属性值,条件是使用传递给脚本的属性值(如果存在)
  • 将ItemGroup从MyGroup目标更改为全局范围
  • 根据value属性的值定义要发出的itemgroup的每个元素的条件
e、 g.您的脚本如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Value Condition="$(Value) == ''">5</Value>
  </PropertyGroup>
  <ItemGroup>
    <File Include="5" Condition="$(Value) >5">
      <Value>5a</Value>
    </File>
    <File Include="4" Condition="$(Value) >4">
      <Value>4a</Value>
    </File>
    <File Include="3" Condition="$(Value) >3">
      <Value>3a</Value>
    </File>
    <File Include="2" Condition="$(Value) >2">
      <Value>2a</Value>
    </File>
    <File Include="1" Condition="$(Value) >1">
      <Value>1a</Value>
    </File>
  </ItemGroup>
  <Target Name="Recursive" Condition="$(Value) >0">
    <PropertyGroup>
      <Value>$([MSBuild]::Subtract($(Value), 1))</Value>
    </PropertyGroup>
    <Message Text="File: @(File->'%(Value)') Value=$(Value)" Importance="High" />
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value)"/>
  </Target>
  <Target Name="Build">
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
  </Target>
</Project>

谢谢但是我无法在实际项目中使用
条件
属性构建ItemGroup。给出的示例是一个原型,展示了我面临的问题。这些项是我的项目中的一组文件。MSBuild脚本实际上不是“用于生成项目的过程语言”,因此,如果您对项目组没有控制权或几乎没有控制权,则问题的答案是“否”(至少是afaik)—MSBuild将处理所有全局属性和项,然后再向这些属性和项添加任何目标调用和项,但是没有被移除。你能描述一下你想要实现什么吗?也许有另一种解决方案不需要递归调用?编辑:嗯,对不起,我没注意到你的答案。我很高兴你用另一种方法解决了你的问题我的问题是我有一组
Delphi
project(290++)要构建。这些项目之间存在依赖关系。我已经成功地从这些项目中构建了依赖关系,并使用项目元数据将其保存在
ItemGroup
中,以保存依赖信息。首先,我从
ItemGroup
中筛选一个没有依赖关系的项目列表,并以并行方式执行构建任务。然后,我从ItemGroup中删除新构建对象文件的依赖关系。在第二个循环中,我再次过滤。这些操作将使用
MSBuild
以递归方式执行。您是否使用MSBuild构建Delphi项目,例如,在exec中调用您自己的编译器?为什么要使用MSBuild而不是任何其他脚本语言?我不确定您为什么选择MSBuild,但我想说,对于.NET以外的任何对象,它作为批处理构建语言都是平庸的。它对于.NET构建非常有用,因为所有的构建过程都与之相关。您在.NET中的问题可能会很容易解决—只需构建输出项目,所有依赖项都将自动生成。
Delphi
自2007年起使用
MSBuild
来构建一组项目(
groupproj
dproj
文件)。更多信息:
<?xml version="1.0" encoding="utf-8"?>
<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Value Condition="$(Value) == ''">5</Value>
  </PropertyGroup>
  <ItemGroup>
    <File Include="5" Condition="$(Value) >5">
      <Value>5a</Value>
    </File>
    <File Include="4" Condition="$(Value) >4">
      <Value>4a</Value>
    </File>
    <File Include="3" Condition="$(Value) >3">
      <Value>3a</Value>
    </File>
    <File Include="2" Condition="$(Value) >2">
      <Value>2a</Value>
    </File>
    <File Include="1" Condition="$(Value) >1">
      <Value>1a</Value>
    </File>
  </ItemGroup>
  <Target Name="Recursive" Condition="$(Value) >0">
    <PropertyGroup>
      <Value>$([MSBuild]::Subtract($(Value), 1))</Value>
    </PropertyGroup>
    <Message Text="File: @(File->'%(Value)') Value=$(Value)" Importance="High" />
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value)"/>
  </Target>
  <Target Name="Build">
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
  </Target>
</Project>
<Target Name="MyGroup">
    <ItemGroup>
        <File Include="5">
            <Value>5a</Value>
        </File>
        <File Include="4">
            <Value>4a</Value>
        </File>
        <File Include="3">
            <Value>3a</Value>
        </File>
        <File Include="2">
            <Value>2a</Value>
        </File>
        <File Include="1">
            <Value>1a</Value>
        </File>
    </ItemGroup>
</Target>

<Target Name="Recursive" DependsOnTargets="MyGroup" Condition="$(Value) > 0" >
    <ItemGroup>
        <File Remove="$(Value)" />
        <File Remove="$(Done)" />
    </ItemGroup>

    <Message Text="File: @(File->'%(Value)') Value=$(Value)" Importance="High" />

    <PropertyGroup>
        <Done>$(Done);$(Value)</Done>
        <Value>$([MSBuild]::Subtract($(Value), 1))</Value>
    </PropertyGroup>

    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value);Done=$(Done)" />
</Target>

<Target Name="Build" DependsOnTargets="MyGroup">
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
</Target>