1. 程式人生 > >MSBuild的簡單介紹與使用

MSBuild的簡單介紹與使用

MSBuild 是 Microsoft 和 Visual Studio的生成系統。它不僅僅是一個構造工具,應該稱之為擁有相當強大擴充套件能力的自動化平臺。MSBuild平臺的主要涉及到三部分:執行引擎、構造工程、任務。其中最核心的就是執行引擎,它包括定義構造工程的規範,解釋構造工程,執行“構造動作”;構造工程是用來描述構造任務的,大多數情況下我們使用MSBuild就是遵循規範,編寫一個構造工程;MSBuild引擎執行的每一個“構造動作”就是通過任務實現的,任務就是MSBuild的擴充套件機制,通過編寫新的任務就能夠不斷擴充MSBuild的執行能力。所以這三部分分別代表了引擎、指令碼和擴充套件能力。

構造工程(指令碼檔案)
先說說構造工程,只要通過Notepad開啟任何一個Visual Studio下的C#工程(csproj)檔案,就知道構造工程到底是怎麼回事了。

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Root>$(MSBuildStartupDirectory)</Root>
  </PropertyGroup>
<Target Name="Build"> <!-- Compile --> <ItemGroup> <ProjectToBuild Include="$(Root)\..\src\Foundation\Common\Gimela.Common.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Infrastructure\Gimela.Infrastructure.sln" /> <ProjectToBuild
Include="$(Root)\..\src\Foundation\Management\Gimela.Management.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Security\Gimela.Security.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Tasks\Gimela.Tasks.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Text\Gimela.Text.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Net\Gimela.Net.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\ServiceModel\Gimela.ServiceModel.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Data\Gimela.Data.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Presentation\Gimela.Presentation.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Media\Gimela.Media.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Streaming\Gimela.Streaming.sln" /> <ProjectToBuild Include="$(Root)\..\src\Crust\Gimela.Crust.sln" /> </ItemGroup> <MSBuild Projects="@(ProjectToBuild)" Targets="Build" Properties="Configuration=Debug;"> <Output TaskParameter="TargetOutputs" ItemName="AssembliesBuiltByChildProjects" /> </MSBuild> </Target> </Project>

在構造工程中我們可以定義和使用變數(通過Property/PropertyGourp/Item/ItemGroup等元素),可以使用條件分支(通過Choose/When/Otherwise等元素)、能夠在執行時給變數賦值(通過執行任務,獲取其返回型別引數的方式)、能夠定義執行塊(通過Target元素,相當於函式)、能夠進行異常處理(通過OnError元素)、還可以複用已有工程定義的內容(通過Import元素)。擁有這些能力和高階語言已經相差無幾了,所以筆者認為構造工程不是描述性語言,而是指令碼語言。

這裡還需要強調一點的是,專案級元素(Property)可以在元素下定義,也可以在構造過程中作為外部引數傳入,這是一個非常有用的特性,一般編譯時選擇配置項(Debug或者Release)就是利用這個特性實現的。

Project元素
這是每一個專案檔案的最外層元素,它表示了一個專案的範圍。如果缺少了這一元素,MSBuild會報錯稱Target元素無法識別或不被支援。
Project元素擁有多個屬性,其中最常用到的是DefaultTargets屬性。我們都知道,在一個專案的生成過程中可能需要完成幾項不同的任務(比如編譯、單元測試、check-in到原始碼控制伺服器中等),其中每一項任務都可以用Target來表示。對於擁有多個Target的專案,你可以通過設定Project的DefaultTargets(注意是複數)屬性來指定需要執行哪(幾)個Target,如果沒有這個設定,MSBuild將只執行排在最前面的那個Target。

Property元素

在專案中你肯定需要經常訪問一些資訊,例如需要建立的路徑名、最終生成的程式集名稱等。以name/value的形式新增進Property,隨後就可以以$(PropertyName)的形式訪問。這樣你就無須為了改動一個檔名稱而讓整個專案檔案傷筋動骨了。比如上面程式碼中的Bin就是將要建立的路徑名稱,而AssemblyName則是最終要生成的程式集名稱。這些屬性的名稱不是固定的,你完全可以按自己的習慣來進行命名。在使用時,你需要把屬性名稱放在”$(“和”)”對內(不包括引號),以表示這裡將被替換成一個Property元素的值。
另外,如果Property元素數量比較多,你還可以把它們分門別類地放在不同的PropertyGroup裡,以提高程式碼的可閱讀性。這對Property本身沒有任何影響。

 <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{6C2561FB-4405-408F-B41B-ACE5E519A26E}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Gimela.Infrastructure.Patterns</RootNamespace>
    <AssemblyName>Gimela.Infrastructure.Patterns</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>

Item元素
在整個專案檔案中你肯定要提供一些可被引用的輸入性資源(inputs)資訊,比如原始碼檔案、引用的程式集名稱、需要嵌入的圖示資源等。它們應該被放在Item裡,以便隨時引用。語法是:<Item Type=”TheType”Include=”NameOrPath” />

其中Type屬性可以被看作是資源的類別名稱,比如對於.cs原始檔,你可以把它們的Type都設定為Source,對於引用的程式集把Type都設定為Reference,這樣在隨後想引用這一類別的資源時只要引用這個Type就可以了,方法是@(TypeName)。可千萬別和Property的引用方法弄混了。
既然Type是資源的類名,那麼Include就是具體的資源名稱了,比如在上面的示例程式碼中,Include引用的就是C#原始碼檔案的名稱。你也可以用使用萬用字元*來擴大引用範圍。比如下面這行程式碼就指定了當前目錄下的所有C#檔案都可以通過@(Source)來引用:

<Item Type=”Source” Include=”*.cs” />

另外,你也可以通過與PropertyGroup類似的方法把相關的Item放在ItemGroup裡。

  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Data" />
    <Reference Include="System.ServiceModel" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Commands\CommandBase.cs" />
    <Compile Include="Commands\DuplexCommandBase.cs" />
    <Compile Include="Commands\ICommand.cs" />
    <Compile Include="Commands\IDuplexCommand.cs" />
    <Compile Include="Extensions\BitConverterExtensions.cs" />
    <Compile Include="Extensions\ConcurrentDictionaryExtensions.cs" />
    <Compile Include="Extensions\StopwatchExtensions.cs" />
    <Compile Include="Extensions\TimeSpanExtensions.cs" />
    <Compile Include="Flyweight\FlyweightObjectPool.cs" />
    <Compile Include="Singleton\StaticSingleton.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="SmartQueue\ISmartQueueMapper.cs" />
    <Compile Include="SmartQueue\SmartQueue.cs" />
    <Compile Include="SmartQueue\SmartQueueBase.cs" />
    <Compile Include="SmartQueue\SmartQueueMapper.cs" />
    <Compile Include="UnitOfWork\IUnitOfWork.cs" />
    <Compile Include="UnitOfWork\IUnitOfWorkFactory.cs" />
    <Compile Include="UnitOfWork\UnitOfWork.cs" />
    <Compile Include="WeakActions\IWeakActionExecuteWithObject.cs" />
    <Compile Include="WeakActions\WeakAction.cs" />
    <Compile Include="WeakActions\WeakActionGeneric.cs" />
    <Compile Include="WeakFuncs\IWeakFuncExecuteWithObjectAndResult.cs" />
    <Compile Include="WeakFuncs\WeakFunc.cs" />
    <Compile Include="WeakFuncs\WeakFuncGeneric.cs" />
  </ItemGroup>

Target元素
Target表示一個需要完成的虛擬的任務單元。每個Project可以包括一個或多個Target,從而完成一系列定製的任務。你需要給每個Target設定一個Name屬性(同一Project下的兩個Target不能擁有同樣的Name)以便引用和區別。

舉例來說,在你的專案生成過程中可能需要完成三個階段的任務:首先check-out原始碼,接下來編譯這些程式碼並執行單元測試,最後把它們check-in。那麼通常情況下你可以建立三個不同的Target以清晰劃分三個不同的階段:

<Target Name=”CheckOut” ></Target>

<Target Name=”Build”  DependsOnTargets=”CheckOut”> <Task Name=”Build”

.../> <Task Name=”UnitTest” ... />

</Target>

<Target Name=”CheckIn” DependsOnTargets=”CheckOut;Build”> 

</Target>

這樣,你就可以非常清晰地控制整個生成過程。為了反應不同Target之間的依賴關係(只有Check-in後才能編譯,只有編譯完成才可能Check-out……),你需要設定Target的DependsOnTargets屬性(注意是複數),以表示僅當這些Target執行完成之後才能執行當前的Target。當MSBuild引擎開始執行某項Target時(別忘了Project的DefaultTargets屬性),會自動檢測它所依賴的那些Target是否已經執行完成,從而避免因為某個生成環節缺失而導致整個生成過程發生意外。
你可以通過Project的DefaultTargets屬性指定MSBuild引擎從哪(幾)個Target開始執行,也可以在呼叫MSBuild.exe時使用t開關來手動指定將要執行的Target,方法如下:
MSBuild /t:CheckOut 這樣,只有CheckOut(以及它所依賴的Target,在上文中沒有)會被執行。

Task元素
這可能是整個專案檔案中最重要的,因為它才是真正可執行的部分(這也是為什麼我在上面說Target是虛擬的)。你可以在Target下面放置多個Task來順序地執行相應的任務。


相關推薦

MSBuild簡單介紹使用

MSBuild 是 Microsoft 和 Visual Studio的生成系統。它不僅僅是一個構造工具,應該稱之為擁有相當強大擴充套件能力的自動化平臺。MSBuild平臺的主要涉及到三部分:執行引擎、構造工程、任務。其中最核心的就是執行引擎,它包括定義構造工程的規範,解釋

內核調試神器SystemTap — 簡單介紹使用(一)

kprobe utils its preview response art sym about output a linux trace/probe tool. 官網:https://sourceware.org/systemtap/ 簡單介紹 S

WebService的簡單介紹入門使用

編程 子集 amp 分布 使用 互操作 開發 配置 ebs WebService是一個平臺獨立的,低耦合的,自包含的、基於可編程的web的應用程序,可使用開放的XML(標準通用標記語言下的一個子集)標準來描述、發布、發現、協調和配置這些應用程序,用於開發分布式的互操作的應用

Apache shiro的簡單介紹使用(spring整合使用)

簡單介紹 ace .cn album spring 整合 amp 介紹 pri http://pic.cnhubei.com/space.php?uid=1774&do=album&id=1343605http://pic.cnhubei.com/space

shell腳本基礎的簡單介紹簡單應用

shell 變量 基礎 Shell腳本是Linux中很重要的一種“程序”。什麽shell腳本?shell腳本是提前設計的可執行語句,用來完成特定任務的文件。Shell腳本可分為交互式和非交互式交互式:指腳本在運行時,需要一些人為的參與,比如,鍵盤輸入數據,確認選項等。因為有人為的參與,所以運行時更加智能化,但

圖像處理 - ImageMagick 簡單介紹案例

ans per function 博客 解析 滿足 文本水印 ast 坐標系統 在客戶端我們可以用 PhotoShop 等 GUI 工具處理靜態圖片或者動態 GIF 圖片,不過在服務器端對於 WEB 應用程序要處理圖片格式轉換,縮放裁剪,翻轉扭曲,PDF解析等操作, G

cassandra簡單介紹基本操作

一、使用場景:   是一款分散式的結構化資料儲存方案(NoSql資料庫),儲存結構比Key-Value資料庫(像Redis)更豐富,但是比Document資料庫(如Mongodb)支援度有限;適合做資料分析或資料倉庫這類需要迅速查詢且資料量大的應用   相關概念:   &n

Kafka的簡單介紹使用,生產者和消費者的JavaApi

一、簡介 2、實時流資料管道,可以在 3、構建流式引用 4、是一個分散式流式處理平臺, 統稱訊息佇列或訊息中介軟體,有生產者和消費者之分 消費者去kafka中拉資料(而不是kafka給資料) 其實kafka就是一個臨時儲存的外掛,但是這個外掛效能很強大 kafka 是用scala編譯的 0.

KVM簡單介紹管理

簡介 KVM(Kernel-basedVirtual Machine,基於核心的虛擬機器)是適用於包含虛擬化擴充套件(Intel VT或AMD-V)的x86硬體上的Linux的完全虛擬化解決方案。它由可載入的核心模組kvm.ko組成,它提供核心虛擬化基礎架構和處理器特定模組,kvm-in

Django簡單介紹環境搭建

Django:MVC(model:主要封裝對資料庫層的訪問,對資料庫中的資料進行增刪改查操作。view:用於封裝結果,生成頁面展示的html內容。controller:用於接受請求請求,處理業務邏輯,與Model和View互動,返回結果)核心思想:解耦,讓不同的程式碼塊之間降低耦合,增強程式

Fork/Join框架簡單介紹使用

為了偷個懶,我就直接將我自己寫程式的註釋拿過來貼上去了。 /**  * @author   * Fork/join框架是Java7提供的一個用於並行任務執行的框架,將一個大任務分解為若干個小任務,再彙總每個小任務  * 通常我們使用fork/join框架,需先建立一個任務,

KVM簡單介紹基本使用

簡介 KVM(Kernel-basedVirtual Machine,基於核心的虛擬機器)是適用於包含虛擬化擴充套件(Intel VT或AMD-V)的x86硬體上的Linux的完全虛擬化解決方案。它由可載入的核心模組kvm.ko組成,它提供核心虛擬化基礎架構和處

Hbase簡單介紹安裝

  需要對大資料進行隨機,實時讀寫訪問時,請使用Apache Hbase。該專案的目標是託管非常大的表。 開源的,分散式的,版本化的非關係資料庫,模仿google的Bigtable. Just as Bigtable leverages the distributed data sto

JavaBean簡單介紹使用(例項:JSP+JavaBean註冊驗證)

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getSchem

iOS中runtime(執行時)的簡單介紹應用

最近學習到runtime這一塊知識了所以就總結一下,以備以後要用。但是由於runtime這一塊的知識比較多所以今天在這裡只是做一個簡單的總結。 一、什麼是Runtime? Objective-C runtime是一個實現Objective-C語言的

Jmeter簡單介紹搭配Jenkins實現自動化測試實踐

Bioneck 豈安科技研發工程師 負責 Stalker 專案的部分研發與測試工作,程式設計愛好者,樂於使用程式碼解決生活中的重複工作。 最近有個需要依靠 Jmeter+Jenkins 實現自動化測試後部署的需求,於是看了看Jmeter的資

LaTeX宏包說明文檔的簡單介紹下載地址

ofo 原本 xelatex 沒有 尺寸 book code 中文版 標題 LaTeX的宏包(或宏集)很多,我把曾經用到的宏包說明文檔上傳到網上供大家下載使用。原本打算放到51CTO裏面,但是在上傳有些文件時提示已經有人上傳了,但是去查找時又沒有,不清楚怎麽回事,所以就都放

socket 簡單介紹例子

java提供四種類型的網路通訊: 1、InelAddress:用於標識網路上的硬體資源,表示網際網路協議地址(IP); 2、URL:統一資源定位符  通過URL可以直接讀取或寫入網路上的資料; 3、Sockets:使用TCP協議實現網路通訊的Socket相關的類(客戶端的S

MyBatis逆向工程——MyBatis Generator (MBG)-簡單介紹執行步驟(1)

寫在前面: Mybatis Generator是MyBatis和ibatis的程式碼生成器。主要生成如下:        (1)與表結構匹配的Java POJO(欄位名對應屬性)        (2)SQL對映XML檔案(檔案為配置中每個表上的簡單CRUD(增刪改查)函式生成

LXC簡單介紹使用

簡介 LXC(LinuX Containers)Linux容器,一種作業系統層虛擬化技術,為Linux核心容器功能的一個使用者空間介面。它將應用軟體系統打包成一個軟體容器(Container),內含應用軟體本身的程式碼,以及所需要的作業系統核心和庫。透過統一的名字空間和共享API來分配不