揭开Visual Studio编译的神秘面纱:MSBuild

时间:2021-07-13 03:33:51

我们平时写完程序以后,在Visual Studio中右击build,我们的程序就编译完了。那么点击build之后到底发生了什么事情?如果没有Visual Studio我们该如何进行编译?这就是MSBuild提供的功能,下面将以一些例子来一步步的说明它的用法。

场景:

有一个.cs文件,想用MSBuild将它编译成一个exe文件.

using System;

 

namespace MyApp

{

class Program

{

static void Main(string[] args)

{

}

}

}

 

实施:

1.创建Project文件:

用任何的文本编辑器创建一个.proj文件(在这个例子中是MyApp.proj), 在文件里加入如下的内容:

<Project DefaultTargets="Compile"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

</Project>

这是一个根节点,后面的步骤中,将在它的下面添加一些子节点。

2.添加项目属性。

一个项目有很多属性,比如项目名称。现在就为这个项目添加一个名称:

<Project DefaultTargets="Compile"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>

<appname>MyApp</appname>

</PropertyGroup>

</Project>

从上面的代码可以看到,属性都放在PropertyGroup节点中。

appname这个属性其实类似于一个变量,在文件的其他的地方可以通过@(appname)来引用它。

所以放在PropertyGroup里面的节点都相当于一些全局变量,以供在文件的其他地方使用。

3.添加Item.

下面将要编译的文件添加到配置里面去:

<Project DefaultTargets = "Compile"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >

 

<!-- Set the application name as a property -->

<PropertyGroup>

<appname>MyApp</appname>

</PropertyGroup>

 

<ItemGroup>

<CSFile Include = "MyClass.cs"/>

</ItemGroup>

</Project>

可以看到,Item放在ItemGroup节点里。CSFile也类似于一个变量,在文件的其他的地方可以通过@(CSFile)来引用它。

4.添加Target.

Target指的是要编译任务的集合,是Task的容器。

<Project DefaultTargets = "Compile"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >

 

<!-- Set the application name as a property -->

<PropertyGroup>

<appname>HelloWorldCS</appname>

</PropertyGroup>

 

<ItemGroup>

<CSFile Include = "MyClass.cs"/>

</ItemGroup>

 

<Target Name="Compile"></Target>

</Project>

 

5.添加Task.

Task是Target的子节点,用来定义一个个具体的编译任务。

<Project DefaultTargets = "Compile"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >

 

<!-- Set the application name as a property -->

<PropertyGroup>

<appname>HelloWorldCS</appname>

</PropertyGroup>

 

<ItemGroup>

<CSFile Include = "MyClass.cs"/>

</ItemGroup>

 

<Target Name="Compile">

<CSC Sources = "@(CSFile)"></CSC>

</Target>

</Project>

 

上面的代码中,CSC是MSBuild保留字,它会调用csc.exe来进行编译。

@()里面用来放Item的集合名字。在这里放的是第3步中定义的CSFile项。如果在当前Target中有多个CSFile节点,都会被这个CSC 任务处理。

6.添加Task output

Task output指的是一个具体任务的输出设置。

<Project DefaultTargets = "Compile"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >

 

<!-- Set the application name as a property -->

<PropertyGroup>

<appname>HelloWorldCS</appname>

</PropertyGroup>

 

<ItemGroup>

<CSFile Include = "MyClass.cs"/>

</ItemGroup>

 

<Target Name="Compile">

<CSC Sources = "@(CSFile)"

OutputAssembly = "$(appname).exe">

<Output TaskParameter="OutputAssembly"

ItemName="MyClass"/>

</CSC>

</Target>

</Project>

上面代码中的TaskParameter指定了输出的文件名称,它用的是CSC节点中定义的OutputAssembly属性的值。
ItemName指定这个Item的名字,在其他地方可以通过@()语法引用这个Item.

7. 添加消息

如果希望在编译的过程中,输出一些消息来指示编译的进度。可以对一个Target添加Message.

<Project DefaultTargets = "Compile"

xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >

 

<!-- Set the application name as a property -->

<PropertyGroup>

<appname>MyApp</appname>

</PropertyGroup>

 

<ItemGroup>

<CSFile Include = "MyClass.cs"/>

</ItemGroup>

 

<Target Name="Compile">

<CSC Sources = "@(CSFile)"

OutputAssembly = "$(appname).exe">

<Output TaskParameter="OutputAssembly"

ItemName="MyClass"/>

</CSC>

<Message Text="The output file is @(MyClass)"/>

</Target>

</Project>

可以看到,这段代码引用了第6步中设置的ItemName

 

执行:

  1. 将MyApp.proj和MyClass.cs放在一个目录中。

揭开Visual Studio编译的神秘面纱:MSBuild

  1. 打开命令行,执行MSBuild(" C:\Windows\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe" MyApp.proj),执行结果如下:
  2. 揭开Visual Studio编译的神秘面纱:MSBuild

     

    揭开Visual Studio编译的神秘面纱:MSBuild