Saya memiliki file solusi c # besar (~ 100 proyek), dan saya mencoba untuk meningkatkan waktu pembuatan. Saya pikir "Copy Local" boros dalam banyak kasus bagi kami, tetapi saya bertanya-tanya tentang praktik terbaik.
Dalam .sln, kami memiliki aplikasi A tergantung pada rakitan B yang tergantung pada rakitan C. Dalam kasus kami, ada lusinan "B" dan beberapa "C". Karena ini semua termasuk dalam .sln, kami menggunakan referensi proyek. Semua majelis saat ini membangun $ (SolutionDir) / Debug (atau Rilis).
Secara default, Visual Studio menandai referensi proyek ini sebagai "Salin Lokal", yang menghasilkan setiap "C" disalin ke $ (SolutionDir) / Debug sekali untuk setiap "B" yang membangun. Ini sepertinya boros. Apa yang salah jika saya mematikan "Salin Lokal"? Apa yang dilakukan orang lain dengan sistem besar?
MENGIKUTI:
Banyak tanggapan menyarankan untuk memecah bangunan menjadi file .sln yang lebih kecil ... Pada contoh di atas, saya akan membangun kelas dasar "C" terlebih dahulu, diikuti oleh sebagian besar modul "B", dan kemudian beberapa aplikasi, " SEBUAH". Dalam model ini, saya perlu memiliki referensi non-proyek untuk C dari B. Masalah yang saya temui adalah bahwa "Debug" atau "Release" dimasukkan ke jalur petunjuk dan saya akhirnya membangun build rilis saya dengan "B" terhadap debug membangun "C".
Bagi Anda yang membagi bangunan menjadi beberapa file .sln, bagaimana Anda mengelola masalah ini?
sumber
<Private>True</Private>
di csproj?.sln
menjadi yang lebih kecil mematahkan perhitungan interdependensi automagic VS<ProjectReference/>
s. Saya telah pindah dari beberapa yang lebih kecil.sln
menjadi satu yang besar.sln
sendiri hanya karena VS menyebabkan lebih sedikit masalah dengan cara itu ... Jadi, mungkin tindak lanjutnya dengan mengasumsikan solusi yang belum tentu terbaik untuk pertanyaan awal? ;-)Jawaban:
Dalam proyek sebelumnya saya bekerja dengan satu solusi besar dengan referensi proyek dan menabrak masalah kinerja juga. Solusinya tiga kali lipat:
Selalu atur properti Salin Lokal ke false dan tegakkan ini melalui langkah msbuild khusus
Atur direktori output untuk setiap proyek ke direktori yang sama (lebih disukai relatif ke $ (SolutionDir)
Target cs default yang dikirimkan dengan kerangka kerja menghitung set referensi yang akan disalin ke direktori keluaran proyek yang saat ini sedang dibangun. Karena ini memerlukan penghitungan penutupan transitif di bawah hubungan 'Referensi', ini bisa menjadi SANGAT mahal. Solusi saya untuk ini adalah mendefinisikan kembali
GetCopyToOutputDirectoryItems
target dalam file target umum (mis.Common.targets
) Yang diimpor di setiap proyek setelah imporMicrosoft.CSharp.targets
. Menghasilkan setiap file proyek terlihat seperti berikut:Ini mengurangi waktu build kami pada waktu tertentu dari beberapa jam (sebagian besar karena kendala memori), menjadi beberapa menit.
The didefinisikan ulang
GetCopyToOutputDirectoryItems
dapat dibuat dengan menyalin garis 2,438-2,450 dan 2,474-2,524 dariC:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets
dalamCommon.targets
.Untuk kelengkapan definisi target yang dihasilkan kemudian menjadi:
Dengan solusi ini di tempat saya menemukan itu bisa diterapkan untuk memiliki sebanyak> 120 proyek dalam satu solusi, ini memiliki manfaat utama bahwa urutan pembangunan proyek masih dapat ditentukan oleh VS daripada melakukan itu dengan tangan dengan membagi solusi Anda .
sumber
Saya sarankan Anda membaca artikel Patric Smacchia tentang hal itu:
Anda juga dapat membaca artikel ini untuk membantu Anda mengurangi jumlah proyek Anda dan meningkatkan waktu kompilasi Anda.
sumber
Saya sarankan memiliki salinan local = false untuk hampir semua proyek kecuali yang ada di atas pohon dependensi. Dan untuk semua referensi yang ada di atas set copy local = true. Saya melihat banyak orang menyarankan berbagi direktori keluaran; Saya pikir ini adalah ide yang mengerikan berdasarkan pengalaman. Jika proyek startup Anda menyimpan referensi ke dll yang mana proyek lain memegang referensi untuk Anda pada suatu saat akan mengalami pelanggaran akses \ berbagi bahkan jika salinan lokal = salah pada semuanya dan bangunan Anda akan gagal. Masalah ini sangat menyebalkan dan sulit dilacak. Saya benar-benar menyarankan menjauh dari direktori keluaran beling dan bukannya memiliki proyek di bagian atas rantai ketergantungan menulis majelis yang diperlukan ke folder yang sesuai. Jika Anda tidak memiliki proyek di "atas," maka saya akan menyarankan salinan post-build untuk mendapatkan semuanya di tempat yang tepat. Juga, saya akan mencoba dan mengingat kemudahan debugging. Setiap proyek exe saya masih meninggalkan copy local = true sehingga pengalaman debug F5 akan bekerja.
sumber
Anda benar. CopyLocal benar-benar akan membunuh waktu membangun Anda. Jika Anda memiliki struktur kode sumber yang besar maka Anda harus menonaktifkan CopyLocal. Sayangnya itu tidak semudah menonaktifkannya dengan benar. Saya telah menjawab pertanyaan ini tentang menonaktifkan CopyLocal di Bagaimana cara mengganti pengaturan CopyLocal (Pribadi) untuk referensi di .NET dari MSBUILD . Saksikan berikut ini. Serta praktik terbaik untuk solusi besar di Visual Studio (2008).
Berikut ini beberapa info lebih lanjut tentang CopyLocal seperti yang saya lihat.
CopyLocal benar-benar diimplementasikan untuk mendukung debugging lokal. Ketika Anda menyiapkan aplikasi untuk pengemasan dan penyebaran, Anda harus membangun proyek Anda ke folder keluaran yang sama dan pastikan Anda memiliki semua referensi yang Anda butuhkan di sana.
Saya telah menulis tentang bagaimana menangani membangun pohon sumber besar dalam artikel MSBuild: Praktik Terbaik Untuk Membuat Bangunan yang Andal, Bagian 2 .
sumber
Menurut pendapat saya, memiliki solusi dengan 100 proyek adalah kesalahan besar. Anda mungkin dapat membagi solusi Anda dalam unit logis kecil yang valid, sehingga menyederhanakan pemeliharaan dan pembuatan.
sumber
Saya terkejut tidak ada yang disebutkan menggunakan hardlink. Alih-alih menyalin file, itu membuat hardlink ke file asli. Ini menghemat ruang disk dan juga mempercepat pembangunan. Ini dapat diaktifkan pada baris perintah dengan properti berikut:
/ p: CreateHardLinksForAdditionalFilesIfPossible = true; CreateHardLinksForCopyAdditionalFilesIfPossible = true; CreateHardLinksForCopyFilesToOutputDirectoryIfPossible = true; CreateHardLinksForCopyLocalIfPemungkinanBertarungPelanggan = truePemungkinanBertarungungDapatMungkin = true;
Anda juga dapat menambahkan ini ke file impor pusat sehingga semua proyek Anda juga bisa mendapatkan manfaat ini.
sumber
Jika Anda mendapatkan struktur dependensi yang ditentukan melalui referensi proyek atau melalui dependensi tingkat solusi, aman untuk mengaktifkan "Salin Lokal" Saya bahkan akan mengatakan bahwa itu adalah praktik terbaik untuk dilakukan, karena itu akan memungkinkan Anda menggunakan MSBuild 3.5 untuk menjalankan build Anda secara paralel ( via / maxcpucount) tanpa proses berbeda yang saling berujung ketika mencoba menyalin rujukan yang direferensikan.
sumber
"praktik terbaik" kami adalah menghindari solusi dengan banyak proyek. Kami memiliki direktori bernama "matrix" dengan versi rakitan saat ini, dan semua referensi berasal dari direktori ini. Jika Anda mengubah beberapa proyek dan Anda dapat mengatakan "sekarang perubahannya selesai" Anda dapat menyalin perakitan ke direktori "matriks". Jadi semua proyek yang bergantung pada perakitan ini akan memiliki versi saat ini (= terbaru).
Jika Anda memiliki beberapa proyek dalam penyelesaian, proses pembuatannya jauh lebih cepat.
Anda dapat mengotomatiskan langkah "salin rakitan ke direktori matriks" menggunakan makro studio visual atau dengan "menu -> alat -> alat eksternal ...".
sumber
Anda tidak perlu mengubah nilai CopyLocal. Yang perlu Anda lakukan adalah menetapkan $ umum (OutputPath) untuk semua proyek dalam solusi dan $ ditetapkan sebelumnya (UseCommonOutputDirectory) menjadi true. Lihat ini: http://blogs.msdn.com/b/kirillosenkov/archive/2015/04/04/using-a-common-intermediate-and-output-directory-for-your-solution.aspx
sumber
Set CopyLocal = false akan mengurangi waktu pembuatan, tetapi dapat menyebabkan masalah yang berbeda selama penerapan.
Ada banyak skenario, ketika Anda perlu memiliki Copy Local 'kiri ke True, misalnya
Masalah yang mungkin dijelaskan dalam pertanyaan SO
" Kapan salinan-lokal disetel ke true dan kapan tidak? ",
" Pesan kesalahan 'Tidak dapat memuat satu atau lebih dari jenis yang diminta. Ambil properti LoaderExceptions untuk informasi lebih lanjut.' "
Dan aaron-stainback 's jawaban untuk pertanyaan ini.
Pengalaman saya dengan pengaturan CopyLocal = false TIDAK berhasil. Lihat posting blog saya "JANGAN Ubah referensi proyek" Salin Lokal "ke false, kecuali pahami selanjutnya."
Waktu untuk mengatasi masalah kelebihan manfaat pengaturan copyLocal = false.
sumber
CopyLocal=False
pasti akan menyebabkan beberapa masalah, tetapi ada solusi untuk itu. Juga, Anda harus memperbaiki format blog Anda, itu hampir tidak dapat dibaca, dan mengatakan di sana bahwa "Saya telah diperingatkan oleh <konsultan acak> dari <perusahaan acak> tentang kemungkinan kesalahan selama penyebaran" bukan argumen. Anda perlu berkembang.Saya cenderung membangun ke direktori umum (misalnya .. \ bin), jadi saya bisa membuat solusi pengujian kecil.
sumber
Anda dapat mencoba menggunakan folder tempat semua rakitan yang dibagikan di antara proyek akan disalin, lalu buat variabel lingkungan DEVPATH dan atur
<developmentMode developerInstallation="true" />
dalam file machine.config pada setiap workstation pengembang. Satu-satunya hal yang perlu Anda lakukan adalah menyalin versi baru di folder Anda di mana DEVPATH mengarahkan poin.
Juga bagi solusi Anda menjadi beberapa solusi yang lebih kecil jika memungkinkan.
sumber
Ini mungkin bukan praktik terbaik, tetapi ini adalah cara saya bekerja.
Saya memperhatikan bahwa Managed C ++ membuang semua binernya ke dalam $ (SolutionDir) / 'DebugOrRelease'. Jadi saya membuang semua proyek C # saya di sana juga. Saya juga mematikan "Salin Lokal" dari semua referensi ke proyek dalam solusi. Saya telah melihat peningkatan waktu pembangunan dalam solusi 10 proyek kecil saya. Solusi ini adalah campuran dari C #, C ++ terkelola, C ++ asli, layanan web C #, dan proyek pemasang.
Mungkin ada sesuatu yang rusak, tetapi karena ini adalah satu-satunya cara saya bekerja, saya tidak menyadarinya.
Akan menarik untuk mengetahui apa yang saya langgar.
sumber
Biasanya, Anda hanya perlu Salin Lokal jika Anda ingin proyek Anda menggunakan DLL yang ada di Bin Anda vs apa yang ada di tempat lain (GAC, proyek lain, dll.)
Saya cenderung setuju dengan orang lain bahwa Anda juga harus mencoba, jika mungkin, untuk memecah solusi itu.
Anda juga dapat menggunakan Pengelola Konfigurasi untuk membuat sendiri konfigurasi bangunan yang berbeda di dalam satu solusi yang hanya akan membangun rangkaian proyek tertentu.
Tampaknya aneh jika semua 100 proyek mengandalkan satu sama lain, jadi Anda harus dapat memecahnya atau menggunakan Pengelola Konfigurasi untuk membantu diri Anda sendiri.
sumber
Anda dapat meminta referensi proyek Anda menunjuk ke versi debug dll. Dari pada skrip msbuild Anda, Anda dapat mengaturnya
/p:Configuration=Release
, sehingga Anda akan memiliki versi rilis aplikasi Anda dan semua rakitan satelit.sumber
Jika Anda ingin memiliki tempat pusat untuk referensi DLL menggunakan salinan lokal palsu akan gagal tanpa GAC kecuali Anda melakukannya.
http://nbaked.wordpress.com/2010/03/28/gac-alternative/
sumber
Jika referensi tidak terkandung dalam GAC, kita harus mengatur Salin Lokal ke true sehingga aplikasi akan berfungsi, jika kami yakin bahwa referensi akan diinstal sebelumnya di GAC maka dapat disetel ke false.
sumber
Yah, saya tentu tidak tahu bagaimana masalah tersebut berhasil, tetapi saya telah melakukan kontak dengan solusi build yang membantu dirinya sendiri sehingga semua file yang dibuat diletakkan di ramdisk dengan bantuan tautan simbolik .
c: \ folder solusi \ obj -> ramdisk r: \ folder solusi \ obj \
Anda juga dapat memberi tahu tambahan studio visual direktori temp yang dapat digunakan untuk pembuatan.
Sebenarnya bukan itu yang terjadi. Tapi itu benar-benar menyentuh pemahaman saya tentang kinerja.
Penggunaan prosesor 100% dan proyek besar dalam waktu kurang dari 3 Menit dengan semua ketergantungan.
sumber