艾伟:MSBuild 简解

简介:   从最原始的编译器,逐渐到 Shell 命令组合、Make工具,到现在的针对性 Build 工具,Rake、Ant、MSBuild,甚至于 PowerShell 这样的工具;都为我们软件开发以及系统管理做出了贡献,我甚至不能想象几十年前使用编译器生成程序的复杂步骤(其实就是把 makefile 拆开,相当恐怖)。

  从最原始的编译器,逐渐到 Shell 命令组合、Make工具,到现在的针对性 Build 工具,Rake、Ant、MSBuild,甚至于 PowerShell 这样的工具;都为我们软件开发以及系统管理做出了贡献,我甚至不能想象几十年前使用编译器生成程序的复杂步骤(其实就是把 makefile 拆开,相当恐怖)。

  探讨 Make、Ant 以及 MSBuild 无太多意义,甚至从纯技术和扩展性上来说,我认为 MSBuild 弱于 NAnt,但是软件并不是这么简单,之所以深研 MSBuild,M$ 作为后盾让人信任的无奈。

  本文主要讲述 MSBuild 的基本概念,以及如何使用它辅助开发。

  首先我们来看一个最简单的 Build:

 
 
< Project ToolsVersion ="3.5" DefaultTargets ="Build" xmlns ="http://schemas.microsoft.com/developer/msbuild/2003" > < PropertyGroup > < Welcome > Hello MSBuild! Welcome> Property> <Target Name="Build"> <Message Text="$(Hello)" /> Target> Project>


  假设我们把这个文件保存到 D:\build.proj ,然后在命令行切换工作目录到 D:\,运行 msbuild.exe(msbuild 默认直接运行当前目录下的 *.sln 或 *.*proj 文件),则命令行将会显示详细的 build 信息,当然也包括我们的消息 'Hello MSBuild!' 。

概念

Project
  Project 代表一个 Build,有属性 ToolsVersion、DefaultTargets、 InitialTargets,分别为 依赖的 MSBuild 版本、默认 Build 目标,初始化目标。

Property
  Property 是 MSBuild 中的基本单元,可以理解为变量,我们可以在大多数地方使用它作为 Task 的参数以完成我们预期的目标。
  下面的语句示范如何声明 Property:

 
  
< PropertyGroup > < Name Condition ="$(Name) == ''" > Kate Name> <WorkPath>D:\Workspace WorkPath> PropertyGroup>

  这里定义了两个 Property,我们可以使用 $(Name) 和 $(WorkPath) 来引用它们,就和前面的范例一样。
  Property 可以使用 MSBuild 的 /p 参数定义,这里就使用 Condition 属性判断是否存在外部 Name,如果不存在则使用自定义的 "Kate"。

Target
  Target 是 Build 的基本单元,也对应 MSBuild 的 /t 参数,可用参数有 DependOnTargets,代表依赖的目标。

Task
  Task 即任务,Build 的过程就是若干 Task 的执行。上面的 就是 MSBuild 内置的一个 Task,Text 则是参数。
  Task 可以使用 Condition 属性。
  通常情况下,MSBuild 自带的 Task 并不够用,有以下 MSBuild 扩展,可以几乎不需要自己写扩展:
  * MSBuild Community Tasks
  * SDC Tasks Library
  * MSBuild Extension Pack

Item
  我们可以简单的把 Item 理解为 .Net 中的 Dictionary> 类型,内层的字典被称作元数据表。

 

 
  
< ItemGroup > < Table Include ="A;B;C;D" /> < Game Include ="StarCraft" /> < Game Include ="WarCraft" /> < Game Include ="CoderCraft" /> < Program Include ="MyApp" > < Developer > Zealic Developer> <Timestamp>2009-01-01T11:22:33 Timestamp> Program> ItemGroup>

  为方便理解,我们可以用 C# 来表述上述内容。
 
  
var Table = new Dictionary < string ,Dictionary < string , string > { { " A " , new Dictionary < string , string > }, { " B " , new Dictionary < string , string > }, { " C " , new Dictionary < string , string > }, { " D " , new Dictionary < string , string > } }; var Game = new Dictionary < string ,Dictionary < string , string > { { " StarCraft " , new Dictionary < string , string > }, { " WarCraft " , new Dictionary < string , string > }, { " CoderCraft " , new Dictionary < string , string > } } var Program = new Dictionary < string ,Dictionary < string , string > { { " MyApp " , new Dictionary < string , string > { " Developer " , " Zealic " , " Timestamp " , " 2009-01-01T11:22:33 " } } };

和使用 Property 不同,Item 有如下用法:
* @(Table) : 直接传递 Item 或展开为 A;B;C;D (视 Task 参数类型而定)。
* @(Table, '+') : 以指定的分隔符展开 Item,结果为 A+B+C+D
* @(Table -> '%(Identity).dll') : 转换 Item 为 A.dll;B.dll;C.dll;D.dll
* %(Program.Developer) : 引用 Program Item 的元数据 "Developer";此外,以这种方式使用 Item 都会导致循环所有 Item 成员。比如 ,会导致三次 Task 调用,分别输出 StarCraft, WarCraft 以及 CoderCraft;Identity 代表 Item 的名称,有关 Item 的更多预定义元数据,请参考 MSDN

Item 可以使用 Condition 属性。

 

结语

  可能有人会问,既然 MSBuild 和批处理能做的事都差不多,为什么不直接使用批处理呢?

  有以下几点原因:

    * 与 .Net Framework 紧密集成。
    * 易于扩展:你可以使用任何 CLR 上的语言编写 MSBuild Task 进行扩展。
    * 高效率:多个解决方案/项目可以在一个解决方案中编译,甚至支持多核下的并行编译。
    * 利于诊断:MSBuild 可扩展的日志系统使得 build 过程几乎和白盒没有区别,你可以看到 build 的每一步细节。这也是 VS2003 转到 VS2005 之间最大的转变 - IDE 对编译过程的感知从黑盒转变到白盒。

  此外,利用众多第三方 Task,MSBuild 可以完成诸如持续集成、管理服务器、自动化部署等任务,解放我们的时间,让我们可以有更多的时间  Coding 或偷懒 -_-。

  了解到这些内容以后,聪明的读者,你是否已经打开一个正在开发的项目的 *.csproj 文件,用文本编辑器看看 MSBuild 究竟有什么魔法呢?

  PS:文章写的比较简单,不够全面,有问题请给我妹儿 Zealic  ,我将详细为你解答。或访问我的 Twitter,里面有不少小技巧。

2009-3-28 Zealic

目录
相关文章
|
6月前
|
传感器 人工智能 监控
医院不良事件管理系统:PDCA持续改进,形成事件的整改闭环管理
医院安全事件管理系统通过全流程闭环管理、多维度分析与RCA根因分析,助力上报与处理高效协同,支持智能流转、风险预警与持续改进,提升医疗质量与患者安全。
652 5
|
7月前
|
存储 Java 物联网
如何快速开发一套智慧校园电子班牌系统?
简介:本文详解如何快速开发智慧校园电子班牌系统,涵盖技术栈选型、模块化开发策略、云端与终端协同方案,并提供源码二开建议,助力两个月内高效交付,适用于多校落地应用。
315 0
|
8月前
|
存储 Java 容器
偏向锁
偏向锁是JVM为提升单线程环境下锁性能而引入的优化机制。其核心思想是将锁偏向首个获取它的线程,避免无竞争时的同步开销,从而提高执行效率。适用于锁由同一线程多次获取、无并发竞争的场景。一旦出现多线程竞争,偏向锁会撤销并升级为更高级别的锁。合理使用可显著提升性能,但在高并发环境下需谨慎配置。
161 0
|
5月前
|
机器学习/深度学习 人工智能 自然语言处理
47_历史里程碑:从ELIZA到Transformer
在当今的数字时代,我们已经习惯于与智能助手对话、向大语言模型提问,甚至依赖它们生成创意内容。然而,这看似理所当然的人机对话能力,实际上经历了长达半个多世纪的曲折发展历程。从1966年麻省理工学院的简陋程序,到2017年Google提出的革命性架构,聊天AI的演变不仅是技术的进步,更是人类对自身语言本质探索的缩影。
|
5月前
|
数据采集 供应链 程序员
爬坑 10 年!1688 店铺全量商品接口实战:从 memberId 解析、分页优化到数据完整性闭环
本文深度解析1688店铺全量商品接口实战经验,涵盖memberId解析、分页优化、数据完整性校验等核心难点,结合代码示例与避坑清单,助力开发者高效对接B2B供应链数据,少走两年弯路。
|
8月前
|
JSON 安全 API
人车关系核验 API:核验一致性的Python调用指南
在现代交通管理中,“人车不符”“证照分离”等问题频发,影响监管与安全。为此,基于多源数据的人车关系核验API应运而生,提供实时身份一致性验证,支撑智慧交通建设。
325 0
快手自动抢红包辅助插件,快手抢红包福袋脚本全自动,智能抢包软件按键版
这是一套快手自动抢红包插件源码,通过模拟点击实现自动化操作。例如准备100个快手账号配合此插件挂机抢红包
|
11月前
|
人工智能 Serverless 调度
突破地域限制,实现算力无限供给 —阿里云ACK One注册集群开启多地域Serverless算力调度
本文介绍了阿里云ACK One注册集群多地域Serverless算力调度解决方案,解决传统数据中心在AI时代面临的算力不足问题。方案通过分钟级接入、100%兼容Kubernetes操作及云上Serverless弹性,实现跨地域弹性算力供给,支持高并发请求与模型快速迭代。文中详细描述了快速接入步骤、指定地域调度及动态调度方法,并提供了相关代码示例。该方案助力企业实现AI推理服务的规模化部署,提升商业落地效率。
|
网络架构
ensp :使用静态协议实现两台pc之间的通信
ensp :使用静态协议实现两台pc之间的通信
959 0
ensp :使用静态协议实现两台pc之间的通信
什么是调用结构?西门子S7-1200的调用结构如何使用?
今天我们来介绍一下西门子S7-1200的调用结构。在西门子S7-1200中采用调用结构来描述用户程序中块的调用层级,调用结构提供了几个方面的信息,包括所用的块,对其它块的调用,各块之间的关系,每个块的数据要求以及块的状态等
什么是调用结构?西门子S7-1200的调用结构如何使用?

热门文章

最新文章