解读 Microsoft.NET.Sdk 的源码,你能定制各种奇怪而富有创意的编译过程
在 csproj 中,Project?中的?Sdk?屬性是 MSBuild 15.0 開始支持的,也就是 Visual Studio 2017 開始支持。有了 Sdk 屬性的存在,MSBuild 編譯過程能夠擴展得非常強大,而不止是過去?Import?的一個?props?和?targets?文件。
本文將介紹 Microsoft.NET.Sdk 的源碼,以及利用源碼中的一些線索來完成官方文檔中沒有提及的功能擴展。
This post is written in?multiple languages. Please select yours:
在計算機上全局搜索?Microsoft.NET.Sdk?可以找到不同版本的多個 Sdk 目錄,由于我安裝了 .NET Core 3.0,所以找到的目錄是:C:\Program Files\dotnet\sdk\3.0.100-preview6-012264。當然,按照官網 How to: Reference an MSBuild Project SDK 的描述,如果自己實現了一套 Sdk,也可以以 NuGet 包的形式發布。
?搜索 Microsoft.NET.Sdk
▲ 我計算機上的 Sdk 文件夾
Sdk 中的 NuGet 部分在 GitHub 上的倉庫地址:
NuGet.Client/src/NuGet.Core at dev · NuGet/NuGet.Client
在打開看?Microsoft.NET.Sdk?的目錄結構后,我們可以發現這幾乎就是 NuGet 包要求的目錄結構。
關于 NuGet 包的目錄結構,我在下面兩篇文章中都有提到過:
如何創建一個基于 MSBuild Task 的跨平臺的 NuGet 工具包
如何創建一個基于命令行工具的跨平臺的 NuGet 工具包
官方對 NuGet 的目錄結構也有介紹:How to create a NuGet package from a convention-based working directory。
不過,Sdk 類型的 NuGet 包會多一個?Sdk?文件夾。
Sdk?文件夾中的?Sdk.props?和?Sdk.targets?是會被默認?Import?的,這一點在官方文檔 How to: Reference an MSBuild Project SDK - Visual Studio 中是有說明的,以下兩段代碼的含義相同:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net48</TargetFramework> </PropertyGroup></Project><Project> <!-- Implicit top import --> <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" /> <PropertyGroup> <TargetFramework>net48</TargetFramework> </PropertyGroup> <!-- Implicit bottom import --> <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /></Project>由于這兩個文件的默認引入,Sdk 可以完成非常多的編譯任務。而且通常 Sdk 帶有擴展性,使得我們可以很方便地對項目的編譯過程進行擴展,這一點在我前面提到了兩篇制作 NuGet 工具包的文章中都有說明。
在 Sdk 文件夾中搜索?Target?節點的個數,我得到了 174 個(隨 .NET Core 2.1 發布);不過有一些是同名的,會被重寫(類似于 C#/.NET 中的繼承和重寫);核心的并沒有那么多。
CollectPackageReferences?用于收集?PackageReference?收集到的所有依賴(也就是 NuGet 包依賴)
CoreCompile?核心的編譯過程
GenerateAssemblyInfo?用于生成?AssemblyInfo.cs?文件(以前可是手工寫的呢)
Pack?用于將當前程序集打包成一個 NuGet 包
GenerateNuspec?在打包之前生成 nuspec 文件
下面是 Microsoft.NET.Sdk 中發現的一些富有創意的編譯過程:
<Target Name="DontRestore" BeforeTargets="Restore"> <Error Text="This project should not be restored" /> </Target>▲ 如果有?Restore,那么讓你編譯不通過
<Target Name="ReferenceStaticLegacyPackage" BeforeTargets="CollectPackageReferences"> <ItemGroup> <PackageReference Remove="LiteDB" /> <PackageReference Include="LiteDB" Version="2.0.2" /> </ItemGroup></Target>▲ 這是我另外寫的一篇文章:阻止某個 NuGet 包意外升級
參考資料
How to: Reference an MSBuild Project SDK - Visual Studio - Microsoft Docs
原文地址:https://walterlv.com/post/read-microsoft-net-sdk.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結
以上是生活随笔為你收集整理的解读 Microsoft.NET.Sdk 的源码,你能定制各种奇怪而富有创意的编译过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#8.0: 在 LINQ 中支持异步的
- 下一篇: asp.net ajax控件工具集 Au