.NET 项目 SDK 介绍
2024-04-22 08:38:13

概述

.NET 项目基于 MSBuild 格式。 项目文件的根元素是 Project 元素。 Project 元素有一个可选的 Sdk 属性,该属性指定要使用的 SDK(和版本)。 若要使用 .NET 工具并构建你的代码,请将 Sdk 属性设置为可用 SDK 表中的其中一个 ID。

引用 Sdk

常见的引用方式:

1
2
3
<Project Sdk="Microsoft.NET.Sdk">
...
</Project>

这等价于:

1
2
3
<Project>
<Sdk Name="Microsoft.NET.Sdk" />
</Project>

MSBuild 会在顶部和底部导入Sdk.propsSdk.targets,实际在背后文件是这样子:

1
2
3
4
5
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
...
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

Sdk.propsSdk.targets 文件位于计算机中的位置:

1
%ProgramFiles%\dotnet\sdk\[version]\Sdks\Microsoft.NET.Sdk\Sdk

SDK 有哪些可用值可以参考官方文档

Sdk.props

Sdk.props 是项目导入的第一个文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!--
***********************************************************************************************
Sdk.props

WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.

Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
<_AfterSdkPublishDependsOn Condition="'$(_IsAspNetCoreProject)' == 'true'">AfterPublish</_AfterSdkPublishDependsOn>
<_AfterSdkPublishDependsOn Condition="'$(_IsAspNetCoreProject)' != 'true'">Publish</_AfterSdkPublishDependsOn>
</PropertyGroup>

<Target Name="AfterSdkPublish" AfterTargets="$(_AfterSdkPublishDependsOn)"></Target>

<PropertyGroup>
<!--
Indicate to other targets that Microsoft.NET.Sdk is being used.

This must be set here (as early as possible, before Microsoft.Common.props)
so that everything that follows can depend on it.

In particular, Directory.Build.props and nuget package props need to be able
to use this flag and they are imported by Microsoft.Common.props.
-->
<UsingMicrosoftNETSdk>true</UsingMicrosoftNETSdk>

<!--
Indicate whether the set of SDK defaults that makes SDK style project concise are being used.
For example: globbing, importing msbuild common targets.

Similar to the property above, it must be set here.
-->
<UsingNETSdkDefaults>true</UsingNETSdkDefaults>

<CustomAfterDirectoryBuildProps>$(CustomAfterDirectoryBuildProps);$(MSBuildThisFileDirectory)UseArtifactsOutputPath.props</CustomAfterDirectoryBuildProps>
</PropertyGroup>

<PropertyGroup Condition="'$(MSBuildProjectFullPath)' == '$(ProjectToOverrideProjectExtensionsPath)'">
<MSBuildProjectExtensionsPath>$(ProjectExtensionsPathForSpecifiedProject)</MSBuildProjectExtensionsPath>
</PropertyGroup>

<Import Project="$(AlternateCommonProps)" Condition="'$(AlternateCommonProps)' != ''" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="'$(AlternateCommonProps)' == ''"/>
<Import Project="$(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.props" />
</Project>

这里有个 AlternateCommonProps 属性值得留意一下,它可以用来替换接下来即将导入的 Microsoft.Common.props 文件,不过一般情况下用不到。

Microsoft.Common.props

Microsoft.Common.props 是第二个导入的文件,包含了一些初始化导入和钩子。
比如:

  • Directory.Build.props文件就是在这里导入的。
  • <ImportDirectoryBuildProps>属性可以决定是否导入Directory.Build.props
  • <CustomBeforeDirectoryBuildProps>Directory.Build.props之前导入。
  • <CustomAfterDirectoryBuildProps>Directory.Build.props之后导入。
  • 设置了中间目录<BaseIntermediateOutputPath>


从这个文件中可以看出,如果我们需要禁止导入Directory.Build.props文件或设置中间目录,就必须在Microsoft.Common.props导入前就设置好,那么引用 Sdk 时必须显示导入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Project>
<PropertyGroup>
<ImportDirectoryBuildProps>false</ImportDirectoryBuildProps>
<BaseIntermediateOutputPath>obj2\</BaseIntermediateOutputPath>
</PropertyGroup>

<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

<PropertyGroup>
...
</PropertyGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

预处理项目文件

使用dotnet msbuild -preprocess命令,可以看到 MSBuild 在包含 SDK 及其目标之后所显示的完全扩展的项目。

1
dotnet msbuild -preprocess:output.xml

我们便可以分析输出的 xml 文件,大概是一个几千行的项目文件,自上而下导入了各种 .props 和 .targets 文件,这有利于我们快速排查问题。

相关阅读

.NET 项目 SDK
使用 MSBuild 项目 SDK
Document the import order of the common msbuild extension points.