使用MSBuild扩展构建过程

本文的目的是简要介绍MSBuild,展示MSBuild中的目标和任务,了解如何使用.csproj文件,并提供有用的链接。 如果您的文章标题更合适,我将很乐意在评论中进行讨论。

菜单



基本概念( 菜单


MSBuild的设计方式是将项目的组装分为几个阶段。

目标是在项目的组装过程中发生的某个阶段(事件)。 您可以使用标准目标,也可以定义自己的目标。

任务是可以在特定阶段执行的任务。 您可以使用标准任务或创建自己的任务。

引用定位文档( https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-targets ):
目标将任务按特定顺序组合在一起,并允许将构建过程分解为较小的单元。
例如,一个目标可以删除输出目录中的所有文件以准备构建,而另一个目标
编译项目的输入并将其放置在空目录中。

MSBuild构建生命周期( 菜单


对于MSBuild,Microsoft定义了许多标准目标(在文件Microsoft.Common.targets,Microsoft.CSharp.targets等中)。 定义了许多不同的目标,但是在本文中,我们将不对其进行详细介绍。 一些标准目标(已订购):

目标清单(扰流板)
  • 重建之前
  • 干净的
  • 建造前
  • BuildOnlySettings
  • 准备建造
  • PreBuildEvent
  • 解决参考
  • 准备资源
  • ResolveKeySource
  • 编译
  • 不受管理的取消注册
  • 生成序列化程序集
  • 创建卫星组件
  • 生成清单
  • GetTargetPath
  • 准备运行
  • 非托管注册
  • 增量清洁
  • PostBuildEvent
  • 后建
  • 重建后


BeforeBuild和AfterBuild目标专门设计为可以覆盖并可以使用。 我不建议使用列表中剩余的目标,以免造成任何破坏

有关目标列表的更详细视图,可以使用/ pp:选项。 由于有了此参数,将生成一个文件,其中包括所有导入(包括.targets文件)。 您可以在其中找到许多目标和变量(感谢aikixd提供技巧)。


准备示例环境( 菜单


例如,您需要:

  • Visual Studio安装的开发环境
  • 创建名为MSBuildExample的控制台应用程序类型的项目
  • 打开项目文件夹,然后在其中找到MSBuildExample.csproj文件
  • 在记事本或其他编辑器中打开MSBuildExample.csproj文件

在本文的所有示例中,您将需要编辑MSBuildExample.csproj文件。 每个示例都涉及从上一个示例中删除代码并添加一个新代码。 该代码必须在.csproj文件的末尾添加到包含结束Project标记的最后一行。

图片

注意! 在.csproj文件中,大小写很重要
要运行该示例,必须在Visual Studio开发环境中运行build。 对于某些示例,您将需要选择解决方案配置。

图片

结果将显示在Visual Studio的“输出”窗口中(底部)。 如果不是,则通过菜单项View => Output打开它。

图片


在MSBuild中定位( 菜单


例如,我们将使用Message任务,该任务将在Visual Studio的Output窗口中显示信息。 如前所述,有一些标准目标BeforeBuild和AfterBuild,我们将使用它们。 要进行培训,请阅读“ 准备环境 ”部分以获取示例

目标用法示例(剧透)
示例代码:

<Target Name="AfterBuild"> <Message Text="AfterBuild event" Importance="high"></Message> </Target> <Target Name="BeforeBuild"> <Message Text="BeforeBuild event" Importance="high"></Message> </Target> 

执行结果(不必要的排除):
...
建造前活动
...
建屋事件
...


如您所见,任务Message已执行,在Visual Studio的“输出”窗口中显示了我们在BeforeBuild和AfterBuild时指定的文本。
用相同名称定义目标时,它会被覆盖!

目标重写示例(剧透)
示例代码:

 <Target Name="BeforeBuild"> <Message Text="First message" Importance="high"></Message> </Target> <Target Name="BeforeBuild"> <Message Text="Second message" Importance="high"></Message> </Target> 

执行结果(不必要的排除):
...
第二条讯息
...


仅显示第二条消息,因为他们使用了具有相同名称的目标,并且被第二个值覆盖。

创建自己的MSBuild目标( 菜单


如果BeforeBuild和AfterBuild目标还不够,或者您希望在组装生命周期的另一个阶段执行任务,则可以定义自己的目标。 为此,有BeforeTargets和AfterTargets参数。

定义自己的目标的示例(剧透)
示例代码:

  <Target Name="BeforeBuild"> <Message Text="BeforeBuild event" Importance="high"></Message> </Target> <Target Name="MyCustomBeforeTarget" BeforeTargets="BeforeBuild"> <Message Text="MyCustomBeforeTarget event" Importance="high"></Message> </Target> <Target Name="MyCustomAfterTarget" AfterTargets="BeforeBuild"> <Message Text="MyCustomAfterTarget event" Importance="high"></Message> </Target> 

执行结果(不必要的排除):
...
MyCustomBeforeTarget事件
建造前活动
MyCustomAfterTarget事件
...


定义了两个自定义目标-MyCustomBeforeTarget和MyCustomAfterTarget。
因为我们指定了以下内容,所以MyCustomBeforeTarget目标在BeforeBuild目标之前执行:

 BeforeTargets="BeforeBuild" 

因为我们指定了以下内容,所以MyCustomAfterTarget目标在BeforeBuild目标之后执行:

 AfterTargets="BeforeBuild" 

MSBuild中的任务( 菜单


本文不讨论如何编写自己的任务,而是在编写任务之前检查Microsoft提供任务列表。

让我们看一些使用任务和宏的示例。

条件参数(扰流板)
条件参数存在于所有任务中。 引用文档docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-task-reference
MSBuild引擎用来确定是否将执行此任务的布尔表达式。
示例代码:

 <Target Name="BeforeBuild"> <Message Text="Current configuration is Debug" Condition="'$(Configuration)' == 'Debug'" Importance="high"></Message> <Message Text="Current configuration is Release" Condition="'$(Configuration)' == 'Release'" Importance="high"></Message> </Target> 

如果选择了Debug配置解决方案,结果将如下所示(不必要的排除):
...
当前配置为调试
...
如果选择了解决方案配置“发行版”,则结果将如下所示(不必要的排除):
...
当前配置为发布
...
您可以在.csproj中有关变量和宏的部分中找到有关$(配置)宏和其他宏的信息。

有关条件语法的信息可以在以下位置找到:https://docs.microsoft.com/zh-cn/visualstudio/msbuild/msbuild-conditions

CSPROJ(扰流器)中的变量定义
在上面的示例中,我们的文本可以统一。 为避免重复,我们将消息文本放在单独的变量中。

示例代码:

 <PropertyGroup> <MessageText>Current configuration is $(Configuration)</MessageText> </PropertyGroup> <Target Name="BeforeBuild"> <Message Text="$(MessageText)" Condition="'$(Configuration)' == 'Debug'" Importance="high"></Message> <Message Text="$(MessageText)" Condition="'$(Configuration)' == 'Release'" Importance="high"></Message> </Target> 

要定义自己的变量,请使用PropertyGroup元素。


检查文件是否存在,发出错误(破坏文件)
在此示例中,我们执行一个任务来检查是否已创建App.Debug.config文件。 如果未创建,则抛出错误。 如果发生错误,构建将停止,并且错误将在“错误列表”窗口中显示为编译错误。
我们使用Error任务和我们已经熟悉的condition参数。

示例代码:

 <Target Name="BeforeBuild"> <Error Condition="!Exists('App.Debug.config')" Text="File App.Debug.config not found"></Error> </Target> 

结果:
图片

Exists子句使用.csproj文件所在文件夹的相对路径。 要访问当前文件夹上方的文件夹,请使用“ ../”。 如果需要访问子文件夹,请使用格式[DirectoryName] /App.Debug.config。

复制文件(扰流板)
在此示例中,我们将使用“ 复制”任务。 使用该任务,将App.config文件复制到bin / [Configuration] / Config文件夹中,并复制到两个App.config和App.test.config文件中。

示例代码:

 <Target Name="BeforeBuild"> <Copy SourceFiles="App.config;App.config" DestinationFiles="$(OutputPath)/Test/App.config;$(OutputPath)/Test/App.test.config"></Copy> </Target> 

SourceFiles属性是要下载的文件的数组。 指示不带引号,以分号分隔。

DestinationFiles属性是一个文件数组,将在其中复制文件。 指示不带引号,以分号分隔。

在.csproj中的变量和宏部分中,了解有关$(OutputPath)宏的更多信息。

.csproj中的变量和宏( 菜单


.csproj文件中可以使用许多标准宏,可以在https://msdn.microsoft.com/zh-cn/library/c02as0cs.aspxhttps://msdn.microsoft.com/zh-cn/上找到它们的列表。 库/ bb629394.aspx 。 考虑一些有用的宏:

  • $(MSBuildToolsPath) -指示MSBuild文件夹的路径。 例如,C:\ Program Files(x86)\ MSBuild \ 14.0 \ Bin。 合并路径时,请将此宏与斜线一起使用。 例如,$(MSBuildToolsPath)\ Microsoft.Web.Publishing.Tasks.dll。 否则,它可能会错误地形成路径并给出错误消息,即找不到该文件。
  • $(OutputPath) -输出文件夹的相对路径。 例如,bin \ Stage。 将此宏与斜杠一起使用,例如$(OutputPath)\ $(TargetFileName).config。
  • $(TargetFileName) -带有扩展名的输出文件的名称。 例如,MSBuildExample.exe。 输出文件名的扩展名和格式可能与不同类型的项目不同。 使用此宏,您可以安全地确定配置文件的名称。 这对于配置转换可能很有用。
  • $(配置)是当前配置的名称。 例如,发布,调试
  • $(IntermediateOutputPath) -obj文件夹的路径。 例如,obj \ Stage。

要定义自己的参数,请使用PropertyGroup在MSBuild任务部分可以找到定义自己的变量的示例。

链接( 菜单


Source: https://habr.com/ru/post/zh-CN414969/


All Articles