MSBuild入门(续)
MSBuild基本概念(续)
在上一篇简单的介绍了下MSBuild中的四个基本块,每块介绍比较单薄,在这里对在大多数的项目模版生成的*.*proj文件中比较常见一些用法和概念做些补充。主要有一下几方面:
MSBuild特殊字符
一些字符在MSBuild中代表着特殊的上下文含义,如下:
针对MSBuild的特殊字符转义需要用[%xx]这种方式,xx代表字符的ASCII十六进制值([%=%25][$=%24][@=%40]['=%27][;=%3B][?=%3F][*=%2A])。针对XML保留字符则使用<这种方式。 一般用到这些特殊字符的情况不多,见到时能知道是转义就可以了。
MSBuild条件
条件在*.*proj项目文件中非常常见,用Condition特性来表示一个布尔表达式,类似于if条件,几乎所有的元素都可以具有Conditon特性。一个简单的例子如下:
1 <?xml version="1.0" encoding="utf-8"?>
2 <!--condition.xml文件-->
3 <Project DefaultTargets="show" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
4 <PropertyGroup>
5 <!--Condition在属性、项、任务、目标生都有使用-->
6 <!--如果Configuration为空(''),则其值为Debug-->
7 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
8 <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
9 </PropertyGroup>
10 <ItemGroup>
11 <!--如果csfile1.cs文件存在就包含在CSFile项中-->
12 <CSFile Include="csfile1.cs" Condition="Exists('csfile1.cs')"></CSFile>
13 </ItemGroup>
14 <Target Name="show">
15 <!--输出Debug|x86-->
16 <Message Text="$(Configuration)|$(Platform)"/>
17 <!--输出空,因为csfile1.cs并不存在-->
18 <Message Text="@(CSFile)"/>
19 </Target>
20 </Project>
还有一些常用的表达式如!=、!、And、Or等。
MSBuild属性
上篇介绍到可以用$可以引用自定义的属性,除此之外亦可以引用系统的环境变量,如$(Path),以及 MSBuild保留属性(MSDN)。
属性除了可以在项目文件中声明是赋值外,在MSBuild命令行也允许设置属性的值(语法:/p:propertyName=value)。称作全局属性,这类属性会重写在项目文件中设置的属性值,保留属性除外的任何属性都可被这种方式覆盖其原值。 以上面示例为基础:[MSBuild condition.xml /p:Platform=x64],则最终输出结果就为Debug|x64了。
属性还有一种叫做任务发出属性,在上篇用到了,由Output元素的PropertyName特性指定了属性名,这类属性不像一般的声明式属性那样赋值,而是动态得到的值。是在项目文件中很常见的用法。
MSBuild项
项大都是用来引入文件用的,而文件会有一些附加信息,比如版本,语言等,而这些附加信息在项目文件中是以项的子元素的出现的,称为项的元数据。元数据是键/值的形式存储的,声明方式和属性相同。
1 <ItemGroup>
2 <!--如果csfile1.cs文件存在就包含在CSFile项中-->
3 <CSFile Include="csfile1.cs">
4 <!--声明元数据,必须为项的一级子元素-->
5 <!--引用方式:%(CSFile.Culture)-->
6 <Culture>zh-cn</Culture>
7 </CSFile>
8 </ItemGroup>
除了自定义的一些元数据外,系统还提供一些隐式存在的元数据,即不用声明即可使用,具体可参见MSBuild常见的已知元数据。引用这类元数据的语法和自定义的完全相同。
项转换允许把一个项的列表与另一个列表一一变换。比如下面的例子:
1 <?>
5 <CSFile Include="1.cs;2.cs"/>
6 <!--%(Filename)为项的元数据,由系统提供-->
7 <VBFile Include="@(CSFile->'%(Filename).vb')"/>
8 </ItemGroup>
9 <Target Name="show">
10 <!--输出1.cs;2.cs-->
11 <Message Text="@(CSFile)"/>
12 <!--输出1.vb;2.vb-->
13 <Message Text="@(VBFile)"/>
14 </Target>
15 </Project>
MSBuild任务
从上篇中我们对任务的认识是它是一个原子操作,用来执行某一项逻辑处理,但是xml格式的项目文件是没有这个处理能力的,所以这些任务都是映射到.NET类库中的一些类,由这些类来处理操作中的逻辑。具体来说都是实现ITask接口的类,ITask接口位于Microsoft.Build.Framework命名空间。当然我们也可以实现自己的任务类,直接实现ITask接口或者继承自Task(此抽象类实现了ITask接口的部分功能,可简化自定义任务类的编写,留出一个Execute抽象方法供子类重写自己的任务逻辑)。然后通过UsingTask元素映射到出一个任务元素。我就继承Task写一个简单的示例:
1 //AddTwoNumberTask.cs,需编译为dll
2 using System;
3 using Microsoft.Build.Utilities;
4 using Microsoft.Build.Framework;
5
6 /// <summary>
7 /// 继承Task,任务逻辑是处理加法
8 /// </summary>
9 public class AddTwoNumberTask : Task
10 {
11 /// <summary>
12 /// 定义一个加数,
13 /// 如果一个输入属性被要求必须输入,则用[Required]特性标识该属性
14 /// </summary>
15 public String Number1 { get; set; }
16 /// <summary>
17 /// 定义另一个加数
18 /// </summary>
19 public String Number2 { get; set; }
20 public override bool Execute()
21 {
22 this.Sum = (Int32.Parse(this.Number1) + Int32.Parse(this.Number2)).ToString();
23 return true;
24
25 }
26 /// <summary>
27 /// 定义一个输出参数,使用Output特性修饰该属性
28 /// </summary>
29 [Output]
30 public String Sum { get; set; }
31 }
1 <!--buildAddTaskDll.csproj-->
2 <?xml version="1.0" encoding="utf-8"?>
3 <!--从AddTwoNumberTask.cs源文件到编译成dll-->
4 <Project DefaultTargets="buildAddTaskDll" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5 <PropertyGroup>
6 <OutputType>Library</OutputType>
7 </PropertyGroup>
8 <ItemGroup>
9 <Reference Include="Microsoft.Build.Framework" />
10 <Reference Include="Microsoft.Build.Utilities.v4.0" />
11 <Reference Include="System" />
12 </ItemGroup>
13 <ItemGroup>
14 <Compile Include="AddTwoNumberTask.cs" />
15 </ItemGroup>
16 <Target Name="buildAddTaskDll">
17 <!--@(Reference->'$(MSBuildBinPath)\%(Identity).dll')表示项转换-->
18 <Csc Sources="@(Compile)"
19 References="@(Reference->'$(MSBuildBinPath)\%(Identity).dll')"
20 TargetType="$(OutputType)">
21 </Csc>
22 </Target>
23 </Project>
用MSBuild编译buildAddTaskDll.csproj项目文件。得到AddTwoNumberTask.dll程序集。再编写一个项目文件usingtask如下:
<?xml version="1.0" encoding="utf-8"?>
<!--使用自定义的任务做加法-->
<Project DefaultTargets="show" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="AddTwoNumberTask" AssemblyFile = "AddTwoNumberTask.dll"/>
<Target Name="show">
<AddTwoNumberTask Number1="1" Number2="2" >
<Output TaskParameter="Sum" PropertyName="SumValue"/>
</AddTwoNumberTask>
<!--输出3-->
<Message Text="$(SumValue)"/>
</Target>
</Project>
如果仔细看AddTwoNumberTask.cs文件就会发现
//如果Number1或者2不是数字,则此任务就会抛异常了
this.Sum = (Int32.Parse(this.Number1) + Int32.Parse(this.Number2)).ToString();
那么如果<AddTwoNumberTask Number1="1" Number2="2" >在这里加一个ContinueOnError=“true”,则表示会忽略掉逻辑处理中的错误,继续运行,否则会终止执行后续任务。如果任务有输出参数的话,Output元素总是作为任务的子元素出现,作为一个中间桥梁把任务的输出传输到属性或者项中。
MSBuild目标
Project根元素代表者一个项目文件,上面的例子我都会写一个DefaultTargets特性来指定该项目文件要执行的默认目标是哪一个。其实此特性是可选的,也是可以用分号分割写多个的,执行顺序依据书写顺序来判定,也可通过MSBuild命令行参数来传递:
msbuild /target:Build1;Build2
除此之外,Project元素还有一个可选特性InitialTargets,也支持多个目标。如果这两个特性都没有,则MSBuild先执行它遇到的第一个Target。Target有一个DependsOnTargets特性表示当前目标依赖另一个目标,效果就是DependsOnTargets特性指定的目标先于当前目标执行。这绕来绕去好多先后顺序关系,写一个示例看看吧。
1 <?xml version="1.0" encoding="utf-8"?>
2 <!--目标执行顺序-->
3 <!--如果InitialTargets特性存在,则首先执行此目标列表-->
4 <!--如果DefaultTargets特性存在,则继续执行此目标列表-->
5 <Project InitialTargets="B1;B2" DefaultTargets="B3;B4"
6 ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
7 <!--如果发现Target具有DependsOnTargets特性-->
8 <!--则先执行DependsOnTargets指定的目标-->
9 <!--MSBuild4新加入了RunBeforeTargets和RunAfterTargets特性-->
10 <!--其作用和DependsOnTargets类似,一前一后,不做演示了-->
11 <Target Name="B1" DependsOnTargets="B5">
12 <Message Text="B1"/>
13 </Target>
14 <Target Name="B2">
15 <Message Text="B2"/>
16 </Target>
17 <Target Name="B3">
18 <Message Text="B3"/>
19 </Target>
20 <Target Name="B4">
21 <Message Text="B4"/>
22 </Target>
23 <Target Name="B5">
24 <Message Text="B5"/>
25 </Target>
26 <!--结果为:B5 B1 B2 B3 B4-->
27 </Project>
Import元素
项目模版产生的*.*proj项目文件大量的使用这个元素,用来导入可重用的项目文件,其中最常见的一个应该是这个吧,如果你用C#开发的话。
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
MSBuildToolsPath或者是MSBuildBinPath,Project特性指定要导入的项目文件。Import元素像是一个占位元素,MSBuild在执行到此时会用*.targets替换掉此元素,就像本来就声明在这里一样,所以和*.targets文件有关的所有保留属性会被重置。 Import元素对导入文件的扩展名无要求,文件是正确的项目文件就行,但一般约定为*.targets。
总结和备注
了解了以上知识点后,阅读一般的项目模版生成的项目文件(*.*proj)应该是可以的了,下篇文章先认识几个重要的*.targets,为剖析项目文件做准备。
备注:针对项目文件中所指的“特性”是表示一个xml元素的“属性”。由于属性在MSBuild中有特殊含义,则MSDN文档一律把项目文件中的xml属性称作是特性,比如Message任务的Text特性。如有错误之处,欢迎指正!
http://www.cnblogs.com/linianhui/archive/2012/09/01/2666104.html#MSBuildPropertyGroup
MSBuild入门(续)的更多相关文章
- MSBuild的简单介绍与使用
MSBuild 是 Microsoft 和 Visual Studio的生成系统.它不仅仅是一个构造工具,应该称之为拥有相当强大扩展能力的自动化平台.MSBuild平台的主要涉及到三部分:执行引擎.构 ...
- MSBuild是什么?
MSBuild入门 MSBuild是什么? MSBuild全称(Microsoft Build Engine),是用来生成.NET程序的平台.您可能不知道它,但是如果您在使用VS做开发,那么一定时时刻 ...
- 使用微软的MSBuild.exe编译VS .sln .csproj 文件
最近在看一些算法和测试一些程序,以及帮团队测试程序,团队使用了vs开发环境创建的sln项目文件,我使用的是公司的机器,没有任何权限安装程序等操作,但是又需要编译一些程序,所以我想到了,使用MSBuil ...
- MSBuild学习记录
参考资料 官方文档 MSBuild入门 MSBuild的简单介绍与使用
- net中的编译
1.MSBuild 四个基本块(属性.项.任务.目标): MSBuild属性: 属性是一些键/值对,主要用来存储一些配置信息. MSBuild 项: 主要是存储一些项目文件信息,以及文件的元 ...
- WPF入门教程系列三——Application介绍(续)
接上文WPF入门教程系列二——Application介绍,我们继续来学习Application 三.WPF应用程序的关闭 WPF应用程序的关闭只有在应用程序的 Shutdown 方法被调用时,应用程序 ...
- [独孤九剑]持续集成实践(二)– MSBuild语法入门
本系列文章包含: [独孤九剑]持续集成实践(一)- 引子 [独孤九剑]持续集成实践(二)– MSBuild语法入门 [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBu ...
- SQLite入门与分析(二)---设计与概念(续)
SQLite入门与分析(二)---设计与概念(续) 写在前面:本节讨论事务,事务是DBMS最核心的技术之一.在计算机科学史上,有三位科学家因在数据库领域的成就而获ACM图灵奖,而其中之一Jim G ...
- (数字IC)低功耗设计入门(五)——RTL级低功耗设计(续)
二.RTL级低功耗设计(续) 前面一篇博文我记录了操作数隔离等低功耗设计,这里就主要介绍一下使用门控时钟进行低功耗设计. (4)门控时钟 门控时钟在我的第一篇博客中有简单的描述,这里就进行比较详细的描 ...
随机推荐
- CentOS 6.9下KVM虚拟机网络Bridge(网桥)方式与NAT方式详解(转)
摘要:KVM虚拟机网络配置的两种方式:NAT方式和Bridge方式.Bridge方式的配置原理和步骤.Bridge方式适用于服务器主机的虚拟化.NAT方式适用于桌面主机的虚拟化. NAT的网络结构图: ...
- java程序中没有错,但是项目上面显示一个红叉的解决办法
错误信息: 报Description Resource Path Location Type Java compiler level does not match the version of th ...
- GNU Debugger for Windows----GDB
This web page provides 32-bit and 64-bit binaries of gdb for Windows for download. Equation ...
- css/js(工作中遇到的问题)-6
页面resize方法 if(document.createEvent) { const event = document.createEvent ("HTMLEvents"); e ...
- 【mybatis】mybatis中 返回map集合
关于mybatis返回map集合的操作: 1.mapper.xml中写一个查询返回map的sql <select id="findMap" parameterType=&qu ...
- 版本控制SVN的使用笔记
安装 客户端和服务端下载地址,打开网址,根据自己的操作系统下载对应的版本,window用户服务端一般安装的是VisualSVN,客户端安装TortoiseSVN,在实际工作中,我们一般只需要安装Tor ...
- iOS:ShareSDk的分享
使用分享类的SDK其实有很多,例如友盟.ShareSDK等等,参照他们的文档集成起来并不是很难,可能出的一些问题也就是配置文件的问题,这里我个人使用了ShareSDK分享,具体操作可出现的问题如下: ...
- centos7 keepalived以及防火墙配置
安装和配置keepalived,网上有很多资料,但是都没有提到防火墙这块,而且很多都是互相抄袭的,就算配置对了也会遇到很多问题 在查阅资料的时候配置好了keepalived,但是出现了裂脑,即两台服务 ...
- 【云计算】k8s相关资料
参考资料: How to get started, and achieve tasks, using Kubernetes:http://kubernetes.io/docs/getting-star ...
- BST数据结构题
给定BST.改动BST,使得每一个点都是大于他的结点的值之和 关键是这题递归參数怎么设计,每一个点比他大的有两快.一个是右子书(假设有的话),还有一个是祖先里面比他大的,假设直接用这两个的话,找不到递 ...