调用可重用的msbuild目标时将列表项传递给Properties

时间:2014-07-05 14:32:18

标签: msbuild msbuild-task msbuildcommunitytasks

我正在尝试按照How to invoke the same msbuild target twice?

中概述的基本模型在msbuild中创建可重用的目标

我试图传递一个我想要解释为列表的属性。我还没有在网上找到一个处理这种情况的例子。据我了解,问题是属性已被视为列表项,因此它不喜欢传入列表项。有没有办法让msbuild在这里正确打包和解包列表?

Msbuild抱怨:

error MSB4012: The expression "FilesToZip=@(Scripts)" cannot be used in this context. Item lists cannot be concatenated with other strings where an item list is expected. Use a semicolon to separate multiple item lists.

以下是一个示例来电者:

<Target Name="BuildMigrationZip">

   <MSBuild Projects="BuildZip.msbuild"
      Targets="BuildZip"
      Properties="FilesToZip=@(Scripts);OutputZipFile=$(MigrationPackageFilePath);OutputFolder=$(MigrationPackagePath);Flatten=true"/>

  <Message Text="Created database migration zip: $(MigrationPackageFilePath)" Importance="high"/>

</Target>

基础目标:

<Target Name="BuildZip">

  <MakeDir Directories="$(OutputFolder)"/>

  <Zip Files="@(FilesToZip)" 
  ZipFileName="$(OutputZipFile)"
  Flatten="$(Flatten)"
  ParallelCompression="false" />

</Target>

我基本上只是回去剪切和粘贴这些,虽然我想在这里打包一些拉链。

更新:同样的问题适用于在可重用目标上设置输入。到目前为止,我的问题解决了原始功能,但保持依赖项工作会很好。例如:

<Target Name="BuildZip"
   Inputs="@(FilesToZip)"
   Outputs="$(OutputZipFile)">

  <MakeDir Directories="$(OutputFolder)"/>

  <Zip Files="@(FilesToZip)" 
  ZipFileName="$(OutputZipFile)"
  Flatten="$(Flatten)"
  ParallelCompression="false" />

</Target>

1 个答案:

答案 0 :(得分:4)

他们的关键是将列表作为属性传递。因此,当您的Scripts列表定义为

<ItemGroup>
  <Scripts Include="A"/>
  <Scripts Include="B"/>
  <Scripts Include="C"/>
</ItemGroup>

然后你首先将它转换为一个属性(它只生成分号分隔的项目,但msbuild知道如何通过Properties目标的MSBuild传递它,然后将其传递给目标:< / p>

<Target Name="BuildMigrationZip">
  <PropertyGroup>
    <ScriptsProperty>@(Scripts)</ScriptsProperty>
  </PropertyGroup>

  <MSBuild Projects="$(MSBuildThisFile)" Targets="BuildZip"
           Properties="FilesToZip=$(ScriptsProperty)" />
</Target>

(请注意我在这里使用$(MSBuildThisFile):您不一定需要为每个目标创建单独的构建文件,事实上对于像您这样的小目标而言,它还需要更多方便把它放在同一个文件中)

然后在您的目标目标中,您再次将该属性转换为列表:

<Target Name="BuildZip">
  <ItemGroup>
    <FilesToZipList Include="$(FilesToZip)"/>
  </ItemGroup>
  <Message Text="BuildZip: @(FilesToZipList)" />
</Target>

输出:

BuildZip: A;B;C

<强>更新

使用Inputs时,您无法传递@(FilesToZip),因为它不会扩展为空,因为它不是列表:它是一个属性 - 恰好是一些以分号分隔的字符串。因此,它可用于Inputs您只需将其展开为属性即$(FilesToZip)

<Target Name="BuildZip"
        Inputs="$(FilesToZip)"
        Outputs="$(OutputZipFile)">
  ...
</Target>

第二轮的输出:

BuildZip:
Skipping target "BuildZip" because all output files are up-to-date with respect to the input files.