Bagikan melalui


Opsi tingkat solusi --output tidak lagi valid untuk perintah terkait build

Dalam 7.0.200 SDK, ada perubahan untuk tidak lagi menerima-o--output/opsi saat menggunakan file solusi dengan perintah berikut:

  • build
  • clean
  • pack
  • publish
  • store
  • test
  • vstest

Ini karena semantik properti, yang dikontrol OutputPath oleh --output/-o opsi , tidak didefinisikan dengan baik untuk solusi. Proyek yang dibangun dengan cara ini akan menempatkan output mereka di direktori yang sama, yang tidak konsisten dan telah menyebabkan sejumlah masalah yang dilaporkan pengguna.

Perubahan ini dikurangi ke tingkat keparahan peringatan di SDK 7.0.201, dan pack dihapus dari daftar perintah yang terpengaruh.

Versi yang diperkenalkan

.NET 7.0.200 SDK, dikurangi menjadi peringatan hanya di SDK 7.0.201.

Perilaku sebelumnya

Sebelumnya, jika Anda menentukan --output/-o saat menggunakan file solusi, output untuk semua proyek yang dibuat akan ditempatkan di direktori yang ditentukan dalam urutan yang tidak terdefinisi dan tidak konsisten.

Perilaku yang baru

dotnet CLI akan mengalami kesalahan jika --output/-o opsi digunakan dengan file solusi. Mulai dari 7.0.201 SDK, peringatan akan dipancarkan sebagai gantinya dotnet pack , dan jika tidak ada peringatan atau kesalahan yang akan dihasilkan.

Jenis perubahan yang melanggar

Perubahan yang melanggar ini mungkin memerlukan modifikasi untuk membangun skrip dan alur integrasi berkelanjutan. Akibatnya mempengaruhi kompatibilitas biner dan sumber.

Alasan untuk berubah

Perubahan ini dilakukan karena semantik properti, yang dikontrol OutputPath oleh --output/-o opsi , tidak didefinisikan dengan baik untuk solusi. Proyek yang dibangun dengan cara ini akan menempatkan output mereka di direktori yang sama, yang tidak konsisten dan telah menyebabkan sejumlah masalah yang dilaporkan pengguna.

Ketika solusi dibangun dengan --output opsi , OutputPath properti diatur ke nilai yang sama untuk semua proyek, yang berarti bahwa semua proyek akan memiliki output mereka ditempatkan di direktori yang sama. Tergantung pada kompleksitas proyek dalam solusi, hasil yang berbeda dan tidak konsisten dapat terjadi. Mari kita lihat beberapa contoh bentuk solusi yang berbeda dan bagaimana mereka dipengaruhi oleh berbagi OutputPath.

Proyek tunggal, TargetFramework tunggal

Bayangkan solusi yang berisi satu proyek yang menargetkan satu TargetFramework, net7.0. Dalam hal ini, menyediakan --output opsi setara dengan mengatur OutputPath properti dalam file proyek. Selama build (atau perintah lainnya, tetapi mari kita cakup diskusi yang akan dibangun untuk saat ini), semua output untuk proyek akan ditempatkan di direktori yang ditentukan.

Proyek tunggal, beberapa TargetFrameworks

Sekarang bayangkan solusi yang berisi satu proyek dengan beberapa TargetFrameworks, net6.0 dan net7.0. Karena multi-penargetan, proyek akan dibangun dua kali, sekali untuk setiap TargetFramework. Untuk setiap build 'dalam' OutputPath ini, akan diatur ke nilai yang sama, sehingga output untuk setiap build dalam akan ditempatkan di direktori yang sama. Ini berarti bahwa build mana pun yang selesai terakhir akan menimpa output build lain, dan dalam sistem build paralel seperti MSBuild beroperasi secara default, 'terakhir' tidak ditentukan.

Pustaka => Konsol => Uji, TargetFramework tunggal

Sekarang bayangkan solusi yang berisi proyek pustaka, proyek konsol yang mereferensikan proyek pustaka, dan proyek pengujian yang mereferensikan proyek konsol. Semua proyek ini menargetkan satu TargetFramework, net7.0. Dalam hal ini, proyek pustaka akan dibangun terlebih dahulu, dan kemudian proyek konsol akan dibangun. Proyek pengujian akan dibangun terakhir, dan akan mereferensikan proyek konsol. Untuk setiap proyek bawaan, output dari setiap build akan disalin ke dalam direktori yang ditentukan oleh OutputPath, sehingga direktori akhir akan berisi aset dari ketiga proyek. Ini berfungsi untuk pengujian, tetapi untuk penerbitan dapat mengakibatkan aset pengujian dikirim ke produksi.

Pustaka => Konsol => Uji, beberapa TargetFrameworks

Sekarang ambil rantai proyek yang sama dan tambahkan build net6.0TargetFramework ke net7.0 dalamnya selain build. Masalah yang sama dengan proyek tunggal, build multi-target terjadi - penyalinan aset khusus TFM yang tidak konsisten ke direktori yang ditentukan.

Beberapa aplikasi

Sejauh ini kami telah melihat skenario dengan grafik dependensi linier - tetapi banyak solusi mungkin berisi beberapa aplikasi terkait. Ini berarti bahwa beberapa aplikasi dapat dibangun bersamaan ke folder output yang sama. Jika aplikasi menyertakan file dependensi dengan nama yang sama, build mungkin gagal sesekali saat beberapa proyek mencoba menulis ke file tersebut di jalur output secara bersamaan.

Jika beberapa aplikasi bergantung pada versi file yang berbeda, maka bahkan jika build berhasil, versi file mana yang disalin ke jalur output mungkin tidak deterministik. Ini dapat terjadi ketika proyek bergantung (mungkin transitif) pada versi paket NuGet yang berbeda. Dalam satu proyek, NuGet membantu memastikan bahwa dependensinya (termasuk dependensi transitif melalui paket NuGet dan/atau referensi proyek) disatukan ke versi yang sama. Karena penyatuan dilakukan dalam konteks proyek tunggal dan proyek dependennya, ini berarti dimungkinkan untuk menyelesaikan versi paket yang berbeda ketika dua proyek tingkat atas terpisah dibangun. Jika proyek yang bergantung pada versi yang lebih tinggi menyalin dependensi terakhir, maka seringkali aplikasi akan berjalan dengan sukses. Namun, jika versi yang lebih rendah disalin terakhir, maka aplikasi yang dikompilasi terhadap versi yang lebih tinggi akan gagal memuat assembly pada runtime. Karena versi yang disalin dapat bersifat non-deterministik, ini dapat menyebabkan build yang sporadis dan tidak dapat diandalkan di mana sangat sulit untuk mendiagnosis masalah.

Contoh lainnya

Untuk contoh selengkapnya tentang bagaimana kesalahan mendasar ini muncul dalam praktiknya, lihat diskusi tentang dotnet/sdk#15607.

Rekomendasi umumnya adalah melakukan tindakan yang sebelumnya Anda ambil tanpa/--output-o opsi, lalu memindahkan output ke lokasi yang diinginkan setelah perintah selesai. Anda juga dapat melakukan tindakan pada proyek tertentu dan masih menerapkan --output/-o opsi , karena memiliki semantik yang lebih terdefinisi dengan baik.

Jika Anda ingin mempertahankan perilaku yang ada dengan tepat, maka Anda dapat menggunakan --property bendera untuk mengatur properti MSBuild ke direktori yang diinginkan. Properti yang digunakan bervariasi berdasarkan perintah:

Perintah Properti Contoh
build OutputPath dotnet build --property:OutputPath=DESIRED_PATH
clean OutputPath dotnet clean --property:OutputPath=DESIRED_PATH
pack PackageOutputPath dotnet pack --property:PackageOutputPath=DESIRED_PATH
publish PublishDir dotnet publish --property:PublishDir=DESIRED_PATH
store OutputPath dotnet store --property:OutputPath=DESIRED_PATH
test TestResultsDirectory dotnet test --property:OutputPath=DESIRED_PATH

CATATAN Untuk hasil terbaik, DESIRED_PATH harus menjadi jalur absolut. Jalur relatif akan 'berlabuh' (yaitu dibuat mutlak) dengan cara yang mungkin tidak Anda harapkan, dan mungkin tidak bekerja sama dengan semua perintah.