MSBuild 转换
更新:2007 年 11 月
转换是从一个项集合到另一个项集合的一对一变换。除了允许项目转换项集合以外,转换还允许目标识别其输入和输出之间的直接映射。本主题介绍转换以及 MSBuild 如何使用转换来更高效地生成项目。
转换修饰符
转换不是任意的,而是受特殊语法的限制,其中所有的转换修饰符必须采用 %(项元数据名称) 的格式。任何项元数据都可用作转换修饰符,包括在创建项时赋给各个项的已知项元数据。有关已知项元数据的列表,请参见 MSBuild 常见项的元数据。
在下面的示例中,将一个 .resx 文件列表转换为一个 .resources 文件列表。%(filename) 转换修饰符指定各个 .resources 文件与对应的 .resx 文件具有相同的文件名称。
@(RESXFile->'%(filename).resources')
说明: |
---|
您可以为转换后的项集合指定自定义分隔符,就像对普通项集合那样。例如,要使用逗号 (,) 而不是默认的分号 (;) 来分隔转换后的项集合,请使用下面的 XML。 @(RESXFile->'Toolset\%(filename)%(extension)', ',') |
例如,如果 @(RESXFile) 项集合中的项为 Form1.resx、Form2.resx 和 Form3.resx,则转换后的列表中的输出将为 Form1.resources、Form2.resources 和 Form3.resources。
使用多个修饰符
转换可以包含多个修饰符,这些修饰符可按任何顺序组合,并且修饰符可以在转换表达式中重复使用。在下面的示例中,包含文件的目录的名称被更改,但是文件保留原来的名称和文件扩展名。
@(RESXFile->'Toolset\%(filename)%(extension)')
例如,如果 RESXFile 项集合中的项为 Project1\Form1.resx、Project1\Form2.resx 和 Project1\Form3.text,则转换后的列表中的输出将为 Toolset\Form1.resx、Toolset\Form2.resx 和 Toolset\Form3.text。
依赖项分析
转换保证了在转换后的项集合与原始项集合之间存在一对一的映射关系。因此,如果目标创建的输出是输入的转换,MSBuild 就可以分析输入和输出的时间戳,确定是要跳过、生成还是部分重新生成目标。
在下面示例内的 Copy 任务中,BuiltAssemblies 项集合中的每个文件都将映射到该任务的目标文件夹(由 Outputs 属性中的转换指定)中的某个文件。如果 BuiltAssemblies 项集合中的任何文件发生更改,将仅为发生更改的文件运行 Copy 任务,并跳过所有其他文件。有关依赖项分析和使用转换的更多信息,请参见如何:增量生成。
<Target Name="CopyOutputs"
Inputs="@(BuiltAssemblies)"
Outputs="@(BuiltAssemblies -> '$(OutputPath)%(Filename)%(Extension)')">
<Copy
SourceFiles="@(BuiltAssemblies)"
DestinationFolder="$(OutputPath)"/>
</Target>
示例
说明
下面的示例演示一个使用转换的 MSBuild 项目文件。该示例假定 c:\sub0\sub1\sub2\sub3 目录中仅有一个 .xsd 文件,并假定工作目录为 c:\sub0。
代码
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Schema Include="sub1\**\*.xsd"/>
</ItemGroup>
<Target Name="Messages">
<Message Text="rootdir: @(schema->'%(rootdir)')"/>
<Message Text="fullpath: @(schema->'%(fullpath)')"/>
<Message Text="rootdir + directory + filename + extension: @(schema->'%(rootdir)%(directory)%(filename)%(extension)')"/>
<Message Text="identity: @(schema->'%(identity)')"/>
<Message Text="filename: @(schema->'%(filename)')"/>
<Message Text="directory: @(schema->'%(directory)')"/>
<Message Text="relativedir: @(schema->'%(relativedir)')"/>
<Message Text="extension: @(schema->'%(extension)')"/>
</Target>
</Project>
注释
该示例产生下面的输出。
rootdir: C:\
fullpath: C:\xmake\sub1\sub2\sub3\myfile.xsd
rootdir + directory + filename + extension: C:\xmake\sub1\sub2\sub3\myfile.xsd
identity: sub1\sub2\sub3\myfile.xsd
filename: myfile
directory: xmake\sub1\sub2\sub3\
relativedir: sub1\sub2\sub3\
extension: .xsd