天呐!你知道MSBuild都干了些什么

一个典型的.NET5.0项目文件是这样的,看着非常简洁:

<Project Sdk="Microsoft.NET.Sdk.Web"><PropertyGroup><TargetFramework>net5.0</TargetFramework></PropertyGroup><ItemGroup><PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" /></ItemGroup></Project>

但是,当我们执行“生成”时,却可以看到输出了大量日志,完全不知道这些目标都是哪来的? 

我们知道,生成操作实际是由MSBuild执行的。

那么,MSBuild到底干了什么?

查看日志

虽然,只要你在选项里设置日志级别为“诊断”,项目生成时会输出非常详细的日志记录: 

但是,这样生成的文本日志量太大了,要找出需要的信息难如登天。

这时,我们可以使用“MSBuild结构化日志查看器”,以可视化的方式查看日志。

安装

查看器的安装依赖Chocolatey。

首先,以管理员身份打开命令提示符,运行下列命令安装Chocolatey:

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

然后,运行下列命令安装日志查看器:

choco install msbuild-structured-log-viewer

生成日志

打开MSBuild Structured Log Viewer,选择“Open Project/Solution”,打开我们新建的Web API示例项目WebApplication1.sln,点击“Build”按钮生成日志:

运行完成后,你应该可以看到如下内容:

点击项目名称左边的箭头展开后,可以看到MSBuild准备执行的所有目标,每个目标中包含多个任务:

灰色的表示跳过的目标,展开后可以看到跳过的原因。

下面,我们以bin\Debug\net5.0\Swashbuckle.AspNetCore.Swagger.dll文件怎么输出的为例,演练如何分析日志。

分析日志

Copy任务

在左侧Search Log窗口上方,输入bin\Debug\net5.0\Swashbuckle.AspNetCore.Swagger.dll作为条件:

可以看到文件是由_CopyFilesMarkedCopyLocal目标中的Copy任务生成的,选中后在中间Log窗口双击任务名,会在右侧窗口显示任务详情,原来任务来源于MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets文件。

Copy任务作用是将源文件ReferenceCopyLocalPaths复制到目标文件$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)

那么源文件和目标文件的值,又是从哪来的呢?

OutDir属性

我们可以轻易地查找到$(OutDir)的值等于bin\Debug\net5.0,却没看到bin\Debug\net5.0这个值是由谁赋给它的:

通过左侧的Find In Files窗口,原来它来自于MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets文件,从OutputPath赋值:

metaproj文件

OutputPath的值来源于同一个文件,等于$(BaseOutputPath)$(Configuration)\

BaseOutputPath也来源于这个文件。但奇怪的是,Configuration却来源于一个叫做WebApplication1.sln.metaproj的文件:

项目目录下并没有这个文件啊?!

随后,我们在日志中找到这样一条消息:

已生成元项目“D:\Codes\WebApplication1\WebApplication1.sln.metaproj”。

而且,在WebApplication1.sln.metaproj中,我们还可以找到Rebuild目标:

而Rebuild又依赖于其他目标:

你还记得生成日志时,带的/t:Rebuild参数吗?

现在清楚了,MSBuild启动时首先生成.metaproj文件,然后根据文件中的元数据,按照依赖关系执行目标。

DestinationSubDirectory属性

但是,%(DestinationSubDirectory)在日志里并没有找到任何赋值的位置。

试着继续探索原始文件来源,最终定位到了ResolvePackageAssets目标下的ResolvePackageAssets任务:

具体参数值对应任务的输出参数RuntimeAssemblies

<Output TaskParameter="RuntimeAssemblies" ItemName="RuntimeCopyLocalItems" />

查看dotnet/sdk/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs的源码,RuntimeAssemblies的类型是ITaskItem[]

ITaskItem定义如下:

public interface ITaskItem
{string ItemSpec { get; set; }int MetadataCount { get; }ICollection MetadataNames { get; }IDictionary CloneCustomMetadata();void CopyMetadataTo(ITaskItem destinationItem);string GetMetadata(string metadataName);void RemoveMetadata(string metadataName);void SetMetadata(string metadataName, string metadataValue);
}

接着,我们找到这样一段代码:

if (!string.IsNullOrEmpty(destinationSubDirectory))
{WriteMetadata(MetadataKeys.DestinationSubDirectory, destinationSubDirectory);
}

DestinationSubDirectory原来是Metadata啊!

结论

根据上面的分析,可以梳理出bin\Debug\net5.0\Swashbuckle.AspNetCore.Swagger.dll文件如何输出的整个流程:

  • MSBuild启动,根据项目文件生成.metaproj文件

  • MSBuild根据/t参数, 从.metaproj文件中读取目标

  • 根据目标的依赖关系,按顺序执行其他目标

  • 其中,ResolvePackageAssets目标下的ResolvePackageAssets任务获取项目所有依赖包的Metadata

  • 再由_CopyFilesMarkedCopyLocal目标中的Copy任务遍历依赖包,根据Metadata复制文件到指定目录下的指定文件名

现在,你可以跟同事show一下:我知道MSBuild干了什么!

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/300379.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

笑到打鸣~ | 今日趣图

全世界只有3.14 % 的人关注了青少年数学之旅视频来源网络

JAVA拾遗1

JAVA拾遗1 1 static修饰符 类的成员变量分为静态变量和实例变量, 被stacit修饰的变量,叫静态变量,没被修饰的就是实例变量了. 静态变量的特点,在于其在内存中只有一个COPY,在使用时不需要实例化,直接用类名来调用就可以了. 同样,比如 public static int add()…

Tech·Ed 2006中国 实况报道

比较懒&#xff0c;哈哈&#xff0c;将就把园子里的几位兄弟的报道转载过来了&#xff0c;俱乐部的兄弟们先欣赏到&#xff0c;有时间我在写点报道了 :)全球首发----TechEd 2006中国 实况报道。全程跟踪。(一)全球首发----TechEd 2006中国 实况报道。全程跟踪。(二)全球首发---…

为什么理工类专业成绩好的人,英语总是很差?

▲ 点击查看在知乎上曾经有一个话题&#xff1a;为什么会有数学很好但英语很差的人&#xff1f;这个话题还被浏览了四十多万次。说起这个话题&#xff0c;评论中很多人也纷纷表示感同身受。在上学的时候&#xff0c;要么英语成绩好到飞起&#xff0c;要么数学成绩牛逼到不行。…

php大数组查找算法,PHP简单的数组查找算法分享

PHP中对于数组的查找可以用顺序查找或二分法查找。其中顺序查找比较简单&#xff0c;就是逐个比较查找。但缺点也较明显&#xff0c;如果查找的元素恰巧在最后一个&#xff0c;循环的次数过多。1.顺序查找算法描述在数组中逐个查找&#xff0c;确认是否有某个元素&#xff0c;存…

.Net Core with 微服务 - Polly 服务降级熔断

在我们实施微服务之后&#xff0c;服务间的调用变的异常频繁。多个服务之间可能是互相依赖的关系。某个服务出现故障或者是服务间的网络出现故障都会造成服务调用的失败&#xff0c;进而影响到某个业务服务处理失败。某一个服务调用失败轻则造成当前相关业务无法处理&#xff1…

IfElseActivity

IfElseActivity 1.IfElseActivity有两个IfElseBranch子控件&#xff0c;分别作为IfElse的两个分支容器,系统自动添加&#xff0c; 2.其中左边(为真件条)的IfElseBranch容器要设Condition 3.IfElse左边(为真件条)的IfElseBranch容器的Condition有两个条件模式:Code Condition,De…

vim cheat-sheet

Vim 命令小抄original card by Laurent Gregoires redesign by brohan基本移动 插入模式 撤消&#xff0c;重做 h l j k左/右 移动一个字符&#xff1b;上/下 移动一行 ^Vc ^Vn插入字符 c 的本义/十进制值 n u U撤销最近的改动 / 恢复最近被改动的行b w向 左/右 移动一个单词…

递归与非递归法实现链表相加 CC150 V5 2.5题 java版

前言&#xff1a;这是一道很有意思的题目&#xff0c;原题如下&#xff1a;You have two numbers represented by a linked list, where each node contains a single digit. The digits are stored in reverse order, such that the 1’s digit is at the head of the list. W…

荷兰人发明的新客机是劈叉的!乘客坐在机翼上

全世界只有3.14 % 的人关注了青少年数学之旅与汽车外型的复杂多变相比&#xff0c;飞机的外型似乎总是那么朴实无华&#xff0c;不管是客机还是战斗机&#xff0c;大约都是大家习以为常的那个样子……但是&#xff0c;终于有人要推陈出新了&#xff01;荷兰皇家航空公司与代尔夫…

预约 .NET Conf: Focus on F# 活动,赢得官方周边!

James: 最近 .NET 基金会预告了将在本月29日底举行的 .NET Conf: Focus on F# 线上活动&#xff0c;预约这次活动还能有机会赢得官方大礼包。.NET Conf: Focus on F# 是一个免费的、为期一天的直播活动&#xff0c;会上有来自社区和使用f#语言的微软团队的演讲者。学习 F# 如何…

【转】测试人员的思想理念和工作方法

测试人员的思想理念和工作方法 软件测试的前提假设 测试人员进行软件测试的基本假设是“有罪推断” &#xff0c;即认为被测程序一定是有bug的&#xff0c;而且每个功能点的实现都存在bug&#xff0c;而且一定存在严重的bug。 请牢记这个假设 &#xff0c;一旦在日后的工作过程…

.NET Day in China(上海-今日活动)| 线上线下

点击蓝字关注我们活动简介.NET 6 Preview 6 在 7月14日已经发布&#xff0c;.NET 6 是微软开启全平台统一一个 .NET 计划以来的第一个 LTS 版本&#xff0c;意义重大&#xff0c;微软在 .NET 6 引入了 MAUI&#xff0c;跨平台开发将更为简单&#xff0c;ASP.NET Core 也在不断的…

公司重金求数据分析师:为什么90%的公司都需要它?

全世界只有3.14 % 的人关注了青少年数学之旅混迹互联网的同学们&#xff0c;或多或少都对“数据分析师”这一职业有所耳闻。即使你不认识任何数据分析师&#xff0c;也一定看到过这类研究报告或者文章&#xff1a;Smart is the new sexy. 酷炫的图表&#xff0c;理性的分析阐述…

php定位和天气,基于thinkphp实现依据用户ip判断地理位置并提供对应天气信息的应用...

基于thinkphp实现根据用户ip判断地理位置并提供对应天气信息的应用我们都知道&#xff0c;在很多的网站都提供了给用户提供天气预报的功能&#xff0c;有时会发现&#xff0c;用户即使不输入任何和自己有关的地理位置信息&#xff0c;同样的网站也可以去判断地理位置并且显示天…

php配置问题汇总

前两天开始跟进PHP&#xff1b;我觉得&#xff0c;PHP的环境配置远比其他语言的要复杂很多。我所说的“其他语言”&#xff0c;包括Java&#xff0c;Oracle&#xff0c;scala&#xff0c;Python等。到现在PHP的环境被搭好&#xff0c;因为是全手动的配置&#xff0c;我完完整整…

Orchard Core 1.0.0 正式发布!

James: Orchard 最早是微软的员工创造的开源项目&#xff0c;使用的技术架构可以说是非常优秀&#xff0c;源码值得学习。功能也非常强大&#xff0c;支持模块化、多租户、工作流等等功能&#xff0c;可以说是 .NET 世界的 WordPress。一开始是.NET Framework 的&#xff0c;在…

[方法“Boolean Contains(System.Guid)”不支持转换为 SQL]的解决办法

Guid ClsID newGuid("d4ee9c52-8d68-4f33-9485-0926281c78ac");IList<Guid>Ids WebProduct.GetAllChildByID(ClsID);var query db.T_Products.Where(p >Ids.Contains((Guid)p.F_ClsID));//这一句编译时无错&#xff0c;但是一执行&#xff0c;就报错出错信息…

解决IE为7939.com的病毒~

病毒名称&#xff1a;“诡秘下载器”变种CXW&#xff08;Trojan.DL.Delf.cxw&#xff09;病毒类型&#xff1a;流氓软件病毒危害级别&#xff1a;★★★☆该病毒运行后会从***指定的网站下载指令并运行&#xff0c;会将用户IE浏览器的主页锁定为一个名叫“7939上网导航”的网站…

这哥们到底是应聘的还是来收购公司的?| 今日趣图

全世界只有3.14 % 的人关注了青少年数学之旅图源网络&#xff0c;侵权删