Bagikan melalui


Cara MSBuild membangun proyek

Bagaimana MSBuild benar-benar bekerja? Dalam artikel ini, Anda akan mempelajari cara MSBuild memproses file proyek Anda, baik dipanggil dari Visual Studio, atau dari baris perintah atau skrip. Mengetahui cara kerja MSBuild dapat membantu Anda mendiagnosis masalah dengan lebih baik dan menyesuaikan proses build Anda dengan lebih baik. Artikel ini menjelaskan proses build dan sebagian besar berlaku untuk semua jenis proyek.

Proses build lengkap terdiri dari pemulaan, evaluasi , dan eksekusi target dan tugas yang membentuk proyek. Selain input ini, impor eksternal menentukan detail proses build, termasuk impor standar seperti Microsoft.Common.targets dan impor yang dapat dikonfigurasikan oleh pengguna di tingkat solusi atau proyek.

perusahaan rintisan

MSBuild dapat dipanggil dari Visual Studio melalui model objek MSBuild di Microsoft.Build.dll, atau dengan memanggil executable (MSBuild.exe atau dotnet build) langsung di baris perintah, atau dalam skrip, seperti dalam sistem CI. Dalam kedua kasus, input yang memengaruhi proses build mencakup file proyek (atau objek proyek internal ke Visual Studio), mungkin file solusi, variabel lingkungan, dan sakelar baris perintah atau model objeknya yang setara. Selama fase startup, opsi baris perintah atau setara model objek digunakan untuk mengonfigurasi pengaturan MSBuild seperti mengonfigurasi pencatat. Properti yang diatur pada garis perintah menggunakan sakelar -property atau -p diatur sebagai properti global, yang menggantikan nilai apa pun yang sudah diatur dalam file proyek, meskipun file proyek dibaca kemudian.

Bagian berikutnya adalah tentang file input, seperti file solusi atau file proyek.

Solusi dan proyek

Instans MSBuild dapat terdiri dari satu proyek, atau banyak proyek sebagai bagian dari solusi. File solusi bukan file XML MSBuild, tetapi MSBuild menafsirkannya untuk mengetahui semua proyek yang diperlukan untuk dibangun untuk konfigurasi dan pengaturan platform yang diberikan. Ketika MSBuild memproses input XML ini, prosesnya disebut sebagai build solusi. Ini memiliki beberapa titik yang dapat diperluas yang memungkinkan Anda menjalankan sesuatu di setiap build solusi, tetapi karena build ini adalah eksekusi terpisah dari build proyek individual, tidak ada pengaturan properti atau definisi target dari build solusi yang relevan dengan setiap build proyek.

Anda dapat mengetahui cara memperluas build solusi di Menyesuaikan build solusi.

Build Visual Studio vs. Build MSBuild.exe

Ada beberapa perbedaan signifikan antara ketika proyek dibangun di Visual Studio vs. ketika Anda memanggil MSBuild secara langsung, baik melalui MSBuild yang dapat dieksekusi, atau saat Anda menggunakan model objek MSBuild untuk memulai build. Visual Studio mengelola urutan build proyek untuk build Visual Studio; Visual Studio hanya memanggil MSBuild di tingkat proyek individu, serta ketika itu terjadi, beberapa properti Boolean (BuildingInsideVisualStudio, BuildProjectReferences) diatur yang secara signifikan memengaruhi apa yang dilakukan MSBuild. Di dalam setiap proyek, eksekusi terjadi sama seperti ketika dipanggil melalui MSBuild, tetapi perbedaan muncul dengan proyek yang direferensikan. Dalam MSBuild, ketika proyek yang dirujuk diperlukan, sebuah build benar-benar dilakukan; yaitu, proses ini menjalankan tugas-tugas dan alat, serta menghasilkan output. Saat build Visual Studio menemukan proyek yang dirujuk, MSBuild hanya mengembalikan output yang diharapkan dari proyek yang dirujuk; ini memungkinkan Visual Studio mengontrol pembangunan proyek lain tersebut. Visual Studio menentukan urutan build dan panggilan ke MSBuild secara terpisah (sesuai kebutuhan), semuanya sepenuhnya di bawah kontrol Visual Studio.

Perbedaan lain muncul ketika MSBuild dipanggil dengan file solusi, MSBuild mengurai file solusi, membuat file input XML standar, mengevaluasinya, dan menjalankannya sebagai proyek. Build solusi dijalankan sebelum proyek dimulai. Saat membangun dari Visual Studio, tidak ada yang terjadi; MSBuild tidak pernah melihat file solusi. Akibatnya, penyesuaian build solusi (menggunakan sebelum.SolutionName.sln.targets dan setelah.SolutionName.sln.targets) hanya berlaku untuk build MSBuild.exe, dotnet build, atau yang berbasis model objek, bukan build Visual Studio.

Kit Pengembangan Perangkat Lunak Proyek

Fitur SDK untuk file proyek MSBuild relatif baru. Sebelum perubahan ini, file proyek secara eksplisit mengimpor .target dan .props file yang menentukan proses build untuk jenis proyek tertentu.

Proyek .NET Core mengimpor versi .NET SDK yang sesuai dengannya. Lihat gambaran umum, .NET Core project SDK, dan referensi ke properti .

Fase evaluasi

Bagian ini membahas bagaimana file input ini diproses dan diurai untuk menghasilkan objek dalam memori yang menentukan apa yang akan dibangun.

Tujuan dari fase evaluasi adalah untuk membuat struktur objek dalam memori berdasarkan file XML input dan lingkungan lokal. Fase evaluasi terdiri dari enam tahap yang memproses file input seperti file XML proyek atau file XML yang diimpor, umumnya dinamai sebagai file .props atau .targets, tergantung pada apakah mereka terutama mengatur properti atau menentukan target build. Setiap langkah membentuk bagian dari objek yang disimpan di dalam memori yang kemudian digunakan dalam fase eksekusi untuk membangun proyek, tetapi tidak ada tindakan pembangunan yang sebenarnya terjadi selama fase evaluasi. Dalam setiap pass, elemen diproses dalam urutan munculnya elemen tersebut.

Langkah-langkah dalam fase evaluasi adalah sebagai berikut:

  • Mengevaluasi variabel lingkungan
  • Mengevaluasi impor dan karakteristik
  • Mengevaluasi definisi dari item
  • Mengevaluasi barang
  • Mengevaluasi elemen UsingTask
  • Mengevaluasi target

Impor dan properti dievaluasi dalam siklus yang sama sesuai urutan kemunculan, seperti impor diperluas di tempat. Dengan demikian, pengaturan properti dalam file yang diimpor sebelumnya tersedia dalam file yang diimpor nanti.

Urutan pass ini memiliki implikasi yang signifikan dan penting untuk diketahui saat menyesuaikan file proyek. Lihat Urutan evaluasi properti dan item.

Mengevaluasi variabel lingkungan

Dalam fase ini, variabel lingkungan digunakan untuk mengatur properti yang setara. Misalnya, variabel lingkungan PATH tersedia sebagai properti $(PATH). Saat dijalankan dari baris perintah atau skrip, lingkungan perintah digunakan seperti biasa, dan saat dijalankan dari Visual Studio, lingkungan berlaku saat Visual Studio diluncurkan digunakan.

Evaluasi impor dan sifat

Dalam fase ini, seluruh XML input dibaca, termasuk file proyek dan seluruh rantai impor. MSBuild membuat struktur XML dalam memori yang mewakili XML proyek dan semua file yang diimpor. Saat ini, properti yang tidak berada dalam target dievaluasi dan ditetapkan.

Sebagai konsekuensi dari MSBuild membaca semua file input XML di awal prosesnya, setiap perubahan pada input tersebut selama proses build tidak memengaruhi build saat ini.

Properti di luar target apa pun ditangani secara berbeda dari properti dalam target. Dalam fase ini, hanya properti yang ditentukan di luar target apa pun yang dievaluasi.

Karena properti diproses secara berurutan dalam tahap pemrosesan properti, properti pada setiap titik dalam masukan dapat mengakses nilai properti yang muncul sebelumnya dalam masukan, namun tidak untuk properti yang muncul kemudian.

Karena properti diproses sebelum item dievaluasi, Anda tidak dapat mengakses nilai item apa pun pada tahap manapun dari pemrosesan properti.

Mengevaluasi definisi item bisa

Pada tahap ini, definisi item ditafsirkan dan representasi dalam memori dari definisi ini dibuat.

Evaluasi item

Item yang ditentukan di dalam target ditangani secara berbeda dari item di luar target apa pun. Dalam fase ini, item yang berada di luar setiap target beserta metadata terkaitnya diproses. Metadata yang ditentukan oleh definisi item akan digantikan oleh metadata yang diterapkan langsung pada item. Karena item diproses dalam urutan yang muncul, Anda dapat mereferensikan item yang telah ditentukan sebelumnya, tetapi bukan item yang muncul nanti. Karena tahap item terjadi setelah tahap properti, item dapat mengakses properti apa pun jika ditentukan di luar target mana pun, terlepas dari apakah definisi properti muncul kemudian.

Mengevaluasi elemen UsingTask

Dalam fase ini, elemen UsingTask dibaca, dan tugas dinyatakan untuk digunakan nanti selama fase eksekusi.

Mengevaluasi target

Dalam fase ini, semua struktur objek target dibuat dalam memori, sebagai persiapan untuk eksekusi. Tidak ada eksekusi aktual yang terjadi.

Fase eksekusi

Dalam fase eksekusi, target disusun dan dijalankan, serta semua tugas dijalankan. Tetapi pertama-tama, properti dan item yang ditentukan dalam target dievaluasi bersama-sama dalam satu fase dalam urutan munculnya. Urutan pemrosesan sangat berbeda dari bagaimana properti dan item yang tidak berada dalam target diproses: semua properti terlebih dahulu, lalu semua item, dalam pass terpisah. Perubahan pada properti dan item dalam target dapat diamati setelah modifikasinya dilakukan pada target tersebut.

Urutan pembangunan target

Dalam satu proyek, target dijalankan satu per satu. Masalah pusat adalah cara menentukan urutan apa untuk membangun semuanya sehingga dependensi digunakan untuk membangun target dalam urutan yang tepat.

Urutan build target ditentukan oleh penggunaan atribut BeforeTargets, DependsOnTargets, dan AfterTargets pada setiap target. Urutan target selanjutnya dapat dipengaruhi selama eksekusi target sebelumnya jika target sebelumnya memodifikasi properti yang dirujuk dalam atribut ini.

Aturan untuk urutan pembangunan dijelaskan dalam Menentukan urutan pembangunan target. Proses ini ditentukan oleh struktur tumpukan yang berisi target yang akan dibangun. Target di bagian atas proses ini mulai dieksekusi, dan jika tergantung pada hal lain, maka target tersebut didorong ke bagian atas tumpukan, dan mulai dieksekusi. Ketika ada target yang tidak memiliki dependensi, target dieksekusi hingga selesai dan target induknya dapat dilanjutkan.

Referensi Proyek

Ada dua jalur kode yang dapat diambil MSBuild, yang normal, dijelaskan di sini, dan opsi grafik yang dijelaskan di bagian berikutnya.

Proyek individual menentukan ketergantungannya pada proyek lain melalui item ProjectReference. Ketika sebuah proyek yang berada di puncak tumpukan mulai dikerjakan, proyek tersebut mencapai titik di mana target ResolveProjectReferences dieksekusi, sebuah target standar yang ditentukan dalam berkas target umum.

ResolveProjectReferences memanggil tugas MSBuild dengan input item ProjectReference untuk mendapatkan output. Item ProjectReference diubah menjadi item lokal seperti Reference. Fase eksekusi MSBuild untuk proyek saat ini berhenti sementara fase eksekusi mulai memproses proyek yang direferensikan (fase evaluasi dilakukan terlebih dahulu sesuai kebutuhan). Proyek yang dirujuk hanya dibangun setelah Anda mulai membangun proyek dependen, sehingga ini membuat pohon bangunan proyek.

Visual Studio memungkinkan pembuatan dependensi proyek dalam file solusi (.sln). Dependensi ditentukan dalam file solusi dan hanya dihormati saat membangun solusi, atau saat membangun di dalam Visual Studio. Jika Anda membangun satu proyek, jenis dependensi ini diabaikan. Referensi solusi diubah oleh MSBuild menjadi item ProjectReference dan setelah itu diperlakukan dengan cara yang sama.

Opsi Grafik

Jika Anda menentukan pengalih build grafik (-graphBuild atau -graph), ProjectReference menjadi konsep utama yang digunakan oleh MSBuild. MSBuild akan mengurai semua proyek dan membangun grafik urutan pembuatan, grafik ketergantungan proyek yang aktual, yang kemudian ditelusuri untuk menentukan urutan pembuatan. Seperti halnya target dalam proyek individual, MSBuild memastikan bahwa proyek yang dirujuk dibangun setelah proyek yang mereka andalkan.

Pelaksanaan paralel

Jika menggunakan dukungan multiprosesor (saklar-maxCpuCount atau -m), MSBuild membuat node, yang merupakan proses MSBuild yang menggunakan inti CPU yang tersedia. Setiap proyek dikirimkan ke simpul yang tersedia. Dalam simpul, build proyek individual dijalankan secara serial.

Tugas dapat diaktifkan untuk eksekusi paralel dengan mengatur variabel boolean BuildInParallel, yang diatur sesuai dengan nilai properti $(BuildInParallel) di MSBuild. Untuk tugas yang memungkinkan eksekusi paralel, penjadwal kerja mengelola simpul dan menugaskan pekerjaan pada simpul.

Lihat Membangun beberapa proyek secara paralel dengan MSBuild

Impor standar

Microsoft.Common.props dan Microsoft.Common.targets diimpor oleh file proyek .NET (secara eksplisit atau implisit dalam proyek gaya SDK) dan terletak di folder MSBuild\Current\bin dalam penginstalan Visual Studio. Proyek C++ memiliki hierarki impor mereka sendiri; lihat MSBuild Internals untuk proyek C++.

Microsoft.Common.props menetapkan pengaturan default yang dapat Anda ubah. Ini diimpor (secara eksplisit atau implisit) di awal file proyek. Dengan begitu, pengaturan proyek Anda muncul setelah pengaturan bawaan, agar dapat menggantikannya.

File Microsoft.Common.targets dan file target yang diimpornya menentukan proses build standar untuk proyek .NET. Ini juga menyediakan titik ekstensi yang dapat Anda gunakan untuk menyesuaikan build.

Dalam pelaksanaannya, Microsoft.Common.targets adalah pembungkus tipis yang mengimpor Microsoft.Common.CurrentVersion.targets. File ini berisi pengaturan untuk properti standar, dan menentukan target aktual yang menentukan proses build. Target Build didefinisikan di sini, tetapi sebenarnya kosong. Namun, target Build berisi atribut DependsOnTargets yang menentukan target individu yang membentuk langkah-langkah build aktual, yaitu BeforeBuild, CoreBuild, dan AfterBuild. Target Build didefinisikan sebagai berikut:

  <PropertyGroup>
    <BuildDependsOn>
      BeforeBuild;
      CoreBuild;
      AfterBuild
    </BuildDependsOn>
  </PropertyGroup>

  <Target
      Name="Build"
      Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
      DependsOnTargets="$(BuildDependsOn)"
      Returns="@(TargetPathWithTargetPlatformMoniker)" />

BeforeBuild dan AfterBuild adalah titik ekstensi. Target tersebut kosong dalam file Microsoft.Common.CurrentVersion.targets, tetapi proyek dapat menyediakan target BeforeBuild dan AfterBuild mereka sendiri dengan tugas yang perlu dilakukan sebelum atau sesudah proses build utama. AfterBuild dijalankan sebelum target no-op, Build, karena AfterBuild muncul di atribut DependsOnTargets pada target Build, tetapi terjadi setelah CoreBuild.

Target CoreBuild berisi panggilan ke alat build, sebagai berikut:

  <PropertyGroup>
    <CoreBuildDependsOn>
      BuildOnlySettings;
      PrepareForBuild;
      PreBuildEvent;
      ResolveReferences;
      PrepareResources;
      ResolveKeySource;
      Compile;
      ExportWindowsMDFile;
      UnmanagedUnregistration;
      GenerateSerializationAssemblies;
      CreateSatelliteAssemblies;
      GenerateManifests;
      GetTargetPath;
      PrepareForRun;
      UnmanagedRegistration;
      IncrementalClean;
      PostBuildEvent
    </CoreBuildDependsOn>
  </PropertyGroup>
  <Target
      Name="CoreBuild"
      DependsOnTargets="$(CoreBuildDependsOn)">

    <OnError ExecuteTargets="_TimeStampAfterCompile;PostBuildEvent" Condition="'$(RunPostBuildEvent)'=='Always' or '$(RunPostBuildEvent)'=='OnOutputUpdated'"/>
    <OnError ExecuteTargets="_CleanRecordFileWrites"/>

  </Target>

Tabel berikut ini menjelaskan target ini; beberapa target hanya berlaku untuk jenis proyek tertentu.

Target Deskripsi
BuildOnlySettings Pengaturan untuk build sebenarnya saja, bukan untuk saat MSBuild dijalankan ketika proyek dimuat oleh Visual Studio.
PrepareForBuild Siapkan prasyarat untuk membangun
PreBuildEvent Titik perpanjangan proyek untuk menentukan tugas yang akan dijalankan sebelum pembangunan
ResolveProjectReferences Menganalisis dependensi proyek dan membangun proyek yang dirujuk
MenyelesaikanReferensiRakitan Temukan rakitan yang dirujuk.
ResolveReferences Terdiri dari ResolveProjectReferences dan ResolveAssemblyReferences untuk menemukan semua dependensi
PersiapkanSumberDaya Memproses file sumber daya
ResolveKeySource Selesaikan kunci nama kuat yang digunakan untuk menandatangani assembly dan sertifikat yang digunakan untuk menandatangani manifes ClickOnce.
Mengkompilasi Memanggil pengkompilasi
ExportWindowsMDFile Buat file WinMD dari file WinMDModule yang dihasilkan oleh pengkompilasi.
Pencabutan Pendaftaran yang Tidak Dikelola Hapus/bersihkan entri registri Interop COM dari build sebelumnya
Membuat Majelis Serialisasi Hasilkan rakitan serialisasi XML menggunakan sgen.exe.
CreateSatelliteAssemblies Buat satu rakitan satelit untuk setiap budaya unik dalam sumber daya.
Hasilkan Manifes Menghasilkan aplikasi ClickOnce dan manifes penyebaran atau manifes asli.
DapatkanJalurTujuan Mengembalikan item yang berisi produk hasil kompilasi (dapat dieksekusi atau rakitan) untuk proyek ini, beserta metadata.
PrepareForRun Salin output build ke direktori akhir jika telah berubah.
Registrasi Tidak Terkelola Mengatur entri registri untuk Interop COM
IncrementalClean Hapus file yang diproduksi dalam build sebelumnya tetapi tidak diproduksi dalam build saat ini. Hal ini diperlukan untuk membuat Clean bekerja dalam build bertahap.
Peristiwa Pasca-Pembangunan Titik ekstensi bagi proyek untuk menentukan tugas yang akan dijalankan setelah proses build

Banyak target dalam tabel sebelumnya ditemukan dalam impor khusus bahasa, seperti Microsoft.CSharp.targets. File ini menentukan langkah-langkah dalam proses build standar khusus untuk proyek C# .NET. Misalnya, berisi target Compile yang benar-benar memanggil pengkompilasi C#.

Impor yang dapat dikonfigurasi pengguna

Selain impor standar, ada beberapa impor yang dapat Anda tambahkan untuk menyesuaikan proses build.

  • Directory.Build.props
  • Directory.Build.targets

File-file ini dimasukkan sebagai impor standar untuk proyek apapun di subfolder manapun di bawahnya. Biasanya, ini berada pada tingkat solusi untuk mengatur semua proyek dalam solusi, tetapi juga bisa lebih tinggi di sistem file, sampai ke direktori akar drive.

File Directory.Build.props diimpor oleh Microsoft.Common.props, sehingga properti yang ditentukan di dalamnya tersedia dalam file proyek. Mereka dapat ditentukan ulang dalam file proyek untuk menyesuaikan nilai berdasarkan per proyek. File Directory.Build.targets dibaca setelah file proyek. Biasanya berisi target, tetapi di sini Anda juga dapat menentukan properti yang tidak ingin anda tentukan ulang masing-masing proyek.

Kustomisasi dalam file proyek

Visual Studio memperbarui file proyek saat Anda membuat perubahan di Penjelajah Solusi, jendela Properti, atau di Properti Proyek, tetapi Anda juga dapat membuat perubahan Anda sendiri dengan langsung mengedit file proyek.

Banyak perilaku build dapat dikonfigurasi dengan mengatur properti MSBuild, baik dalam file proyek untuk pengaturan lokal ke proyek, atau seperti yang disebutkan di bagian sebelumnya, dengan membuat Directory.Build.props file untuk mengatur properti secara global untuk seluruh folder proyek dan solusi. Untuk build ad hoc pada baris perintah, atau skrip, Anda juga dapat menggunakan opsi /p pada baris perintah untuk mengatur properti untuk pemanggilan MSBuild tertentu. Lihat Common MSBuild project properties untuk informasi tentang properti yang dapat Anda atur.