Derleme başvurularında sorun giderme
MSBuild ve .NET derleme işlemindeki en önemli görevlerden biri, görevde gerçekleşen derleme başvurularını çözümlemektir ResolveAssemblyReference
. Bu makalede, nasıl ResolveAssemblyReference
çalıştığına ilişkin bazı ayrıntılar ve başvuru çözümlenemediğinde ResolveAssemblyReference
gerçekleşebilecek derleme hatalarını giderme adımları açıklanmaktadır. Derleme başvurusu hatalarını araştırmak için YAPıLANDıRıLMıŞ Günlük Görüntüleyicisi'ni yükleyip MSBuild günlüklerini görüntülemek isteyebilirsiniz. Bu makaledeki ekran görüntüleri Yapılandırılmış Günlük Görüntüleyicisi'nden alınmıştır.
AmacıResolveAssemblyReference
, öğe aracılığıyla <Reference>
dosyalarda .csproj
(veya başka bir yerde) belirtilen tüm başvuruları almak ve bunları dosya sistemindeki derleme dosyalarına eşlemektir.
Derleyiciler yalnızca dosya sistemindeki bir .dll
yolu başvuru olarak kabul edebilir, bu nedenle ResolveAssemblyReference
proje dosyalarında görünen gibi mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
dizeleri gibi C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll
yollara dönüştürür ve bu da daha sonra anahtar aracılığıyla /r
derleyiciye geçirilir.
ResolveAssemblyReference
Ayrıca, tüm .dll
ve başvuruların tamamını (aslında grafik teorisi terimlerinde geçişli kapanış) belirler ve .exe
her biri için derleme çıkış dizinine kopyalanıp kopyalanmayacağını belirler. Gerçek kopyalamayı yapmaz (daha sonra gerçek derleme adımından sonra işlenir), ancak kopyalanacak dosyaların bir öğe listesini hazırlar.
ResolveAssemblyReference
hedeften çağrılır ResolveAssemblyReferences
:
Sıralamayı fark ederseniz, ResolveAssemblyReferences
öncesinde Compile
gerçekleşir ve elbette CopyFilesToOutputDirectory
sonrasında Compile
gerçekleşir.
Not
ResolveAssemblyReference
görev, MSBuild yükleme klasörlerindeki standart .targets
dosyada Microsoft.Common.CurrentVersion.targets
çağrılır. .NET SDK MSBuild hedeflerine de adresinden https://github.com/dotnet/msbuild/blob/a936b97e30679dcea4d99c362efa6f732c9d3587/src/Tasks/Microsoft.Common.CurrentVersion.targets#L1991-L2140çevrimiçi olarak göz atabilirsiniz. Bu bağlantı, görevin dosyada ResolveAssemblyReference
tam olarak nerede çağrıldığı .targets
gösterir.
ResolveAssemblyReference girişleri
ResolveAssemblyReference
girişlerini günlüğe kaydetme hakkında kapsamlıdır:
Düğüm Parameters
tüm görevler için standarttır, ancak buna ek olarak ResolveAssemblyReference
Girişler altında kendi bilgi kümesini günlüğe kaydeder (temelde altında Parameters
olduğu gibi ancak farklı yapılandırılmıştır).
En önemli girişler şunlardırAssemblies
:AssemblyFiles
<ResolveAssemblyReference
Assemblies="@(Reference)"
AssemblyFiles="@(_ResolvedProjectReferencePaths);@(_ExplicitReference)"
Assemblies
, proje için çağrıldığı ResolveAssemblyReference
anda MSBuild öğesinin içeriğini Reference
kullanır. NuGet başvurularınız da dahil olmak üzere tüm meta veriler ve derleme başvuruları bu öğede yer almalıdır. Her başvuruya eklenmiş zengin bir meta veri kümesi vardır:
AssemblyFiles
hedefin adlı _ResolvedProjectReferencePaths
çıkış öğesinden ResolveProjectReference
gelir. ResolveProjectReference
daha önce ResolveAssemblyReference
çalıştırılır ve öğeleri disk üzerindeki yerleşik derlemelerin yollarına dönüştürür <ProjectReference>
. Bu nedenle, AssemblyFiles
geçerli projenin tüm başvurulu projeleri tarafından oluşturulan derlemeleri içerecektir:
Başka bir yararlı giriş, değerini özelliğinden _FindDependencies
alan boole FindDependencies
parametresidir:
FindDependencies="$(_FindDependencies)"
Geçişli bağımlılık derlemelerinin analizini kapatmak için derlemenizde bu özelliği false
olarak ayarlayabilirsiniz.
ResolveAssemblyReference algoritması
Görevin basitleştirilmiş algoritması ResolveAssemblyReference
aşağıdaki gibidir:
- Günlük girişleri.
- Ortam değişkenini
MSBUILDLOGVERBOSERARSEARCHRESULTS
denetleyin. Daha ayrıntılı günlükler almak için bu değişkeni herhangi bir değere ayarlayın. - Başvurular nesnesinin tablosunu başlatın.
- Önbellek dosyasını (varsa) dizininden
obj
okuyun. - Bağımlılıkların kapatılmasını hesaplama.
- Çıkış tablolarını oluşturun.
- Önbellek dosyasını dizine
obj
yazın. - Sonuçları günlüğe kaydetme.
Algoritma, derlemelerin giriş listesini alır (hem meta verilerden hem de proje başvurularından), işlediği her derleme için başvuru listesini alır (meta verileri okuyarak) ve başvuruda bulunılan tüm derlemelerin eksiksiz bir kümesini (geçişli kapanış) oluşturur ve bunları çeşitli konumlardan (GAC, AssemblyFoldersEx vb.) çözümler.
Başvuruda bulunan derlemeler, yeni başvuru ekleninceye kadar listeye yinelemeli olarak eklenir. Ardından algoritma durdurulur.
Göreve sağladığınız doğrudan başvurular Birincil başvurular olarak adlandırılır. Geçişli başvuru nedeniyle kümeye eklenen dolaylı derlemelere Bağımlılık adı verilir. Her dolaylı derlemenin kaydı, dahil edilmesine ve buna karşılık gelen meta verilerine yol açan tüm birincil ("kök") öğeleri izler.
ResolveAssemblyReference görevinin sonuçları
ResolveAssemblyReference
sonuçların ayrıntılı günlüğünü sağlar:
Çözümlenen derlemeler iki kategoriye ayrılır: Birincil başvurular ve Bağımlılıklar. Birincil başvurular, oluşturulan projenin başvuruları olarak açıkça belirtildi. Bağımlılıklar, başvuru başvurularından geçişli olarak çıkarılmıştır.
Önemli
ResolveAssemblyReference
belirli bir derlemenin başvurularını belirlemek için derleme meta verilerini okur. C# derleyicisi bir derleme yaydığında, yalnızca gerçekten gerekli olan derlemelere başvurular ekler. Bu nedenle, belirli bir projeyi derlediğinizde, proje derlemede işlenmeyen gereksiz bir başvuru belirtebilir. Gerekli olmayan projeye başvurular eklemek sorun değil; yoksayılır.
CopyLocal öğesi meta verileri
Başvurular da meta veriye CopyLocal
sahip olabilir veya olmayabilir. Başvuruda varsa CopyLocal = true
, daha sonra hedef tarafından CopyFilesToOutputDirectory
çıkış dizinine kopyalanır. Bu örnekte true DataFlow
CopyLocal
olarak ayarlanmış, ancak Immutable
ayarlanmamaktadır:
CopyLocal
Meta veriler tamamen eksikse varsayılan olarak true olduğu varsayılır. Bu nedenle ResolveAssemblyReference
, aksi bir neden bulmadığı sürece varsayılan olarak bağımlılıkları çıkışa kopyalamaya çalışır. ResolveAssemblyReference
, belirli bir başvuruyu olmak CopyLocal
veya seçmemek için nedenlerini kaydeder.
Karar için CopyLocal
tüm olası nedenler aşağıdaki tabloda listelenir. Derleme günlüklerinde arama yapabilmek için bu dizeleri bilmek yararlı olur.
CopyLocal durumu | Açıklama |
---|---|
Undecided |
Kopyalama yerel durumu şu anda kararsız. |
YesBecauseOfHeuristic |
Herhangi bir nedenle 'hayır' olmadığından başvuru olmalıdır CopyLocal='true' . |
YesBecauseReferenceItemHadMetadata |
Kaynak öğesi Private='true' olduğundan Başvuru olmalıdır CopyLocal='true' |
NoBecauseFrameworkFile |
Başvurunun olması CopyLocal='false' gerekir çünkü bu bir çerçeve dosyasıdır. |
NoBecausePrerequisite |
Başvurunun önkoşul CopyLocal='false' dosyası olması gerekir. |
NoBecauseReferenceItemHadMetadata |
Özniteliği projede 'false' olarak ayarlandığından Private başvuru CopyLocal='false' olmalıdır. |
NoBecauseReferenceResolvedFromGAC |
Başvuru, GAC'den çözümlendiği için olmalıdır CopyLocal='false' . |
NoBecauseReferenceFoundInGAC |
Derleme GAC'de bulunduğunda (başka bir yerde çözümlendiğinde bile) eski davranış CopyLocal='false' . |
NoBecauseConflictVictim |
Başvurunun, aynı adlı derleme dosyası arasındaki çakışmayı kaybettiğinden olması CopyLocal='false' gerekir. |
NoBecauseUnresolved |
Başvuru çözümlenmedi. Bulunamadığından bin dizinine kopyalanamaz. |
NoBecauseEmbedded |
Başvuru eklenmiştir. Çalışma zamanında yüklenmeyacağından bin dizinine kopyalanmamalıdır. |
NoBecauseParentReferencesFoundInGAC |
özelliği copyLocalDependenciesWhenParentReferenceInGac false olarak ayarlanır ve tüm üst kaynak öğeleri GAC'de bulundu. |
NoBecauseBadImage |
Sağlanan derleme dosyası, hatalı bir görüntü olduğundan, büyük olasılıkla yönetilmediğinden, büyük olasılıkla hiç derleme olmadığından kopyalanmamalıdır. |
Özel öğe meta verileri
Belirlemenin CopyLocal
önemli bir kısmı, tüm birincil başvurulardaki meta verilerdir Private
. Her başvurunun (birincil veya bağımlılık), bu başvurunun kapanışa eklenmesine katkıda bulunan tüm birincil başvuruların (kaynak öğeler) bir listesi vardır.
- Kaynak öğelerden hiçbiri meta veri belirtmezse
Private
,CopyLocal
olarak ayarlanırTrue
(veya ayarlanmaz; varsayılan olarakTrue
) - Kaynak öğelerden herhangi biri öğesini belirtirse
Private=true
CopyLocal
, olarak ayarlanırTrue
- Kaynak derlemelerden hiçbiri belirtmezse
Private=true
ve en az biri belirtirsePrivate=false
,CopyLocal
olarak ayarlanırFalse
Hangi başvuru Özel değerini false olarak ayarladı?
Son nokta, false olarak ayarlanması için CopyLocal
sık kullanılan bir nedendir: This reference is not "CopyLocal" because at least one source item had "Private" set to "false" and no source items had "Private" set to "true".
MSBuild hangi başvurunun false olarak ayarlandığını Private
bize söylemez, ancak yapılandırılmış günlük görüntüleyicisi yukarıda belirtilen öğelere meta veriler ekler Private
:
Bu, araştırmaları basitleştirir ve söz konusu bağımlılığın ile CopyLocal=false
ayarlanmasına tam olarak hangi başvurunun neden olduğunu bildirir.
Genel Derleme Önbelleği
Genel Derleme Önbelleği (GAC), başvuruların çıkışa kopyalanıp kopyalanmayacağını belirlemede önemli bir rol oynar. GaC'nin içeriği makineye özgü olduğundan ve bu durum yeniden üretilebilir derlemelerde sorunlarla sonuçlandığından (davranış, GAC gibi makine durumuna bağlı farklı makinelerde farklılık gösterdiğinde) bu durum talihsiz bir durumdur.
Durumu hafifletmek için ResolveAssemblyReference
son düzeltmeler yapıldı. bu iki yeni giriş ResolveAssemblyReference
ile davranışını denetleyebilirsiniz:
CopyLocalDependenciesWhenParentReferenceInGac="$(CopyLocalDependenciesWhenParentReferenceInGac)"
DoNotCopyLocalIfInGac="$(DoNotCopyLocalIfInGac)"
AssemblySearchPaths
Bir derlemeyi bulmaya çalışırken yol ResolveAssemblyReference
aramalarının listesini özelleştirmenin iki yolu vardır. Listeyi tam olarak özelleştirmek için özelliği AssemblySearchPaths
önceden ayarlanabilir. Sipariş önemlidir; bir derleme iki konumdaysa, ResolveAssemblyReference
ilk konumda bulduklarında durur.
Varsayılan olarak, on konum araması vardır (.NET SDK kullanıyorsanız dört konum ResolveAssemblyReference
) ve ilgili bayrak false olarak ayarlanarak her birini devre dışı bırakabilirsiniz:
- Geçerli projeden dosya arama özelliği false olarak ayarlanarak
AssemblySearchPath_UseCandidateAssemblyFiles
devre dışı bırakılır. - Başvuru yolu özelliğinde arama (dosyadan
.user
) özelliği false olarak ayarlanarakAssemblySearchPath_UseReferencePath
devre dışı bırakılır. - Öğeden ipucu yolunun kullanılması özelliği false olarak ayarlanarak
AssemblySearchPath_UseHintPathFromItem
devre dışı bırakılır. - MSBuild'in hedef çalışma zamanı ile dizini kullanmak, özelliği false olarak ayarlanarak
AssemblySearchPath_UseTargetFrameworkDirectory
devre dışı bırakılır. - AssemblyFolders.config dosyasından derleme klasörleri aranırken özelliği false olarak ayarlanarak
AssemblySearchPath_UseAssemblyFoldersConfigFileSearchPath
devre dışı bırakılır. - Özelliği false olarak ayarlanarak
AssemblySearchPath_UseRegistry
kayıt defterinde arama devre dışı bırakılır. - Eski kayıtlı derleme klasörlerinde arama özelliği false olarak ayarlanarak
AssemblySearchPath_UseAssemblyFolders
devre dışı bırakılır. - GAC'ye bakmak özelliği false olarak ayarlanarak
AssemblySearchPath_UseGAC
devre dışı bırakılır. - Özelliği false olarak ayarlanarak
AssemblySearchPath_UseRawFileName
başvurunun Include değerini gerçek bir dosya adı olarak ele almak devre dışı bırakılır. - Özelliği false olarak ayarlanarak
AssemblySearchPath_UseOutDir
uygulamanın çıkış klasörü denetleniyor.
Bir çakışma oluştu
Sık karşılaşılan bir durum, MSBuild'in farklı başvurular tarafından kullanılan aynı derlemenin farklı sürümleri hakkında bir uyarı vermesidir. Çözüm genellikle app.config dosyasına bağlama yeniden yönlendirmesi eklemeyi içerir.
Bu çakışmaları araştırmanın kullanışlı bir yolu, MSBuild Yapılandırılmış Günlük Görüntüleyicisi'nde "Çakışma oldu" araması yapmaktır. Hangi başvuruların söz konusu derlemenin hangi sürümlerine ihtiyaç duyduğu hakkında ayrıntılı bilgiler gösterir.