MSBuild:根据文件路径的一部分过滤项目

时间:2017-05-19 22:34:54

标签: msbuild

我需要复制一组文件,这些文件位于包含存放这些文件的软件包版本的文件夹下:

<ItemGroup>
    <MyFiles Include="$(MyPackages)\foo.x64*\binaries\*.*"/>
</ItemGroup>

foo.x64*可以解析为多个文件夹,例如foo.x64.17.5.50foo.x64.17.6.2,后缀代表软件包的版本。我想根据该版本过滤我的项目,但我似乎无法找到一种方法来将项目文件路径的任何部分提取为我项目上的元数据,然后在批处理或条件中使用它。

2 个答案:

答案 0 :(得分:2)

可以在这里使用msbuild的一些功能。那些是:

  1. 定义自定义项元数据。我们称他们为FooArchFooVersion
  2. MSBuild允许调用一些包含正则表达式的.net API。因此,我们可以在此处使用RegEx.Match()来提取您需要了解的信息。
  3. 在对字符串进行数字比较时,MSBuild会将它们解析为Versions。这样您就可以执行'%(FooItems.FooVersion)' &lt; '17.6.2'
  4. 等范围条件

    开箱即用的不可能是确定项目列表的最高版本。为此,您需要编写自定义的msbuild任务。

    更具体的示例:要在项目上添加所需的元数据并复制正确的版本和体系结构,您可以执行以下操作:

    <PropertyGroup>
      <FooRegEx>[\\/]foo\.(?&lt;arch&gt;x(\d*))\.(?&lt;version&gt;((\d+)(\.\d+)+))</FooRegEx>
      <FooVersionToUse>17.5.50</FooVersionToUse>
    </PropertyGroup>
    
    <ItemGroup>
      <FooFiles Include="mypkgs\foo*\binaries\**\*">
        <FooArch>$([System.Text.RegularExpressions.Regex]::Match(%(Identity), $(FooRegEx)).get_Groups().get_Item("arch"))</FooArch>
        <FooVersion>$([System.Text.RegularExpressions.Regex]::Match(%(Identity), $(FooRegEx)).get_Groups().get_Item("version"))</FooVersion>
      </FooFiles>
    </ItemGroup>
    
    <Target Name="IncludeFoo" BeforeTargets="PrepareForBuild">
      <PropertyGroup>
        <FooArchToUse Condition="'$(FooArchToUse)' == '' and '$(Platform)' != 'AnyCPU'">$(Platform)</FooArchToUse>
        <FooArchToUse Condition="'$(FooArchToUse)' == ''">x64</FooArchToUse>
      </PropertyGroup>
      <ItemGroup>
        <Content Include="@(FooFiles)" 
                 Link="foo\%(Filename)%(Extension)"
                 CopyToOutputDirectory="PreserveNewest"
                 Condition="'%(FooFiles.FooVersion)' == '$(FooVersionToUse)' and '%(FooFiles.FooArch)' == '$(FooArchToUse)'"/>
      </ItemGroup>
    </Target>
    

    这会将为(默认为x64)构建的所选版本和平台的项目复制到输出目录的foo子文件夹中。 (在MSBuild 15.1上测试过)。我已将示例项目上传到GitHub here

答案 1 :(得分:0)

您可以使用ItemGroup的 Condition 属性根据某些布尔表达式过滤掉元素。您可以根据this answer使用正则表达式。