使用 dotnet 和 MsBuild 构建 .NET 应用程序有啥区别?

Posted

技术标签:

【中文标题】使用 dotnet 和 MsBuild 构建 .NET 应用程序有啥区别?【英文标题】:What's the difference between using dotnet and MsBuild for building .NET applications?使用 dotnet 和 MsBuild 构建 .NET 应用程序有什么区别? 【发布时间】:2021-05-26 17:07:37 【问题描述】:

我第一次在没有使用 Visual Studio 的情况下进行了一些构建,显然我对 MsBuild 和构建过程的了解存在差距。

那么,下面的两个构建过程有什么区别呢?


选项 1:

dotnet build C:\Dev\trunk\Mvc.sln

这个选项使用“Build Engine version 16.8.3+39993bd9d for .NET”——我想这意味着这种方式可以用于 .NET Core,因为它没有引用“Framework”?


选项 2:

msbuild C:\Dev\trunk\Mvc.sln

此选项使用“Build Engine version 16.8.2+25e4d540b for .NET Framework”。


我的假设是“dotnet build”命令只是使用 MsBuild 的一种简写方式。但是,两者提供的日志记录完全不同,它们都产生不同的结果。

【问题讨论】:

相同的底层编译器,不同的东西调用它。编译器本身以 .NET Standard 2.0 为目标,并且可以在 .NET Framework 和 .NET Core/5 上运行。 MSBuild(如 VS)在 .NET Framework 上运行,而 dotnet build 在 .NET Core 上运行。尽管存在差异(例如,针对 .NET Core/5 的分析器只能在 dotnet build 下运行),但它们大体上是等效的。 MSBuild 可以处理非 SDK 风格的项目,而 dotnet build 只能处理 SDK 风格的项目(请记住,编译器本身不会解释 .csproj 文件) @canton7 感谢您的评论。在VS中构建时,它是如何做到的? .NET Core 项目是否会使用 dotnet build 而 .NET Framework 项目会使用 msbuild? 不,在 VS 中构建将始终在 .NET Framework 之上运行编译器:VS 有效地使用了 MSBuild。正在编译的应用程序的目标运行时(技术上)完全独立于编译器本身当前正在执行的运行时:在 .NET Framework 上运行的 Roslyn 可以发出由 .NET Core 执行的 IL。但是dotnet build 确实意味着编译器可以在不支持 .NET Framework(例如 Linux)的目标上运行,并且对于命令行使用来说它是一个整体上更好的界面 好的,这很有意义。感谢您花时间解释它以帮助我理解它,而不仅仅是因为它很容易而投反对票! 另外值得注意的是,该编译器是自带VS的,所以它的版本与VS的版本是一致的,升级VS可以获得新的编译器版本。编译器也包含在 .NET SDK 中,dotnet build 从已安装的 SDK 中加载编译器,因此您可以通过安装更高版本的 SDK 来升级它 【参考方案1】:

Roslyn - C# 编译器平台 - 是一个 .NET Standard 2.0 库,这意味着它可以在 .NET Framework 4.6.1+ 和 .NET Core 2.0+ 上运行(1) .

包含 MSBuild 的 Visual Studio 在 .NET Framework 上运行。当您使用 Visual Studio(或直接使用 MSBuild)构建项目时,它会在 .NET Framework 上运行 Roslyn。 Visual Studio 知道如何处理 SDK 样式的 csprojs 和旧的非 SDK 样式的 csprojs,并相应地调用 Roslyn。使用的 Roslyn 版本与 Visual Studio 版本相关。

dotnet build 是一个单独的工具,是一个 .NET Core 应用程序。它只知道如何构建 SDK 样式的 csprojs,并且它通过在 .NET Core 上运行 Roslyn 来做到这一点。 Roslyn 与 .NET Core SDK 一起分发,dotnet build 从这些已安装的 SDK 版本之一(通常是最新版本)加载 Roslyn。

这两种构建 C# 项目的方法或多或少是等效的,它们调用相同的编译器代码。但是,它们在可以运行的位置(Visual Studio 是 .NET Framework 和仅限 Windows,dotnet build 是 .NET Core 并且可以在多个平台上运行)以及它们是否可以构建旧的非 SDK 样式 csprojs 方面有所不同。 dotnet build 在命令行中使用也更好一些。

请注意,加载 Roslyn 的运行时与 Roslyn 可以发出的编译 IL 无关:在 .NET Framework 上运行的 Roslyn 可以发出由 .NET Core 执行的 IL,反之亦然。

如果您使用的分析器以 .NET Core 为目标(不太可能,因为鼓励分析器以 .NET Standard 2.0 为目标),这些将仅从 dotnet build 运行。


(1) 我使用“.NET Core”来指代 .NET Core 和 .NET 5+。

【讨论】:

以上是关于使用 dotnet 和 MsBuild 构建 .NET 应用程序有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

使用 MSBuild 构建 gRPC dotnet 核心项目时如何包含自定义目录

msbuild、dotnet sdks、azure、kudu等使用的环境变量列表

dotnet cli与新vs2017 msbuild的关系

dotnet 通过引用 msbuild 程序集实现自己定制编译器

dotnet 通过引用 msbuild 程序集实现自己定制编译器

MSBuild - 在构建中集成跨平台编译器