请升级到MicrosoftEdge以使用最新的功能、安全更新和技术支持。
MSBuild
用于创建可靠的最佳实践生成,第1部分
SayedIbrahimHashimi
内容
定义目标依赖项批处理任务定义动态项和属性扩展清理过程组织目标使用通配符
定义目标依赖项
MSBuild中定义一个目标时,可以使用DependsOnTargets属性来定义目标依赖项。MSBuild使用此属性确定在其中执行目标的顺序。是例如如果您定义名为的目标部署依赖目标PrepareForBuild和生成的如下所示Express的依赖项:
请看一下此处显示修改后的部署目标:
批处理任务
MSBuild使用称为任务批处理的概念,该任务将执行一次按每个唯一的批处理或的值组。批始终创建基于项目的元数据。请看一下一个简单的示例使用图2所示该Batching01.proj文件的内容。
图2A简单批处理示例
在TaskBatching01目标中用调用消息任务。此表达式将导致MSBuild来确定由从SampleItem物料组元数据定义唯一批。因为我知道该组有两个唯一的值,我知道的两个批创建,从组元数据和其他与使用A2中具有A1的值。另一条消息任务,创建基于ID的元数据值的数目。执行此目标的结果如图3所示。
图3Batching01.proj结果
C:\Samples\Batching>msbuildBatching01.proj/t:TaskBatching01/nologoBuildstarted10/20/20081:27:58AM.Project"C:\Samples\Batching\Batching01.proj"onnode0(TaskBatching01target(s)).SampleItem:one;two;three;four;fiveSampleItem.Group:A1SampleItem.Group:A2SampleItem.Id:A363BE85-2CB1-4221-A9CB-2881B7699329SampleItem.Id:48E171C8-2274-4567-84D5-D20C6B0CB363SampleItem.Id:618E5BD8-650F-43c9-855E-259126284004SampleItem.Id:65E8E8E7-5A3F-4e02-A1D9-34F797CB68D9SampleItem.Id:43D0D1FE-304F-4aff-BE19-67AD2195872BDoneBuildingProject"C:\Samples\Batching\Batching01.proj"(TaskBatching01target(s)).Buildsucceeded.0Warning(s)0Error(s)可以看到该语句flattensSampleItem值到一个字符串传递到消息任务导致的@(SampleItem)表达式的位置"一;两个;三个;四个;五个"。对比这具有与该调用所示的行为。在这种情况下已两次执行消息任务。在该SampleItem.id实例的情况下消息任务已执行五次。
图4Copy01.proj
src|class1.cs|class2.cs|class3.cs|class4.cs|+---Admin|admin_class1.cs|admin_class2.cs|+---Utilitiesutil_class1.csutil_class2.cs在本示例,在DestinationFolder被指定为$(Dest)%(SrcFiles.RecursiveDir).此语句将SrcFiles项目分为三个组的RecursiveDir根据值RecursiveDir、管理和实用程序的空值。复制任务都调用三次,一次每个组。期间的每次调用只当前组中的该文件为SrcFiles项传递给复制任务。
若要才能清楚地看到此,一下生成图5所示的详细的日志。从日志,您就可以确认复制任务执行三次,并且每次只文件匹配RecursiveDir的当前值已包括在SrcFiles项目中。
图5递归复制文件
图6Zip01.proj
Zip任务用于在ZipFile目标和值$(_ZipWorkingDir)%(SourceFiles.group).内%(SourceFiles.Access).zipisprovidedfortheZipFileNameproperty.在包含从相同的项列表的多个批处理表达式的情况下,批创建使用元数据的唯一组合。此语句,批会创建从唯一值的组和访问。因为有组的三个值和两个访问,将有最多六个批。在这种情况下有图7所示的组合所组成的只有四个批。
其他可能的组合(管理/公用和Util/私钥)永远不会在项目中显示,因此不会使用它们。现在,我们知道应创建四个.zip文件。如果执行命令msbuildZip01.proj/t:ZipFiles,可以看到结果如图8所示。
图8创建基于元数据的Zip文件
C:\Samples\Batching>msbuildZip01.proj/nologoBuildstarted11/3/200811:40:40PM.Project"C:\Samples\Batching\Zip01.proj"onnode0(defaulttargets).Creatingdirectory"output\".Creatingzipfile"output\common.public.zip".added"src/class1.cs".added"src/class3.cs".Createdzipfile"output\common.public.zip"successfully.Creatingzipfile"output\common.private.zip".added"src/class2.cs".added"src/class4.cs".Createdzipfile"output\common.private.zip"successfully.Creatingzipfile"output\util.public.zip".added"src/Utilities/util_class1.cs".added"src/Utilities/util_class2.cs".Createdzipfile"output\util.public.zip"successfully.Creatingzipfile"output\admin.private.zip".added"src/Admin/admin_class1.cs".added"src/Admin/admin_class2.cs".Createdzipfile"output\admin.private.zip"successfully.DoneBuildingProject"C:\Samples\Batching\Zip01.proj"(defaulttargets).Buildsucceeded.0Warning(s)0Error(s)在该图,可以看到zip任务IMAPITable四次,预期。每个zip文件名称中包含使用批处理的两个元数据值。
此处描述的行为并不限于两个元数据值或单个项目列表。您可以自由使用如有必要的尽可能多的元数据值。批处理在多个项列表的行为与不同内容我已经介绍并不将此处讨论。
定义动态项和属性
MSBuild2.0中必须使用CreateItem和CreateProperty任务分别创建动态的项和属性。MSBuild3.5中,您可以通过使用相同的语法,当您使用的静态项创建它们。首选的方法是使用ItemGroup和PropertyGroup元素,在一个目标。
属性和Item评估发生多个周期。静态属性和项,属性计算的上向下(从文件末尾文件的开头),包括输入任何导入的项目和项目计算从上到下,还包括任何导入的项目中输入。它们执行计算动态属性和项。
在创建项和属性时,约定是开始使用下划线的名称为"internal"的值。项目和属性名称不能启动使用下划线表示用户它们能够替代它们。在创建这些属性或项目时,给出此约定,应首先检查以查看是否在已定义一个条件。这非常有用,以防其他人已定义相同的属性或应重写您的项目。
MSBuild3.5包含与动态项的新功能。是例如MSBuild2.0中,您不能修改的项列表的内容。在一个项列表中包括项目后无法删除。在解决此限制是创建新项目不包括您不想值。MSBuild3.5现在支持通过删除属性的项目中的删除值。图9中,显示该项目文件RemoveItems01.proj,演示此。
图9RemoveItems01.proj
图10显示了执行删除目标的结果。基于图10所示的输出,您可以看到,class2.cs和class3.cs文件已成功删除从SrcFiles物料。可以同时添加和更新使用ItemGroup元素内部的一个的目标的元数据使用相同的语法处理创建动态的项目。若要了解如何更新元数据值,请一下UpdateMetadata01.proj文件图11所示。
图10从项目中删除值
C:\Samples>msbuildRemoveItems01.proj/t:Remove/nologoBuildstarted10/26/200812:54:11AM.Project"C:\Samples\RemoveItems01.proj"onnode0(Removetarget(s)).SrcFiles:Batching\src\class1.cs;Batching\src\class2.cs;Batching\src\class3.csSrcFiles:Batching\src\class1.csDoneBuildingProject"C:\Samples\RemoveItems01.proj"(Removetarget(s)).Buildsucceeded.0Warning(s)0Error(s)图11UpdateMetadata01.proj
图12更新现有的元数据
C:\Samples>msbuildUpdateMetadata01.proj/t:UpdateSpecificVersion/nologoBuildstarted10/29/200812:07:39AM.Project"C:\Samples\UpdateMetadata01.proj"onnode0(UpdateSpecificVersiontarget(s)).IronPython,Version=...:Falselog4net,Version=...:Falsenunit.core,...:Falsenunit.framework,Version=...:Falsenunit.util,...:FalseUpdateReference.SpecificVersiontoTrueIronPython,Version=...:Truelog4net,Version=...:Truenunit.core,...:Truenunit.framework,Version=...:Truenunit.util,...:TrueDoneBuildingProject"C:\Samples\UpdateMetadata01.proj"(UpdateSpecificVersiontarget(s)).Buildsucceeded.0Warning(s)0Error(s)您可以看到添加AddMetadata01.proj文件包含相应的示例代码中的元数据的一个示例。我不会转到详细信息。与修改项目列表本身,更新数据,并将元数据添加到项目中,在执行目标时可以是具有MSBuild2.0没有等效项的新功能。
扩展清理过程
此部分与使用MSBuild会生成VisualStudio中的C#或VisualBasic.NET项目时。此处描述的行为都包含内部目标文件用于生成这些类型的项目和不在MSBuild本身。
在修改生成过程来创建新文件,您负责扩展清理过程清理这些文件。MSBuild清理文件,它负责自动,但它不能,生成的自定义的目标的文件。MSBuild维护名为FileWrites包含需要清洗的文件的项目列表。此列表被保存到一个文件被称为"清理缓存"obj文件夹。可以将其他值放到FileWrites项列表,以便在被删除项目清理时。
有两个缺点这样,但是。要删除的文件必须位于该输出路径下,并您必须将项目追加到该列表,清除的缓存写入磁盘的中清理或会出现IncrementalClean目标根据执行的生成类型之前。生成目标完成之前,将调用这些目标。
在示例代码本文随附,您将看到Windows窗体项目WindowsFormsApplication1,在其中我已定义BeforeBuild目标,如下所示:
图13Clean目标结果
另一种方法是使用目标依赖项。您可以扩展清理过程中注入您自己的目标将CleanDependsOn属性。请看一下自定义到WindowsFormsApplication2项目图14中,显示的Microsoft.CSharp.targets导入语句之后发生。
图14WindowFormsApplication2
图15Clean目标结果
C:\Samples\WindowsFormsApplication2>msbuildWindowsFormsApplication2.csproj/t:Clean/nologoBuildstarted10/26/20081:17:40PM.Project"C:\Samples\WindowsFormsApplication2\WindowsFormsApplication2.csproj"onnode0(Cleantarget(s)).CustomBeforeCleantargetexecutedCoreClean:Deletingfile"\bin\Debug\WindowsFormsApplication2.exe".Deletingfile"\bin\Debug\WindowsFormsApplication2.pdb".Deletingfile"\obj\Debug\WindowsFormsApplication2.Form1.resources".Deletingfile"\obj\Debug\WindowsFormsApplication2.Properties.Resources.resources".Deletingfile"\obj\Debug\WindowsFormsApplication2.csproj.GenerateResource.Cache".Deletingfile"\obj\Debug\WindowsFormsApplication2.exe".Deletingfile"\obj\Debug\WindowsFormsApplication2.pdb".AfterClean:AfterCleantargetexecutedCustomAfterClean:CustomAfterCleantargetexecutedDoneBuildingProject"C:\Samples\WindowsFormsApplication2\WindowsFormsApplication2.csproj"(Cleantarget(s)).Buildsucceeded.0Warning(s)0Error(s)组织目标
生成过程的增长需要组织驻留了不同的部分。通常情况下,最好使用专用的职责的文件和其内容反映它们的用途。定义为产品的生成过程时,请解决这种情况下,会有所帮助创建三个文件:
通过以便重写MyProduct.settings.targets中的任何值并准备MyProduct.targets属性和项。如果您与此生成过程的C#项目,MyProduct.targets相当于Microsoft.CSharp.targets(和Microsoft.common.targets),并其他两个文件构成实际的项目文件。
使用通配符
VisualStudio项目文件并不使用通配符来填充VisualStudio进行的交互的项目。例如,您可以定义编译项目包含将在如下所示发送给该的编译器的文件的列表: