MSBuild 如何生成项目How MSBuild builds projects

MSBuild 的实际工作原理是什么?How does MSBuild actually work? 在本文中,你将了解 MSBuild 如何处理项目文件,无论是从 Visual Studio 调用,还是从命令行或脚本调用。In this article, you'll learn how MSBuild processes your project files, whether invoked from Visual Studio, or from a command line or script. 了解 MSBuild 的工作方式可以帮助你更好地诊断问题并更好地自定义生成过程。Knowing how MSBuild works can help you better diagnose problems and better customize your build process. 本文介绍了生成过程,该过程在很大程度上适用于所有项目类型。This article describes the build process and is largely applicable to all project types.

完整的生成过程包括生成项目的目标和任务的初始启动评估执行The complete build process consists of initial startup, evaluation, and execution of the targets and tasks that build the project. 除了这些输入以外,外部导入还会定义生成过程的详细信息,包括标准导入,如解决方案或项目级别的 Microsoft.Common.targets 和 user-configurable importsIn addition to these inputs, external imports define the details of the build process, including both standard imports such as Microsoft.Common.targets and user-configurable imports at the solution or project level.

启动Startup

可通过 Microsoft.Build.dll 中的 MSBuild 对象模型,或者在命令行上或在脚本(如 CI 系统中)中直接调用可执行文件,从 Visual Studio 调用 MSBuild。MSBuild can be invoked from Visual Studio through the MSBuild object model in Microsoft.Build.dll , or by invoking the executable directly on the command line, or in a script, such as in CI systems. 在任一情况下,影响生成过程的输入都包括项目文件(或 Visual Studio 内部的项目对象),可能是解决方案文件、环境变量、命令行开关或其对象模型等效项。In either case, inputs that affect the build process include the project file (or project object internal to Visual Studio), possibly a solution file, environment variables, and command-line switches or their object model equivalents. 在启动阶段,使用命令行选项或对象模型等效项来配置 MSBuild 设置,如配置记录器。During the startup phase, the command-line options or object model equivalents are used to configure MSBuild settings such as configuring loggers. 使用 -property-p 开关在命令行上设置的属性设置为全局属性,这些属性将重写项目文件中设置的任何值,即使稍后读取项目文件也是如此。Properties set on the command line using the -property or -p switch are set as global properties, which override any values that would be set in the project files, even though project files are read in later.

以下各节介绍了输入文件,如解决方案文件或项目文件。The next sections are about the input files, such as solution files or project files.

解决方案和项目Solutions and projects

作为解决方案的一部分,MSBuild 实例可能包含一个项目,也可以包含多个项目。MSBuild instances may consist of one project, or many projects as part of a solution. 解决方案文件不是 MSBuild XML 文件,但 MSBuild 会将其解释为了解需要针对给定的配置和平台设置生成的所有项目。The solution file isn't an MSBuild XML file, but MSBuild interprets it to know all the projects that are required to be built for the given configuration and platform settings. 当 MSBuild 处理此 XML 输入时,称为解决方案生成。When MSBuild processes this XML input, it's referred to as the solution build. 它有一些可扩展点,使你能够在每个解决方案生成中运行一些内容,但由于此生成是独立于单个项目生成单独运行的,因此,解决方案生成中的属性或目标定义的设置与每个项目生成均不相关。It has some extensible points that allow you to run something at every solution build, but since this build is a separate run from the individual project builds, no settings of properties or target definitions from the solution build are relevant to each project build.

可在自定义解决方案生成中了解如何扩展解决方案生成。You can find out how to extend the solution build at Customize the solution build.

Visual Studio 生成与MSBuild.exe 生成Visual Studio builds vs. MSBuild.exe builds

在 Visual Studio 中生成项目与通过 MSBuild 可执行文件直接调用 MSBuild 或使用 MSBuild 对象模型启动生成之间,有一些显著的区别。There are some significant differences between when projects build in Visual Studio vs. when you invoke MSBuild directly, either through the MSBuild executable, or when you use the MSBuild object model to start a build. Visual Studio 管理 Visual Studio 生成的项目生成顺序;它仅在单个项目级别调用 MSBuild,并在执行此操作时,将设置几个布尔属性(BuildingInsideVisualStudioBuildProjectReferences),这对 MSBuild 的功能有很大影响。Visual Studio manages the project build order for Visual Studio builds; it only calls MSBuild at the individual project level, and when it does, a couple of Boolean properties (BuildingInsideVisualStudio, BuildProjectReferences) are set that significantly affect what MSBuild does. 在每个项目中,执行进行方式与通过 MSBuild 调用时的方式相同,但在引用项目方面存在差异。Inside each project, execution occurs the same as when invoked through MSBuild, but the difference arises with referenced projects. 在 MSBuild 中,需要引用项目时,实际上会发生生成;也就是说,它会运行任务和工具,并生成输出。In MSBuild, when referenced projects are required, a build actually occurs; that is, it runs tasks and tools, and generates the output. 当 Visual Studio 生成查找引用项目时,MSBuild 仅返回所引用项目的预期输出;它允许 Visual Studio 控制其他项目的生成。When a Visual Studio build finds a referenced project, MSBuild only returns the expected outputs from the referenced project; it lets Visual Studio control the building of those other projects. Visual Studio 确定生成顺序并单独调用 MSBuild(根据需要),所有这些操作都完全在 Visual Studio 控制下进行。Visual Studio determines the build order and calls into MSBuild separately (as needed), all completely under Visual Studio's control.

如果使用解决方案文件调用 MSBuild,情况又会有所不同,MSBuild 将解析解决方案文件,创建标准 XML 输入文件,对文件进行评估,然后作为项目执行文件。Another difference arises when MSBuild is invoked with a solution file, MSBuild parses the solution file, creates a standard XML input file, evaluates it, and executes it as a project. 解决方案生成在任何项目之前执行。The solution build is executed before any project. 从 Visual Studio 生成时,不会出现这些情况;MSBuild 不会看到解决方案文件。When building from Visual Studio, none of this happens; MSBuild never sees the solution file. 因此,解决方案生成自定义(使用 before.SolutionName.sln.targets 和 after.SolutionName.sln.targets)仅适用于 Msbuild.exe 或对象模型驱动,而不适用于 Visual Studio 生成。As a consequence, solution build customization (using before.SolutionName.sln.targets and after.SolutionName.sln.targets ) only applies to MSBuild.exe or object model driven, not Visual Studio builds.

项目 SDKProject SDKs

MSBuild 项目文件的 SDK 功能相对较新。The SDK feature for MSBuild project files is relatively new. 在进行此更改之前,项目文件显式导入了 .targets 和 .props 文件,这些文件为特定项目类型定义了生成过程。Prior to this change, project files explicitly imported the .targets and .props files that defined the build process for a particular project type.

.NET Core 项目导入适用于它们的 .NET SDK 版本。.NET Core projects import the version of the .NET SDK appropriate to them. 请参阅概述 .NET Core 项目 SDK 以及对属性的引用。See the overview, .NET Core project SDKs, and the reference to the properties.

评估阶段Evaluation phase

本节讨论如何处理和分析这些输入文件,以生成确定将生成内容的内存中对象。This section discusses how these input files are processed and parsed to produce in-memory objects that determine what will be built.

评估阶段的目的是基于输入 XML 文件和本地环境在内存中创建对象结构。The purpose of the evaluation phase is to create the object structures in memory based on the input XML files and local environment. 评估阶段包含六个处理输入文件(如项目 XML 文件或/和导入的 XML 文件(通常名 .props 或 .targets 文件))的环节,具体取决于它们主要是设置属性还是定义生成目标 。The evaluation phase consists of six passes that process the input files such as the project XML files or, and the imported XML files, generally named as .props or .targets files, depending on whether they primarily set properties or define build targets. 每个环节都会生成一部分内存中对象,这些对象稍后会在执行阶段用于生成项目,但在评估阶段不会发生实际的生成操作。Each pass builds a part of the in-memory objects that are later used in the execution phase to build the projects, but no actual build actions occur during the evaluation phase. 在每个环节中,将按照元素的显示顺序对其进行处理。Within each pass, elements are processed in the order in which they appear.

评估阶段中的各个环节如下:The passes in the evaluation phase are as follows:

  • 评估环境变量Evaluate environment variables
  • 评估导入和属性Evaluate imports and properties
  • 评估项定义Evaluate item definitions
  • 评估项Evaluate items
  • 评估 UsingTask 元素Evaluate UsingTask elements
  • 评估目标Evaluate targets

这些环节的顺序有重大影响,在自定义项目文件时无比了解这一点。The order of these passes has significant implications and is important to know when customizing the project file. 请参阅属性和项的评估顺序See Property and item evaluation order.

评估环境变量Evaluate environment variables

在此阶段中,环境变量用于设置等效属性。In this phase, environment variables are used to set equivalent properties. 例如,PATH 环境变量可作为属性 $(PATH) 提供。For example, the PATH environment variable is made available as a property $(PATH). 从命令行或脚本运行时,将正常使用命令环境,从 Visual Studio 运行时,将使用 Visual Studio 启动时生效的环境。When run from the command line or a script, the command environment is used as normal, and when run from Visual Studio, the environment in effect when Visual Studio launches is used.

评估导入和属性Evaluate imports and properties

在此阶段中,将读入整个输入 XML,包括项目文件和整个导入链。In this phase, the entire input XML is read in, including the project files and the entire chain of imports. MSBuild 创建一个内存中 XML 结构,该结构表示项目和所有导入文件的 XML。MSBuild creates an in-memory XML structure that represents the XML of the project and all imported files. 此时,将对不在目标中的属性进行评估和设置。At this time, properties that aren't in targets are evaluated and set.

由于 MSBuild 会在其进程中及早读取所有 XML 输入文件,因此在生成过程中对这些输入的任何更改都不会影响当前生成。As a consequence of MSBuild reading all the XML input files early on in its process, any changes to those inputs during the build process don't affect the current build.

任何目标之外的属性的处理方式与目标中属性的处理方式不同。Properties outside of any target are handled differently from properties within targets. 在此阶段中,只评估在任何目标外部定义的属性。In this phase, only the properties defined outside of any target are evaluated.

由于属性在属性环节按顺序进行处理,因此输入中任何位置的属性都可以访问在输入中较早出现的属性值,但不能访问后面显示的属性。Because properties are processed in order in the properties pass, a property at any point in the input can access property values that appear earlier in the input, but not properties that appear later.

由于在评估项之前处理属性,因此在属性环节的任何部分都不能访问任何项的值。Because the properties are processed before items are evaluated, you can't access the value of any item during any part of the properties pass.

评估项定义Evaluate item definitions

在此阶段中,将解释项定义,并创建这些定义的内存中表示形式。In this phase, item definitions are interpreted and an in-memory representation of these definitions is created.

评估项Evaluate items

在目标内定义的项与任何目标外定义的项的处理方式不同。Items defined inside a target are handled differently from items outside any target. 在此阶段中,将处理任何目标之外的项及其关联的元数据。In this phase, items outside any target, and their associated metadata, are processed. 由项定义设置的元数据将被项的元数据设置替代。Metadata set by item definitions is overridden by metadata setting on items. 由于项按其显示的顺序进行处理,因此你可以引用之前定义的项,但不能引用后面显示的项。Because items are processed in the order that they appear, you can reference items that have been defined earlier, but not ones that appear later. 因为项环节在属性环节之后,因此项都可以访问在任何目标外部定义的任何属性,无论稍后是否显示该属性定义。Because the items pass is after the properties pass, items can access any property if defined outside any targets, regardless of whether the property definition appears later.

评估 UsingTask 元素Evaluate UsingTask elements

在此阶段中,将读取 UsingTask 元素,并声明这些任务以供稍后在执行阶段使用。In this phase, UsingTask elements are read, and the tasks are declared for later use during the execution phase.

评估目标Evaluate targets

在此阶段中,将在内存中创建所有目标对象结构,以准备执行。In this phase, all target object structures are created in memory, in preparation for execution. 无实际执行发生。No actual execution takes place.

执行阶段Execution phase

在执行阶段,将对目标进行排序和运行,并执行所有任务。In the execution phase, the targets are ordered and run, and all tasks are executed. 但首先,在目标内定义的属性和项将以其显示顺序在单个阶段中进行评估。But first, properties and items that are defined within targets are evaluated together in a single phase in the order in which they appear. 处理顺序与不在目标中的属性和项的处理顺序截然不同:首先是所有属性,然后是在各个环节中的所有项。The order of processing is notably different from how properties and items that aren't in a target are processed: all properties first, and then all items, in separate passes. 对目标内的属性和项的更改可以在更改它们的目标之后观察到。Changes to properties and items within a target can be observed after the target where they were changed.

目标生成顺序Target build order

在单个项目中,目标按顺序执行。In a single project, targets execute serially. 核心问题在于如何确定生成所有内容的顺序,以便使用依赖项按正确顺序生成目标。The central issue is how to determine what order to build everything in so that dependencies are used to build the targets in the right order.

目标生成顺序由每个目标上 BeforeTargetsDependsOnTargetsAfterTargets 属性的使用决定。The target build order is determined by the use of the BeforeTargets, DependsOnTargets, and AfterTargets attributes on each target. 如果前面的目标修改了这些属性中引用的属性,则在执行前面的目标期间,后面的目标顺序会受到影响。The order of later targets can be influenced during execution of an earlier target if the earlier target modifies a property that's referenced in these attributes.

确定目标生成顺序中介绍了排序规则。The rules for ordering are described in Determine the target build order. 此过程由包含要生成的目标的堆栈结构决定。The process is determined by a stack structure containing targets to build. 此任务顶部的目标将开始执行,如果它依赖于任何其他内容,则会将这些目标推送到堆栈顶部,并开始执行。The target at the top of this task starts execution, and if it depends on anything else, then those targets are pushed onto the top of the stack, and they start executing. 如果目标没有任何依赖项,则会执行到完成,并继续执行其父目标。When there's a target without any dependencies, it executes to completion and its parent target resumes.

项目引用Project References

MSBuild 可以采用两种代码路径,一种是此处描述的普通路径,一种是下一部分中所述的图形选项。There are two code paths that MSBuild can take, the normal one, described here, and the graph option described in the next section.

单个项目通过 ProjectReference 项来指定它们对其他项目的依赖性。Individual projects specify their dependence on other projects through ProjectReference items. 当堆栈顶部的项目开始生成时,它将达到 ResolveProjectReferences 目标的执行点,即在公用目标文件中定义的标准目标。When a project on the top of the stack begins building, it reaches the point where the ResolveProjectReferences target executes, a standard target defined in the common target files.

ResolveProjectReferences 使用 ProjectReference 项的输入调用 MSBuild 任务以获取输出。ResolveProjectReferences invokes the MSBuild task with inputs of the ProjectReference items to get the outputs. ProjectReference 项转换为本地项,如 ReferenceThe ProjectReference items are transformed to local items such as Reference. 当前项目的 MSBuild 执行阶段将暂停,同时执行阶段开始处理引用项目(根据需要先完成评估阶段)。The MSBuild execution phase for the current project pauses while the execution phase begins to process the referenced project (the evaluation phase is done first as needed). 引用项目仅在你开始生成依赖项目后生成,因此,这会创建一个项目生成树。The referenced project only builds after you start building the dependent project, and so this creates a tree of projects building.

Visual Studio 允许在解决方案 (.sln) 文件中创建项目依赖项。Visual Studio allows creating project dependencies in solution (.sln) files. 依赖项是在解决方案文件中指定的,并且仅在生成解决方案或在 Visual Studio 内生成时才会考虑使用。The dependencies are specified in the solution file and are only respected when building a solution, or when building inside Visual Studio. 如果生成单个项目,则忽略此类型的依赖项。If you build a single project, this type of dependency is ignored. 解决方案引用由 MSBuild 转换为 ProjectReference 项,然后以相同的方式处理。Solution references are transformed by MSBuild into ProjectReference items and thereafter are treated in the same manner.

图形选项Graph option

如果指定图形生成开关(-graphBuild-graph),则 ProjectReference 会成为 MSBuild 使用的一级概念。If you specify the graph build switch (-graphBuild or -graph), the ProjectReference becomes a first-class concept used by MSBuild. MSBuild 将分析所有项目并构造生成顺序图,即项目的实际依赖项关系图,然后遍历该关系图以确定生成顺序。MSBuild will parse all the projects and construct the build order graph, an actual dependency graph of projects, which is then traversed to determine the build order. 与单个项目中的目标一样,MSBuild 确保引用的项目是在其所依赖的项目之后生成的。As with targets in individual projects, MSBuild ensures that referenced projects are built after the projects they depend on.

并行执行Parallel execution

如果使用多处理器支持(-maxCpuCount-m 开关),MSBuild 将创建节点,这些节点是使用可用 CPU 内核的 MSBuild 进程。If using multiprocessor support (-maxCpuCount or -m switch), MSBuild creates nodes, which are MSBuild processes that use the available CPU cores. 每个项目都被提交给一个可用节点。Each project is submitted to an available node. 在节点内,各个项目生成将按顺序执行。Within a node, individual project builds execute serially.

可以通过设置布尔变量 BuildInParallel 为并行执行启用任务,该变量是根据 MSBuild 中 $(BuildInParallel) 属性的值设置的。Tasks may be enabled for parallel execution by setting a boolean variable BuildInParallel, which is set according to the value of the $(BuildInParallel) property in MSBuild. 对于为并行执行启用的任务,工作计划程序会管理节点并将工作分配给节点。For tasks that are enabled for parallel execution, a work scheduler manages nodes and assigns work to nodes.

请参阅使用 MSBuild 并行生成多个项目See Building multiple projects in parallel with MSBuild

标准导入Standard imports

Microsoft.Common.props 和 Microsoft.Common.targets 都是由 .NET 项目文件导入的(在 SDK 样式项目中显式或隐式导入),并且位于 Visual Studio 安装的 MSBuild\Current\bin 文件夹中。Microsoft.Common.props and Microsoft.Common.targets are both imported by .NET project files (explicitly or implicitly in SDK-style projects) and are located in the MSBuild\Current\bin folder in a Visual Studio installation. C++ 项目具有其自己的导入层次结构;请参阅 C++ 项目的 MSBuild 内部层次结构C++ projects have their own hierarchy of imports; see MSBuild Internals for C++ projects.

Microsoft.Common.props 文件设置可重写的默认值。The Microsoft.Common.props file sets defaults you can override. 它在项目文件的开头导入(显式或隐式)。It's imported (explicitly or implicitly) at the beginning of a project file. 这样一来,项目设置将显示在默认值之后,这样就可以重写它们。That way, your project's settings appear after the defaults, so that they override them.

Microsoft.Common.targets 文件及其导入的目标文件定义 .NET 项目的标准生成过程。The Microsoft.Common.targets file and the target files it imports define the standard build process for .NET projects. 它还提供了可用于自定义生成的扩展点。It also provides extension points you can use to customize the build.

在实现中,Microsoft.Common.targets 是一个导入 Microsoft.Common.CurrentVersion.targets 的精简包装器。In implementation, Microsoft.Common.targets is a thin wrapper that imports Microsoft.Common.CurrentVersion.targets . 此文件包含标准属性设置,并定义可定义生成过程的实际目标。This file contains settings for standard properties, and defines the actual targets that define the build process. 此处定义 Build 目标,但实际上它是空的。The Build target is defined here, but is actually itself empty. Build 目标包含 DependsOn 属性,该属性指定构成实际生成步骤的各个目标,这些步骤是 BeforeBuildCoreBuildAfterBuildHowever, the Build target contains the DependsOn attribute that specifies the individual targets that make up the actual build steps, which are BeforeBuild, CoreBuild, and AfterBuild. Build 目标定义如下:The Build target is defined as follows:

  <PropertyGroup>
    <BuildDependsOn>
      BeforeBuild;
      CoreBuild;
      AfterBuild
    </BuildDependsOn>
  </PropertyGroup>

  <Target
      Name="Build"
      Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
      DependsOnTargets="$(BuildDependsOn)"
      Returns="@(TargetPathWithTargetPlatformMoniker)" />

BeforeBuildAfterBuild 是扩展点。BeforeBuild and AfterBuild are extension points. 它们在 Microsoft.Common.CurrentVersion.targets 文件中是空的,但项目可以提供自己的 BeforeBuildAfterBuild 目标,其中包含需要在主生成过程之前或之后执行的任务。They're empty in the Microsoft.Common.CurrentVersion.targets file, but projects can provide their own BeforeBuild and AfterBuild targets with tasks that need to be performed before or after the main build process. AfterBuild 在无操作目标 Build 前运行,因为 AfterBuild 出现在 Build 目标的 DependsOn 属性中,但在 CoreBuild 之后发生。AfterBuild is run before the no-op target, Build, because AfterBuild appears in the DependsOn attribute on the Build target, but it occurs after CoreBuild.

CoreBuild 目标包含对生成工具的调用,如下所示:The CoreBuild target contains the calls to the build tools, as follows:

  <PropertyGroup>
    <CoreBuildDependsOn>
      BuildOnlySettings;
      PrepareForBuild;
      PreBuildEvent;
      ResolveReferences;
      PrepareResources;
      ResolveKeySource;
      Compile;
      ExportWindowsMDFile;
      UnmanagedUnregistration;
      GenerateSerializationAssemblies;
      CreateSatelliteAssemblies;
      GenerateManifests;
      GetTargetPath;
      PrepareForRun;
      UnmanagedRegistration;
      IncrementalClean;
      PostBuildEvent
    </CoreBuildDependsOn>
  </PropertyGroup>
  <Target
      Name="CoreBuild"
      DependsOnTargets="$(CoreBuildDependsOn)">

    <OnError ExecuteTargets="_TimeStampAfterCompile;PostBuildEvent" Condition="'$(RunPostBuildEvent)'=='Always' or '$(RunPostBuildEvent)'=='OnOutputUpdated'"/>
    <OnError ExecuteTargets="_CleanRecordFileWrites"/>

  </Target>

下表对这些目标进行了说明;某些目标仅适用于某些项目类型。The following table describes these targets; some targets are applicable only to certain project types.

目标Target 描述Description
BuildOnlySettingsBuildOnlySettings 仅适用于实际生成的设置,而不适用于 Visual Studio 在项目加载时调用 MSBuild。Settings for real builds only, not for when MSBuild is invoked on project load by Visual Studio.
PrepareForBuildPrepareForBuild 准备生成的先决条件Prepare the prerequisites for building
PreBuildEventPreBuildEvent 项目的扩展点,用于定义在生成之前要执行的任务Extension point for projects to define tasks to execute before build
ResolveProjectReferencesResolveProjectReferences 分析项目依赖项并生成引用的项目Analyze project dependencies and build referenced projects
ResolveAssemblyReferencesResolveAssemblyReferences 找到引用的程序集。Locate referenced assemblies.
ResolveReferencesResolveReferences 包含 ResolveProjectReferencesResolveAssemblyReferences,用于查找所有依赖项Consists of ResolveProjectReferences and ResolveAssemblyReferences to find all the dependencies
PrepareResourcesPrepareResources 处理资源文件Process resource files
ResolveKeySourceResolveKeySource 解析用于对程序集进行签名的强名称密钥以及用于对 ClickOnce 清单进行签名的证书。Resolve the strong name key used to sign the assembly and the certificate used to sign the ClickOnce manifests.
CompileCompile 调用编译器Invokes the compiler
ExportWindowsMDFileExportWindowsMDFile 基于编译器生成的 WinMDModule 文件生成 WinMD 文件。Generate a WinMD file from the WinMDModule files generated by the compiler.
UnmanagedUnregistrationUnmanagedUnregistration 从上一个生成中删除/清除 COM 互操作注册表项Remove/clean the COM Interop registry entries from a previous build
GenerateSerializationAssembliesGenerateSerializationAssemblies 使用 sgen.exe 生成 XML 序列化程序集。Generate an XML serialization assembly using sgen.exe.
CreateSatelliteAssembliesCreateSatelliteAssemblies 为资源中的每个唯一区域性创建一个附属程序集。Create one satellite assembly for every unique culture in the resources.
生成清单Generate Manifests 生成 ClickOnce 应用程序和部署清单或本机清单。Generates ClickOnce application and deployment manifests or a native manifest.
GetTargetPathGetTargetPath 使用元数据返回包含此项目的生成产品(可执行文件或程序集)的项。Return an item containing the build product (executable or assembly) for this project, with metadata.
PrepareForRunPrepareForRun 将生成输出复制到最终目录(如果它们已更改)。Copy the build outputs to the final directory if they've changed.
UnmanagedRegistrationUnmanagedRegistration 设置 COM 互操作的注册表项Set registry entries for COM Interop
IncrementalCleanIncrementalClean 删除在先前生成中生成但未在当前生成中生成的文件。Remove files that were produced in a prior build but weren't produced in the current build. 这是使 Clean 在增量生成中工作的必须条件。This is necessary to make Clean work in incremental builds.
PostBuildEventPostBuildEvent 项目的扩展点,用于定义在生成之后运行的任务Extension point for projects to define tasks to run after build

上表中的许多目标都可在特定于语言的导入中找到,如 Microsoft.CSharp.targets。Many of the targets in the previous table are found in language-specific imports, such as Microsoft.CSharp.targets . 此文件定义特定于 C# .NET 项目的标准生成过程中的步骤。This file defines the steps in the standard build process specific for C# .NET projects. 例如,它包含实际调用 C# 编译器的 Compile 目标。For example, it contains the Compile target that actually calls the C# compiler.

用户可配置的导入User-configurable imports

除了标准导入外,还可以添加几个导入来自定义生成过程。In addition to the standard imports, there are several imports that you can add to customize the build process.

  • Directory.Build.propsDirectory.Build.props
  • Directory.Build.targetsDirectory.Build.targets

这些文件由其下任何子文件夹中的任何项目的标准导入读入。These files are read in by the standard imports for any projects in any subfolder under them. 这通常是解决方案级别的设置,用于控制解决方案中的所有项目,但在文件系统中也可能更高,直至驱动器的根目录。That's commonly at the solution level for settings to control all the projects in the solution, but could also be higher up in the filesystem, up to the root of the drive.

Directory.Build.props 文件由 Microsoft.Common.props 导入,因此项目文件中提供了其中定义的属性。The Directory.Build.props file is imported by Microsoft.Common.props , so the properties defined therein are available in the project file. 可以在项目文件中重新定义这些属性,以便基于每个项目自定义值。They can be redefined in the project file to customize the values on a per-project basis. 将在项目文件后读入 Directory.Build.targets 文件。The Directory.Build.targets file is read in after the project file. 它通常包含目标,但在这里,你还可以定义不希望个别项目重新定义的属性。It typically contains targets, but here you can also define properties that you don't want individual projects to redefine.

项目文件中的自定义项Customizations in a project file

当你在“解决方案资源管理器”、“属性”窗口或“项目属性”中进行更改时,Visual Studio 将更新项目文件,但你也可以通过直接编辑项目文件自行进行更改。Visual Studio updates your project files as you make changes in Solution Explorer , the Properties window, or in Project Properties , but you can also make your own changes by directly editing the project file.

许多生成行为可以通过设置 MSBuild 属性进行配置,可以在项目本地设置的项目文件中进行,也可以按照前面部分所述,通过创建 Directory.Build.props 文件为项目和解决方案的整个文件夹全局设置属性。Many build behaviors can be configured by setting MSBuild properties, either in the project file for settings local to a project, or as mentioned in the previous section, by creating a Directory.Build.props file to set properties globally for entire folders of projects and solutions. 对于命令行或脚本上的临时生成,还可以使用命令行上的 /p 选项为 MSBuild 的特定调用设置属性。For ad hoc builds on the command line, or scripts, you can also use the /p option on the command line to set properties for a particular invocation of MSBuild. 有关可设置的属性的信息,请参阅常见的 MSBuild 项目属性See Common MSBuild project properties for information about properties you can set.

后续步骤Next steps

除了在此描述的扩展点之外,MSBuild 进程还有其他几个扩展点。The MSBuild process has several other extension points other than the ones described here. 请参阅自定义生成See Customize your build. 以及如何扩展 Visual Studio 生成过程and How to extend the Visual Studio build process.

请参阅See also

MSBuildMSBuild