共用方式為


從頭開始建立 MSBuild 項目檔

以 .NET Framework 為目標的程式設計語言會使用 MSBuild 專案檔來描述和控制應用程式建置程式。 當您使用 Visual Studio 建立 MSBuild 項目檔時,會自動將適當的 XML 新增至檔案。 不過,您可能會發現瞭解 XML 的結構,以及如何變更它的方法來管理組建過程會很有説明。

注意

如果您想要瞭解 MSBuild 與任何 SDK 獨立運作的基本概念,本文是適當的。 本文未涵蓋使用 SDK 建置,例如當您使用 dotnet build 或將 Sdk 屬性新增至根專案元素時。 請參閱 .NET 專案 SDK

標準 .csproj 檔案匯入的建置邏輯支援比此範例更多的選項和更複雜的建置程式。

如需為C++專案建立專案檔的相關信息,請參閱 MSBuild (C++)

本教學課程示範如何使用文本編輯器,以累加方式建立基本項目檔。 本逐步解說會遵循下列步驟:

  1. 擴充PATH環境變數。

  2. 建立最少的應用程式原始程序檔。

  3. 建立最小的 MSBuild 項目檔。

  4. 使用項目檔建置應用程式。

  5. 新增屬性以控制組建。

  6. 藉由變更屬性值來控制組建。

  7. 將目標新增至建置。

  8. 藉由指定目標來控制組建。

  9. 以累加方式建置。

本教學課程示範如何在命令提示字元建置專案,並檢查結果。 如需了解有關 MSBuild 以及如何在命令列中執行 MSBuild 的詳細資訊,請參閱 使用 MSBuild

若要完成本教學課程,您必須安裝Visual Studio,因為它包含 MSBuild 和 C# 編譯程式,這是逐步解說的必要專案。

延伸路徑

您必須先擴充PATH環境變數,才能使用 MSBuild,以包含所有必要的工具。

如果您在 Windows 上執行,您可以使用適用於 Visual Studio 的 開發人員命令提示字元。 在 Windows 任務欄的 Windows 搜尋方塊中搜尋它。 若要在一般命令提示字元或腳本環境中設定環境,請在Visual Studio安裝的 Common7/Tools 子資料夾中執行 VSDevCmd.bat

建立最小應用程式

本節說明如何使用文字編輯器建立最少的 C# 應用程式原始程序檔。

  1. 在命令提示字元中,流覽至您要建立應用程式的資料夾,例如,\My Documents\\Desktop\

  2. 建立名為 \HelloWorld\ 的子資料夾,並將目錄變更為移至其中。

  3. 在文字編輯器中,建立新的檔案 HelloWorld.cs,然後複製並貼上下列程序代碼:

    using System;
    
    class HelloWorld
    {
        static void Main()
        {
    #if DebugConfig
            Console.WriteLine("WE ARE IN THE DEBUG CONFIGURATION");
    #endif
    
            Console.WriteLine("Hello, world!");
        }
    }
    
  4. 在命令提示字元中輸入 csc helloworld.cs,以建置應用程式。

  5. 在命令提示字元中輸入 helloworld,以測試應用程式。

    Hello, world! 訊息應該顯示。

  6. 刪除可執行檔。

建立最小 MSBuild 項目檔

既然您擁有最少的應用程式原始程序檔,您可以建立最少的項目檔來建置應用程式。 此項目檔包含下列元素:

  • 必要的根節點 Project

  • 要用來包含項目元素的 ItemGroup 節點。

  • 參考應用程式原始檔案的項目元素。

  • 包含建置應用程式所需工作的 Target 節點。

  • 用以啟動 C# 編譯器以建置應用程式的 Task 元素。

建立最小 MSBuild 項目檔

  1. 在文本編輯器中,HelloWorld.fromscratchproj 建立新的檔案,然後輸入下列程式代碼:

    <Project>
      <ItemGroup>
        <Compile Include="helloworld.cs" />
      </ItemGroup>
    </Project>
    

    ItemGroup 包含項目 Compile,並將一個來源檔案指定為項目。

  2. Target 節點新增為 Project 節點的子專案。 將節點命名為 Build

    <Target Name="Build">
    </Target>
    
  3. 將此工作專案插入為 Target 節點的子專案:

    <Csc Sources="@(Compile)"/>
    
  4. 儲存此項目檔,並將其命名 Helloworld.fromscratchproj

您的最小項目檔應該類似下列程式代碼:

<Project>
  <ItemGroup>
    <Compile Include="helloworld.cs"/>
  </ItemGroup>
  <Target Name="Build">
    <Csc Sources="@(Compile)"/>
  </Target>
</Project>

建置目標中的工作會循序執行。 在此情況下,C# 編譯程式 Csc 工作是唯一的工作。 它需要一份要編譯的來源檔案清單,這清單由 Compile 項目的值來決定。 Compile 項目只會參考一個原始程式檔,Helloworld.cs

注意

在 item 元素中,您可以使用星號 (*) 通配符來引用所有具有 .cs 檔案擴展名的文件,如下所示:

<Compile Include="*.cs" />

建置應用程式

現在,若要建置應用程式,請使用您剛才建立的項目檔。

  1. 在命令提示字元中,輸入 msbuild helloworld.fromscratchproj -t:Build

    此動作會通過叫用 C# 編譯器來建置 Helloworld 應用程式,從而達到 Helloworld 專案檔案的建置目標。

  2. 輸入 helloworld 來測試應用程式。

    Hello, world! 訊息應該會顯示。

注意

您可以通過增加詳盡程度來查看建構的更多細節。 若要將詳述層級設定為「detailed」,請在命令列中輸入此命令:

msbuild helloworld.fromscratchproj -t:Build -verbosity:detailed

新增組建屬性

您可以將組建屬性新增至項目檔,以進一步控制組建。 現在新增這些屬性:

  • 指定應用程式名稱的 AssemblyName 屬性。

  • 指定要包含應用程式之資料夾的 OutputPath 屬性。

若要新增組建屬性

  1. 刪除現有的應用程式可執行檔案(稍後,您將新增 Clean 目標來處理舊輸出檔案的刪除。

  2. 在專案檔中,將這個 PropertyGroup 元素插入 Project 元素開頭之後:

    <PropertyGroup>
      <AssemblyName>MSBuildSample</AssemblyName>
      <OutputPath>Bin\</OutputPath>
    </PropertyGroup>
    
  3. 請在 Csc 工作之前,將此工作新增至建置目標:

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

    MakeDir 任務會建立一個以 OutputPath 屬性命名的資料夾,前提是目前沒有已存在的同名資料夾。

  4. 將此 OutputAssembly 屬性新增至 Csc 工作:

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

    這會指示 C# 編譯程式產生由 AssemblyName 屬性命名的元件,並將它放在 OutputPath 屬性所命名的資料夾中。

  5. 儲存您的變更。

您的項目檔現在應該類似下列程式代碼:

<Project>
  <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>

注意

建議您在資料夾名稱結尾新增反斜杠 (\) 路徑分隔符,當您在 OutputPath 元素中指定它,而不是在 Csc 工作的 OutputAssembly 屬性中新增它。 因此

<OutputPath>Bin\</OutputPath>

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

比...更好

<OutputPath>Bin</OutputPath>

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

測試組建屬性

現在您可以使用使用建置屬性來指定輸出資料夾和應用程式名稱的項目檔來建置應用程式。

  1. 在命令提示字元中,輸入 msbuild helloworld.fromscratchproj -t:Build

    這會建立 \Bin\ 資料夾,然後叫用 C# 編譯程式來建立 MSBuildSample 應用程式,並將它放入 \Bin\ 資料夾中。

  2. 若要確認 \Bin\ 資料夾已建立,而且它包含 MSBuildSample 應用程式,請輸入 dir Bin

  3. 輸入 Bin\MSBuildSample 來執行可執行檔,以測試應用程式。

    Hello, world!應該會顯示 訊息。

新增組建目標

接下來,將兩個目標新增至項目檔,如下所示:

  • 刪除舊檔案的清除目標。

  • 強制在建置工作之前執行清除工作的使用 DependsOnTargets 屬性的重建目標。

現在您有多個目標,您可以將 [建置目標] 設定為預設目標。

若要新增組建目標

  1. 在項目檔中,在建置目標之後新增這兩個目標:

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

    Clean 目標會呼叫 Delete 任務來刪除應用程式。 在清除目標與建置目標都執行之前,重建目標不會執行。 雖然重建目標沒有任務,但它會使得清除目標在建置目標之前執行。

  2. 將此 DefaultTargets 屬性新增至開頭的 Project 元素:

    <Project DefaultTargets="Build">
    

    這會將建置目標設定為預設目標。

您的項目檔現在應該類似下列程式代碼:

<Project DefaultTargets="Build">
  <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>
  <Target Name="Clean" >
    <Delete Files="$(OutputPath)$(AssemblyName).exe" />
  </Target>
  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
</Project>

測試組建目標

您可以練習新的組建目標,以測試項目檔的這些功能:

  • 建置預設編譯版本。

  • 在命令提示字元中設定應用程式名稱。

  • 在建置另一個應用程式之前刪除應用程式。

  • 刪除應用程式而不建置另一個應用程式。

測試組建目標

  1. 在命令提示字元中,輸入 msbuild helloworld.fromscratchproj -p:AssemblyName=Greetings

    由於您未使用 -t 參數來明確設定目標,因此 MSBuild 會執行預設的建置目標。 -p 參數會覆寫 AssemblyName 屬性,並提供新的值,Greetings。 這會導致在 \Bin\ 資料夾中建立新的應用程式 Greetings.exe

  2. 若要確認 \Bin\ 資料夾同時包含 msBuildSample 應用程式和新的 Greetings 應用程式,請輸入 dir Bin

  3. 測試 Greetings 應用程式(例如,在 Windows 上輸入 Bin\Greetings)。

    Hello, world! 訊息應該會被顯示。

  4. 輸入 msbuild helloworld.fromscratchproj -t:clean,以刪除 MSBuildSample 應用程式。

    這會執行 Clean 工作,以移除具有預設 AssemblyName 屬性值的應用程式,MSBuildSample

  5. 輸入 msbuild helloworld.fromscratchproj -t:clean -p:AssemblyName=Greetings來刪除 Greetings 應用程式。

    這會執行 Clean 工作,以移除具有指定 AssemblyName 屬性值的應用程式,Greetings

  6. 若要確認 \Bin\ 資料夾現在是空的,請輸入 dir Bin

  7. 輸入 msbuild

    雖然未指定項目檔,但 MSBuild 會建置 helloworld.fromscratchproj 檔案,因為目前資料夾中只有一個項目檔。 這會導致 MSBuildSample 應用程式在 \Bin\ 資料夾中建立。

    若要確認 \Bin\ 資料夾包含 msBuildSample 應用程式,請輸入 dir Bin

以累加方式建置

只有當目標相依的來源檔案或目標檔案已變更時,您才能告訴 MSBuild 建置目標。 MSBuild 會使用檔案的時間戳來判斷檔案是否已變更。

以逐步方式建置

  1. 在項目檔中,將這些屬性新增至開啟的建置目標:

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

    這會指定建置目標取決於 Compile 專案群組中指定的輸入檔,以及輸出目標為應用程式檔。

    產生的組建目標應該類似下列程式代碼:

    <Target Name="Build" Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe">
      <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
      <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
    </Target>
    
  2. 在命令提示字元中輸入 msbuild -v:d,以測試建置目標。

    請記住,helloworld.fromscratchproj 是預設項目檔,而 Build 是預設目標。

    -v:d 參數是你先前使用的 -verbosity:detailed 的縮寫。

    如果您已經建置輸出,應該會顯示下列幾行:

    略過目標「建置」,因為所有輸出檔案都與輸入檔 up-to日期。

    MSBuild 會略過建置目標,因為自從上次建置應用程式之後,來源檔案都沒有變更。

C# 範例

下列範例顯示編譯 C# 應用程式的項目檔,並記錄包含輸出檔名稱的訊息。

程式碼

<Project DefaultTargets = "Compile">

    <!-- Set the application name as a property -->
    <PropertyGroup>
        <appname>HelloWorldCS</appname>
    </PropertyGroup>

    <!-- Specify the inputs by type and file name -->
    <ItemGroup>
        <CSFile Include = "*.cs"/>
    </ItemGroup>

    <Target Name="Compile">
        <!-- Run the C# compilation using input files of type CSFile -->
        <CSC
            Sources = "@(CSFile)"
            OutputAssembly = "$(appname).exe">
            <!-- Set the OutputAssembly attribute of the CSC task
            to the name of the executable file that is created -->
            <Output
                TaskParameter = "OutputAssembly"
                ItemName = "EXEFile" />
        </CSC>
        <!-- Log the file name of the output file -->
        <Message Text="The output file is @(EXEFile)"/>
    </Target>
</Project>

Visual Basic 範例

下列範例顯示編譯 Visual Basic 應用程式的項目檔,並記錄包含輸出檔名稱的訊息。

程式碼

<Project DefaultTargets = "Compile">

    <!-- Set the application name as a property -->
    <PropertyGroup>
        <appname>HelloWorldVB</appname>
    </PropertyGroup>

    <!-- Specify the inputs by type and file name -->
    <ItemGroup>
        <VBFile Include = "consolehwvb1.vb"/>
    </ItemGroup>

    <Target Name = "Compile">
        <!-- Run the Visual Basic compilation using input files of type VBFile -->
        <VBC
            Sources = "@(VBFile)"
            OutputAssembly= "$(appname).exe">
            <!-- Set the OutputAssembly attribute of the VBC task
            to the name of the executable file that is created -->
            <Output
                TaskParameter = "OutputAssembly"
                ItemName = "EXEFile" />
        </VBC>
        <!-- Log the file name of the output file -->
        <Message Text="The output file is @(EXEFile)"/>
    </Target>
</Project>

接下來會發生什麼?

Visual Studio 可以自動執行本逐步解說中顯示的大部分工作。 若要瞭解如何使用 Visual Studio 來建立、編輯、建置及測試 MSBuild 專案檔,請參閱 使用 MSBuild