Memperluas proses build Visual Studio
Proses build Visual Studio ditentukan oleh serangkaian file MSBuild .targets
yang diimpor ke dalam file proyek Anda. Impor ini implisit, jika Anda menggunakan SDK seperti yang biasanya dilakukan proyek Visual Studio. Salah satu file yang diimpor ini, Microsoft.Common.targets, dapat diperluas agar memungkinkan Anda menjalankan tugas kustom di beberapa titik dalam proses build. Artikel ini menjelaskan tiga metode yang dapat Anda gunakan untuk memperluas proses build Visual Studio:
Buat target kustom dan tentukan kapan harus dijalankan dengan menggunakan
BeforeTargets
atribut danAfterTargets
.Ambil alih properti yang
DependsOn
ditentukan dalam target umum.Ambil alih target tertentu yang telah ditentukan sebelumnya yang ditentukan dalam target umum (Microsoft.Common.targets atau file yang diimpornya).
AfterTargets dan BeforeTargets
Anda dapat menggunakan AfterTargets
atribut dan BeforeTargets
pada target kustom Anda untuk menentukan kapan harus berjalan.
Contoh berikut menunjukkan cara menggunakan atribut AfterTargets
untuk menambahkan target kustom yang memengaruhi file output. Dalam hal ini, atribut menyalin file output ke folder baru CustomOutput. Contohnya juga menunjukkan cara membersihkan file yang dihasilkan oleh operasi build kustom dengan target CustomClean
yang menggunakan atribut BeforeTargets
dan menentukan spesifikasi operasi pembersihan kustom berjalan sebelum target CoreClean
.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<_OutputCopyLocation>$(OutputPath)..\..\CustomOutput\</_OutputCopyLocation>
</PropertyGroup>
<Target Name="CustomAfterBuild" AfterTargets="Build">
<ItemGroup>
<_FilesToCopy Include="$(OutputPath)**\*"/>
</ItemGroup>
<Message Text="_FilesToCopy: @(_FilesToCopy)" Importance="high"/>
<Message Text="DestFiles:
@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(_FilesToCopy)"
DestinationFiles=
"@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
<Target Name="CustomClean" BeforeTargets="CoreClean">
<Message Text="Inside Custom Clean" Importance="high"/>
<ItemGroup>
<_CustomFilesToDelete Include="$(_OutputCopyLocation)**\*"/>
</ItemGroup>
<Delete Files='@(_CustomFilesToDelete)'/>
</Target>
</Project>
Peringatan
Pastikan untuk menggunakan nama yang berbeda dari target yang telah ditentukan sebelumnya (misalnya, target build kustom di sini adalah CustomAfterBuild
, bukan AfterBuild
), karena target yang telah ditentukan sebelumnya ditimpa oleh impor SDK yang juga menentukannya. Lihat tabel di akhir artikel ini untuk daftar target yang telah ditentukan sebelumnya.
Memperluas properti DependsOn
Cara lain untuk memperluas proses build adalah dengan menggunakan DependsOn
properti (misalnya, BuildDependsOn
), untuk menentukan target yang harus dijalankan sebelum target standar.
Metode ini lebih disukai untuk mengambil alih target yang telah ditentukan sebelumnya, yang dibahas di bagian berikutnya. Mengesampingkan target yang telah ditentukan sebelumnya adalah metode lama yang masih didukung, tetapi, karena MSBuild mengevaluasi definisi target secara berurutan, tidak ada cara untuk mencegah proyek lain yang mengimpor proyek Anda mengesampingkan target yang sudah Anda timpa. Jadi, misalnya, target terakhir AfterBuild
yang ditentukan dalam file proyek akan menjadi target yang digunakan selama build setelah semua proyek lain diimpor.
Anda dapat melindungi dari penimpaan target yang tidak diinginkan dengan mengesampingkan DependsOn
properti yang digunakan dalam atribut di DependsOnTargets
seluruh target umum. Misalnya,target Build
berisi nilai atribut DependsOnTargets
dari "$(BuildDependsOn)"
. Pertimbangkan:
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>
Bagian XML ini menunjukkan bahwa sebelum target Build
dapat berjalan, semua target yang ditentukan dalam properti BuildDependsOn
harus berjalan terlebih dahulu. Properti BuildDependsOn
didefinisikan sebagai:
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
Anda dapat mengambil alih nilai properti ini dengan menentukan properti lain bernama BuildDependsOn
di akhir file proyek Anda. Dalam proyek bergaya SDK, ini berarti Anda harus menggunakan impor eksplisit. Lihat Impor impor implisit dan eksplisit, sehingga Anda dapat menempatkan DependsOn
properti setelah impor terakhir. Dengan menyertakan properti BuildDependsOn
sebelumnya di properti baru, Anda dapat menambahkan target baru ke awal dan akhir daftar target. Contohnya:
<PropertyGroup>
<BuildDependsOn>
MyCustomTarget1;
$(BuildDependsOn);
MyCustomTarget2
</BuildDependsOn>
</PropertyGroup>
<Target Name="MyCustomTarget1">
<Message Text="Running MyCustomTarget1..."/>
</Target>
<Target Name="MyCustomTarget2">
<Message Text="Running MyCustomTarget2..."/>
</Target>
Proyek yang mengimpor file proyek Anda dapat memperluas properti ini lebih lanjut tanpa menimpa kustomisasi yang telah Anda buat.
Untuk mengambil alih properti DependsOn
Identifikasi properti yang telah
DependsOn
ditentukan sebelumnya di target umum yang ingin Anda ambil alih. Lihat tabel berikut untuk daftar properti yang umumnya ditimpaDependsOn
.Tentukan contoh sebuah properti atau beberapa properti lain di akhir file proyek Anda. Sertakan properti asli, misalnya
$(BuildDependsOn)
, di properti baru.Tentukan target kustom Anda sebelum atau sesudah definisi properti.
Bangun file proyek.
Properti DependsOn yang umumnya diambil alih
Nama properti | Target yang ditambahkan berjalan sebelum titik ini: |
---|---|
BuildDependsOn |
Titik masuk build utama. Ambil alih properti ini jika Anda ingin menyisipkan target kustom sebelum atau sesudah seluruh proses build. |
RebuildDependsOn |
Tje Rebuild |
RunDependsOn |
Eksekusi output build akhir (jika itu adalah .EXE) |
CompileDependsOn |
Kompilasi (Compile target). Ambil alih properti ini jika Anda ingin menyisipkan proses kustom sebelum atau sesudah langkah kompilasi. |
CreateSatelliteAssembliesDependsOn |
Pembuatan rakitan satelit |
CleanDependsOn |
Target Clean (Menghapus semua output build perantara dan akhir). Ambil alih properti ini jika Anda ingin membersihkan output dari proses build kustom Anda. |
PostBuildEventDependsOn |
PostBuildEvent Target |
PublishBuildDependsOn |
Membangun penerbitan |
ResolveAssemblyReferencesDependsOn |
ResolveAssemblyReferences Target (menemukan penutupan dependensi transitif untuk dependensi tertentu). Lihat ResolveAssemblyReference . |
Contoh: BuildDependsOn dan CleanDependsOn
Contoh berikut mirip dengan contoh BeforeTargets
dan AfterTargets
, tetapi contoh ini menunjukkan cara mencapai fungsionalitas serupa. Contoh ini memperluas build dengan menggunakan BuildDependsOn
untuk menambahkan tugas CustomAfterBuild
Anda sendiri yang menyalin file output setelah build, dan juga menambahkan tugas CustomClean
yang sesuai dengan menggunakan CleanDependsOn
.
Dalam contoh ini, ini adalah proyek bergaya SDK. Seperti disebutkan dalam catatan tentang proyek gaya SDK sebelumnya dalam artikel ini, Anda harus menggunakan metode impor manual, bukan atribut Sdk
yang digunakan oleh Visual Studio saat menghasilkan file proyek.
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk"/>
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk"/>
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);CustomAfterBuild
</BuildDependsOn>
<CleanDependsOn>
$(CleanDependsOn);CustomClean
</CleanDependsOn>
<_OutputCopyLocation>$(OutputPath)..\..\CustomOutput\</_OutputCopyLocation>
</PropertyGroup>
<Target Name="CustomAfterBuild">
<ItemGroup>
<_FilesToCopy Include="$(OutputPath)**\*"/>
</ItemGroup>
<Message Importance="high" Text="_FilesToCopy: @(_FilesToCopy)"/>
<Message Text="DestFiles:
@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(_FilesToCopy)"
DestinationFiles="@(_FilesToCopy->'$(_OutputCopyLocation)%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
<Target Name="CustomClean">
<Message Importance="high" Text="Inside Custom Clean"/>
<ItemGroup>
<_CustomFilesToDelete Include="$(_OutputCopyLocation)**\*"/>
</ItemGroup>
<Delete Files="@(_CustomFilesToDelete)"/>
</Target>
</Project>
Urutan elemen itu penting. Elemen BuildDependsOn
dan CleanDependsOn
harus muncul setelah mengimpor file target SDK standar.
Mengambil alih target yang telah ditentukan sebelumnya
File umum .targets
berisi sekumpulan target kosong yang telah ditentukan sebelumnya yang dipanggil sebelum dan sesudah beberapa target utama dalam proses build. Misalnya, MSBuild memanggil target BeforeBuild
sebelum target utama CoreBuild
dan target AfterBuild
setelah target CoreBuild
. Secara default, target kosong dalam target umum tidak melakukan apa pun, tetapi Anda dapat mengambil alih perilaku defaultnya dengan menentukan target yang Anda inginkan dalam file proyek. Metode yang dijelaskan sebelumnya dalam artikel ini lebih disukai, tetapi Anda mungkin menemukan kode lama yang menggunakan metode ini.
Jika proyek Anda menggunakan SDK (misalnya Microsoft.Net.Sdk
), Anda perlu membuat perubahan dari implisit ke impor eksplisit, seperti yang dibahas dalam Impor eksplisit dan implisit.
Untuk mengambil alih target yang telah ditentukan sebelumnya
Jika proyek menggunakan
Sdk
atribut , ubah ke sintaks impor eksplisit. Lihat Impor eksplisit dan implisit.Identifikasi target yang telah ditentukan sebelumnya dalam target umum yang ingin Anda ambil alih. Lihat tabel berikut untuk daftar lengkap target yang bisa Anda ambil alih dengan aman.
Tentukan target atau target di akhir file proyek Anda, segera sebelum
</Project>
tag dan setelah impor SDK eksplisit. Contohnya:<Project> <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" /> ... <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /> <Target Name="BeforeBuild"> <!-- Insert tasks to run before build here --> </Target> <Target Name="AfterBuild"> <!-- Insert tasks to run after build here --> </Target> </Project>
Perhatikan bahwa
Sdk
atribut pada elemen tingkatProject
atas telah dihapus.Bangun file proyek.
Tabel target yang telah ditentukan sebelumnya
Tabel berikut ini memperlihatkan semua target dalam target umum yang bisa Anda ambil alih.
Nama target | Deskripsi |
---|---|
BeforeCompile , AfterCompile |
Tugas yang disisipkan dalam salah satu target ini berjalan sebelum atau sesudah kompilasi inti dilakukan. Sebagian besar penyesuaian dilakukan di salah satu dari dua target ini. |
BeforeBuild , AfterBuild |
Tugas yang disisipkan dalam salah satu target ini akan berjalan sebelum atau sesudah tugas lainnya dalam build. Catatan: Target BeforeBuild dan AfterBuild sudah ditentukan dalam komentar di akhir sebagian besar file proyek, yang memungkinkan Anda untuk dengan mudah menambahkan peristiwa pra-dan pasca-build ke file proyek Anda. |
BeforeRebuild , AfterRebuild |
Tugas yang disisipkan dalam salah satu target ini berjalan sebelum atau sesudah fungsionalitas pembangunan ulang inti dilakukan. Urutan eksekusi target di Microsoft.Common.targets adalah: BeforeRebuild , Clean , Build , lalu AfterRebuild . |
BeforeClean , AfterClean |
Tugas yang disisipkan dalam salah satu target ini berjalan sebelum atau sesudah fungsionalitas pembersihan inti dilakukan. |
BeforePublish , AfterPublish |
Tugas yang disisipkan dalam salah satu target ini berjalan sebelum atau sesudah fungsionalitas penerbitan inti dilakukan. |
BeforeResolveReferences , AfterResolveReferences |
Tugas yang disisipkan dalam salah satu target ini berjalan sebelum atau sesudah referensi rakitan diselesaikan. |
BeforeResGen , AfterResGen |
Tugas yang disisipkan dalam salah satu target ini berjalan sebelum atau sesudah sumber daya dihasilkan. |
Ada lebih banyak target dalam sistem build dan .NET SDK, lihat target MSBuild - SDK dan target build default.
Praktik terbaik untuk target kustom
Properti DependsOnTargets
dan BeforeTargets
dapat menentukan bahwa target harus berjalan sebelum target lain, tetapi keduanya diperlukan dalam skenario yang berbeda. Mereka berbeda di mana target persyaratan dependensi ditentukan. Anda hanya memiliki kontrol atas target Anda sendiri dan tidak dapat memodifikasi target sistem atau target impor lainnya dengan aman, sehingga membatasi pilihan metode Anda.
Saat menulis target kustom, ikuti panduan umum ini untuk memastikan target Anda dijalankan dalam urutan yang dimaksudkan.
DependsOnTargets
Gunakan atribut untuk menentukan target yang harus Anda lakukan sebelum target Anda dijalankan. Untuk rantai target yang Anda kontrol, setiap target dapat menentukan anggota rantai sebelumnya diDependsOnTargets
.Gunakan
BeforeTargets
untuk target apa pun yang tidak Anda kontrol yang harus Anda jalankan sebelumnya (sepertiBeforeTargets="PrepareForBuild"
untuk target yang perlu dijalankan di awal build).Gunakan
AfterTargets
untuk target apa pun yang tidak Anda kontrol yang menjamin output yang Anda butuhkan tersedia. Misalnya, tentukanAfterTargets="ResolveReferences"
untuk sesuatu yang akan memodifikasi daftar referensi.Anda dapat menggunakannya dalam kombinasi. Contohnya,
DependsOnTargets="GenerateAssemblyInfo" BeforeTargets="BeforeCompile"
.
Impor eksplisit dan implisit
Proyek yang dihasilkan oleh Visual Studio biasanya menggunakan Sdk
atribut pada elemen proyek. Jenis proyek ini disebut proyek bergaya SDK. Lihat Menggunakan SDK proyek MSBuild. Berikut contohnya:
<Project Sdk="Microsoft.Net.Sdk">
Saat proyek Anda menggunakan Sdk
atribut , dua impor ditambahkan secara implisit, satu di awal file proyek Anda, dan satu di akhir.
Impor implisit setara dengan memiliki pernyataan impor seperti ini sebagai baris pertama dalam file proyek, setelah Project
elemen:
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
dan pernyataan impor berikut sebagai baris terakhir dalam file proyek:
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
Sintaks ini disebut sebagai impor SDK eksplisit. Saat Anda menggunakan sintaks eksplisit ini, Anda harus menghilangkan Sdk
atribut pada elemen proyek.
Impor SDK implisit setara dengan mengimpor "umum" .props
atau .targets
file tertentu yang merupakan konstruksi umum dalam file proyek yang lebih lama, seperti:
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
dan
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Setiap referensi lama tersebut harus diganti dengan sintaks SDK eksplisit yang ditunjukkan sebelumnya di bagian ini.
Menggunakan sintaks SDK eksplisit berarti Anda dapat menambahkan kode Anda sendiri sebelum impor pertama, atau setelah impor SDK akhir. Itu berarti Anda dapat mengubah perilaku dengan mengatur properti sebelum impor pertama yang akan berlaku dalam file yang diimpor .props
, dan Anda dapat mengambil alih target yang ditentukan dalam salah satu file SDK .targets
setelah impor akhir. Dengan menggunakan metode ini, Anda dapat mengambil alih BeforeBuild
atau AfterBuild
sebagaimana dibahas berikutnya.
Langkah berikutnya
Ada lebih banyak lagi yang dapat Anda lakukan dengan MSBuild untuk menyesuaikan build. Lihat Menkustomisasi build Anda.
Konten terkait
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk