本文参考自MSDN的一篇文章,从零开始创建MSBuild C#项目文件。

准备条件

  • 一个好用的文本编辑器,例如Atom或者Sublime Text。
  • MSBuild命令行工具。如果已经安装了Visual Studio的话,应该可以在开始菜单中找到类似Visual Studio 2015的MSBuild命令提示符 这样的项目。

创建程序

首先打开MSBuild命令提示符,然后切换到你想要创建项目的文件夹,例如我的文档或者桌面。然后,输入md HelloWorld创建一个名为HelloWorld的文件夹。然后输入cd HelloWorld切换到这个文件夹。为简便起见,下面所说的命令提示符,都是指这里的MSBuild命令提示符。

使用你最喜欢的文本编辑器,在HelloWorld文件夹中创建一个名为helloworld.cs的代码文件,文件内容如下:

using System;class HelloWorld
{static void Main(){
#if DebugConfigConsole.WriteLine("WE ARE IN THE DEBUG CONFIGURATION");
#endifConsole.WriteLine("Hello, world!");}
}

将文件保存之后,就可以在命令提示符中使用C#编译器工具csc编译该文件了。

csc helloworld.cs

然后就可以运行生成的helloworld.exe来查看编译生成的文件了。

helloworld.exe

应该可以在命令提示符中看到程序的输出。然后,删除生成的exe,准备下一步。

创建MSBuild项目文件

用文本编辑器创建名为Helloworld.csproj的文件,文件内容如下:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><ItemGroup><Compile Include="helloworld.cs" /></ItemGroup><Target Name="Build"><Csc Sources="@(Compile)"/>  </Target>
</Project>

下面来简单解释一下。

csproj项目文件是一个XML文件,根节点是Project节点,可以包括若干个ItemGroup节点和Target节点。ItemGroup节点是一个容器,用来包括若干个项元素。例如这里就包括了一个项元素Compile,,包括了helloworld.cs文件。这里还可以使用通配符。

<Compile Include="*.cs" />

Target元素是项目构建的目标,每个文件可以有多个Target,执行不同的任务。这里,名为Build的Target就包括了Csc任务来编译一个文件,使用Source属性来指定要编译的文件。另外还有一些任务,会在下面说明。

这里还有一种语法@(Compile),这里会引用上面定义的项。在这里就是引用上面定义的helloworld.cs文件。如果定义了多个项,Target在执行的时候会以类似foreach的形式迭代执行每一个项。

有了项目文件,就可以使用MSBuild来执行项目的生成了,/t表示执行名为Build的Target。

msbuild helloworld.csproj /t:Build

查看一下是否生成了helloworld.exe,然后将其删除,准备下一步。

添加构建属性

在Project开始标签之后添加一个属性组节点:

<PropertyGroup><AssemblyName>MSBuildSample</AssemblyName><OutputPath>Bin\</OutputPath>
</PropertyGroup>

每个项目文件可以包括若干个PropertyGroup节点,其中可以包括若干个属性节点,每一个节点定义一个属性,可以在项目文件中引用。这里就包括了AssemblyName和OutputPath两个属性。之后就可以通过$(属性名)的语法来使用了。

在Csc节点前插入一个节点:

<MakeDir Directories="$(OutputPath)"      Condition="!Exists('$(OutputPath)')" />

然后再Csc节点中增加一个OutputAssembly属性:

<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />

这里增加了一个创建文件夹的任务,创建的文件夹名字由上面的属性组定义。几乎每个任务都可以添加一个Condition属性,指定什么条件下执行该任务。这里是在输出目录不存在的情况下才执行该任务,创建目录。除此之外,还有其他很多任务,例如复制文件、删除文件等等,详细情况可以查看MSBuild任务参考。另外还有一个名字叫做MSBuild Community Tasks的开源项目,包含了其他一些任务,如果有需求的可以参考一下。

另外微软建议我们在定义目录属性的时候,最好将目录后面的反斜杠\定义到属性中,而不是加在引用之后。例如上面的就比下面的更好:

<OutputPath>Bin\</OutputPath>
OutputAssembly=="$(OutputPath)$(AssemblyName).exe" />
<OutputPath>Bin</OutputPath>
OutputAssembly=="$(OutputPath)\$(AssemblyName).exe" />

现在项目文件应该类似这样:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><PropertyGroup><AssemblyName>MSBuildSample</AssemblyName><OutputPath>Bin\</OutputPath></PropertyGroup><ItemGroup><Compile Include="helloworld.cs" /></ItemGroup><Target Name="Build"><MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" /><Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" /></Target>
</Project>

再次运行一下构建命令,查看一下程序出否在输出目录中生成。

msbuild helloworld.csproj /t:Build

增加构建目标

在构建过程中可以指定多个构建目标,可以指定一个目标调用其他目标,还可以指定默认的构建目标。

在Build目标之后添加两个新目标:

<Target Name="Clean" ><Delete Files="$(OutputPath)$(AssemblyName).exe" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />

这两个构建目标很简单,Clean目标会删除生成的exe文件。Rebuild目标会运行Clean和Build两个目标。

在Project节点中添加一个新属性DefaultTarget,就可以指定一个默认目标。如果运行MSBuild命令的时候没有使用/t指定Target,就会自动执行默认的目标。

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

运行一下msbuild helloworld.csproj /p:AssemblyName=Greetings,测试一下。这里通过/p参数传入指定的参数名,这会覆盖项目文件中指定的文件名。如果不指定参数名的话就会使用在项目中已经定义的参数。然后运行msbuild helloworld.csproj /t:clean /p:AssemblyName=Greetings**/p:AssemblyName=Greetings,删除已经生成的文件。

增量构建

在名为Build的Target中添加如下属性:

Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe"

Inputs属性指定该目标依赖的输入文件,在这里由上面的Compile项所定义。Outputs指定项目的输出文件。指定这两个属性之后,MSBuild就会在运行此目标的时候检查输入和输出文件。如果输入文件相对于输出文件都是最新的,那么MSBuild就会跳过构建过程。如果有部分文件已经修改,MSBuild就会只对这部分文件运行构建目标。

概念总结

MSBuild依据csproj项目文件来进行构建。csproj文件中可以有多种节点。

ItemGroup节点是项目组,可以有多个子节点, 用来包含要处理的一个或多个文件。每个子节点都必须有Include属性指定要包含什么文件,还有一个可选的Exclude节点指定排除什么文件。定义ItemGroup之后,就可以利用@(节点名)来引用Item了。

PropertyGroup节点是属性组,可以有多个节点,用来包含项目构建过程中使用到的属性。定义了属性之后,可以使用$(属性名)语法来访问。

Target是构建目标,是MSBuild的执行目标,每个Target下面可以包含多个任务,还可以引用其他的Target构成一个执行链。微软和C#社区定义了很多任务,可以分别在其MSBuild任务参考和MSBuild Community Tasks中找到。

最后,我在Github上新建了一个项目MSBuildExample,演练了一下上面的概念。这个项目添加了一个AfterBuild目标,在Release状态下构建成功之后,将生成的可执行文件重命名成自定义名称,然后和第三方库以及一个配置文件打包生成zip压缩包。有兴趣的同学可以看一下。

从零开始构建MSBuild C#项目文件相关推荐

  1. Unity从零开始构建能力体系 Unity Ability System

    从零开始构建能力体系 你会学到什么 如何实施能力体系 如何使用用户界面工具包创建用户界面 如何使用Unity的GraphView API 如何实现保存系统 MP4 |视频:h264,1280×720 ...

  2. 万字干货:如何从零开始构建企业级推荐系统?

    「免费学习 60+ 节公开课:投票页面,点击讲师头像」 作者丨gongyouliu 编辑丨zandy 来源 | 大数据与人工智能(ID: ai-big-data) 最近几个月有很多人咨询作者怎么从零开 ...

  3. 从零开始构建一个的asp.net Core 项目(一)

    最近突发奇想,想从零开始构建一个Core的MVC项目,于是开始了构建过程. 首先我们添加一个空的CORE下的MVC项目,创建完成之后我们运行一下(Ctrl +F5).我们会在页面上看到"He ...

  4. 使用PyTorch从零开始构建Elman循环神经网络

    摘要: 循环神经网络是如何工作的?如何构建一个Elman循环神经网络?在这里,教你手把手创建一个Elman循环神经网络进行简单的序列预测. 本文以最简单的RNNs模型为例:Elman循环神经网络,讲述 ...

  5. 从零开始构建自己的爬虫代理IP数据库并定期检验IP有效性...

    ProxyIPPool 从零开始构建自己的代理IP池:根据代理IP网址抓取新的代理IP:对历史代理IP有效性验证 源码地址:https://github.com/TOMO-CAT/ProxyIPPoo ...

  6. 从零开始构建企业级推荐系统

    作者丨gongyouliu 编辑丨zandy 这是作者的第26篇文章,约1.2w字,阅读需60分钟 最近几个月有很多人咨询作者怎么从零开始搭建工业级推荐系统,有做音视频的.有做新闻资讯的.有做在线教育 ...

  7. 从零开始构建一个高可靠的RabbitMQ镜像集群

    从零开始构建一个高可靠的RabbitMQ镜像集群 1.集群环境节点规划如表所示: 1 集群构建 1.停止MQ服务,首先停止3个节点的服务的命令如下: service rabbitmq-server s ...

  8. 为什么谷歌会从零开始构建一个全新的操作系统?

    腾讯科技编者按 <快公司>网站日前发表文章,对谷歌开发一个全新操作系统的原因进行了分析,解释了现有操作系统存在的问题,并对谷歌此举的动机进行了推测,以下为原文: 上周,谷歌一个团队做了一件 ...

  9. 计算机系统要素高清pdf,计算机系统要素:从零开始构建现代计算机[PDF][43.21MB]...

    内容简介 本书通过展现简单但功能强大的计算机系统之构建过程,为读者呈现了一幅完整.严格的计算机应用科学大图景.本书作者认为,理解计算机工作原理的最好方法就是亲自动手,从零开始构建计算机系统. 通过12 ...

  10. 计算机系统要素-从零开始构建现代计算机-答案

    答案 github 地址 这本书主要讲解了计算机原理(1-5章).编译原理(6-11章).操作系统相关知识(12章).不要看内容这么多,其实这本书的内容非常通俗易懂,翻译也很给力.每一章背后都有对应的 ...

最新文章

  1. Facebook 应用机器学习团队专访:人工智能在 Facebook 中的应用
  2. TeeChart替代品,MFC下好用的高速绘图控件-(Hight-Speed Charting)
  3. Android编译笔记二
  4. dockerfile mysql例子_简单的Dockerfile书写(实例!!!)
  5. php过去图片宽度,用php调整图片宽高
  6. 各种排序算法的时间复杂度
  7. 调车遇到的问题及解决办法
  8. 洛谷——P2613 【模板】有理数取余
  9. react-native修改android包名-上传应用市场
  10. Java工具类之Base64Utils实现base64码转换为文件流等互换
  11. 东汉十三州以及各个郡的说明
  12. Linux下载的详细教程
  13. 记录一下matlab画雷达图
  14. fifo的rdata_同步Fifo和异步fifo
  15. 如何获取Windows 10的锁屏壁纸
  16. html图片水平镜像翻转
  17. MybatisPlus相关
  18. 最快的排序算法是什么
  19. seo排名系统源码,矩阵系统源码,火剪系统源码
  20. 前端鸡汤奉上-好好解解腻

热门文章

  1. 浅谈计算机网络技术应用及发展,【网络技术论文】计算机网络技术的应用及发展(共2891字)...
  2. java datatable用法_C# DataTable用法示例详解|DataTable Select,sort排序,Linq过滤操作
  3. php 监听模式,总结Laravel事件系统用法(监听事件,观察者模式)
  4. 前牙正常覆盖是多少_深覆合千万不要矫正?用图示告诉你深覆合深覆盖的区别是什么,有什么危害...
  5. proteus三输入与非门名字_商标取名大全-有创意的2020商标名字大全
  6. 前端面试instanceof_【面试准备】每日前端面试题 45 (前端校招字节跳动面试4)...
  7. python3 django 中文乱码_python3 wsgi服务和响应数据中文乱码问题
  8. Angular 2 组件之间如何通信
  9. glEnable(GL_DEPTH_TEST)作用
  10. Activity与Service通信(不同进程之间)