Aracılığıyla paylaş


Aralıklı derleme hatalarını düzeltme

Her seferinde gerçekleşmeyen derleme hatalarıyla ilgilenmek sinir bozucu bir deneyimdir. Bu makale, kök nedeni belirlemenize ve derlemelerinizin her seferinde tutarlı bir şekilde çalışması için aralıklı derleme hatalarını düzeltmenizi sağlayacak değişiklikler yapmanıza yardımcı olur.

MSBuild, farklı CPU çekirdeklerinde farklı çalışan düğümü işlemleri çalıştırarak paralel derlemeleri destekler. Genellikle paralel olarak oluşturmanın önemli performans avantajları olsa da, bunu yapmak birden çok işlem aynı anda aynı kaynağı kullanmaya çalıştığında oluşan hata riskini de ortaya çıkarabilir. Bu durum bir tür yarış durumudur. Bir yarış durumu, derlemeden derlemeye farklı davranışlar gösterebilir. Örneğin, bir işlem farklı sürelerle diğerinin önünde veya gerisinde olabilir.

Dosya G/Ç çekişmesinden kaynaklanan hata iletileri her zaman bir işletim sistemi dosyası G/Ç hatası içerir, ancak dosya G/Ç hatası oluştuğunda derlemede neler olduğuna bağlı olarak farklı MSBuild hata kodları olabilir. Bazı örnekler Windows platformunda aşağıdaki gibi görünebilir:

error MSB3677: Unable to move file "source" to "dest".
Cannot create a file when that file already exists. [{project file}] 
The process cannot access the file 'file' because it is being used by another process.

Belirli bir projenin birden fazla özellik ayarı bileşimiyle oluşturulması istendiğinde dosya çekişmesi yarışı oluşabilir. MSBuild genellikle, çıkışın da farklı olması durumunda özellik ayarları farklı olduğunda başvuruda bulunan bir proje için ayrı bir derleme yapar. Eşzamanlı olarak çalışan derlemelerin zamanlamasına bağlı olarak, bir dosya aynı konumda zaten varsa taşıma veya kopyalama işlemleri başarısız olabilir veya hedef dosya başka bir MSBuild işlemi tarafından kullanıldığından başarısız olabilir. Ayrıca, başka bir MSBuild işlemi aynı dosyayı okuyor veya yazıyorsa dosya okuma işlemleri başarısız olabilir.

Derleme dosyası çekişmesi sorunlarının çoğunu, nedenini anlayıp proje dosyalarında uygun değişiklikleri yaparak kalıcı olarak düzeltebilirsiniz, ancak bunun nedeni yalnızca kendi kodunuz içindeyse. Yarış koşulları sdk kodundaki hatalardan da kaynaklanabilir. Bu durumda sorunun ilgili SDK sahipleri tarafından bildirilmesi ve araştırılması gerekir.

Derleme yarış koşullarının nedenleri

Bu bölümde yarış koşullarına yol açabilecek farklı sorun türleri açıklanmaktadır. Sonraki bölüm olan Yarış koşullarını tanılama ve düzeltme, bu sorunları çözmek için yapılması gerekenleri açıklar.

Tutarsız ProjectReference özellik ayarları

Aynı projenin farklı derlemeleri birçok derleme işleminin normal bir parçasıdır; bunlar, MSBuild birden fazla ayar bileşimi için çıkış oluştururken oluşur. Örneğin, bir çözüm birden çok hedef çerçeveye (ve net7gibinet472) veya birden çok hedef platform mimarisine (ve x64gibiArm64) sahip olabilir. Bu derleme gereksinimi, her çıkış bileşimi için farklı bir çıkış klasörü belirtilerek karşılanır. Bu şekilde, Arm64 net472 bir derlemenin sürümü diğer birleşimlerden farklı bir klasöre çıkar ve çakışma olmaz. Varsayılan SDK ayarları burada bahsedilen örnekleri zaten işler, ancak bazen birden çok ayar bileşiminin ortaya çıkması o kadar belirgin değildir ve araştırılması gerekir.

ProjectReference özellikleri genel özelliklerle çakışıyor

Veya seçeneğiyle /p /property komut satırında bir özellik ayarladığınızda genel özellikler, başvurulan proje derlemeleri için örtük olarak kullanılır. Ancak, veya GlobalPropertiesToRemovekullanarakRemoveGlobalProperties, belirli bir proje başvurusu için genel özellik ayarlarının bir kısmını veya tümünü atlayabilirsiniz; bu nedenle, bu özellikler tutarlı bir şekilde kullanılmazsa, başvuruda bulunılan bir projenin birden fazla sürümünün genel özellik kümesiyle oluşturulduğu ve başka bir sürümünün ayarlanmamış veya farklı bir değere sahip olduğu bir durumla karşınıza çıkar.

Paketleme istemeden proje derlemelerini tetikler

Derlemeniz daha önce derlenmiş projelerin çıkışını paketlerse, derleme mantığınız oluşturulduklarında kullanılan özgün projelerden farklı özellik ayarları belirttiğinde bir yarış durumuyla karşılaşabilirsiniz. Bu durumda, MSBuild normalde özelliklerdeki uyuşmazlık nedeniyle bu projelerin yeniden oluşturulmasını tetikler. Bu durum yarış koşullarına yol açabilir. Paketlenen projelerin hiçbir zaman derlenmemesi için paketleme projesinde olarak ayarlamayı BuildProjectReferences false göz önünde bulundurun. Bu, paketleme derlemesinin yalnızca proje derlemeleri daha önce yapıldığında ve güncel olduğunda istenmesi gerektiği anlamına gelir.

Yarış koşullarını tanılama ve düzeltme

Derlemeniz tarafından oluşturulan dosyalar için taşıma işlemleri, kopyalama işlemleri veya dosya yazma işlemleri zaman zaman başarısız olduğunda bir yarış durumu hatasından şüphelenmelisiniz.

Sorunu çözme yaklaşımı istenen sonuca bağlıdır. Oluşturulan projenin iki farklı sürümüne gerçekten ihtiyacınız var mı? Öyleyse, çıkış klasörünü iki farklı özellik yapılandırması için farklı hale getirin. Aksi takdirde, her başvuru için aynı özelliklerin ayarlandığından emin olmak için öğeleri değiştirebilirsiniz ProjectReference .

Yarış durumunu tanılamak ve düzeltmek için aşağıdaki adımları izleyin.

  1. Aynı makinedeki Visual Studio hata ayıklayıcısı oturumu gibi bu dosyaları kullanan başka bir program çalıştırmadığınızdan denetleyin.

  2. MSBuild /m:1 seçeneğiyle derlemeleri çalıştırırsanız sorunun giderilip gidermediğini öğrenin. Bkz. MSBuild komut satırı başvurusu. Bu, MSBuild'e derlemeler için kullanılacak düğüm sayısını bildiren komut satırı seçeneğidir. 1 olarak ayarlanırsa, derlemeler seri olarak devam eder ve yarış durumu gerçekleşemez. Seçeneğini kullanmak /m:1 , yarış durumundan kaçınmak için kullanabileceğiniz bir geçici çözümdür, ancak uzun vadeli bir çözüm değildir. Derleme çıkışınız yine de birden çok kez oluşturulur ve olası farklar vardır ve bu durum overbuild olarak adlandırılan bir hata koşuludur. Ayrıca, derlemeyi seri olarak oluşturmak, derlemeyi tamamlamak için gereken süreyi önemli ölçüde artırır. Derleme yalnızca paralel derleme etkinleştirildiğinde aralıklı dosya G/Ç hatasını gösteriyorsa (işlemci sayısı 1'den büyükse), bu bir derleme yarış durumudur.

  3. Günlük oluşturma. Veya daha büyük ayrıntı Normal düzeyine sahip bir derleme çalıştırın (örneğin, komut satırı seçeneğini -verbosity:Normalkullanın). Yarış durumuyla ilgili sorunları gidermek için bir ikili günlük oluşturmanız (veya seçeneğini kullanın/bl) ve bunu Yapılandırılmış Günlük Görüntüleyicisi ile görüntülemeniz önerilir./binlog Bir yarış durumunu tanılamak için yararlı bir günlük almak için, hatayı oluşturan çıkışın erişildiği birden çok yeri yine de bulabildiğinizden, günlüğün başarısız bir çalıştırmadan olması gerekmez.

  4. Bu çalıştırmanın başarısız olup olmadığına bakılmaksızın, günlüğü (veya .binlog dosyayı) açın ve hatayı tetikleyen dosyanın dosya adını arayın ve dosyanın kullanıldığı tüm yerleri bulun.

    Aşağıdaki ekran görüntüsünde, Örnekte çözümü oluşturarak üretilen günlüğü görüntüleyen Yapılandırılmış Günlük Görüntüleyicisi gösterilmektedir. Gösterilenler, bir hata iletisinde bahsedilen net5.0\Base.dll dosyasının arama sonuçlarıdır. Aynı çıkış dosyası, arama sonuçlarında görevin iki katı olarak OutputAssembly Csc gösterilir ve birden çok kez derlendiğini gösterir. Yapılandırılmış Günlük Görüntüleyicisi'nde arama sonuçlarını gösteren ekran görüntüsü.

  5. Bu projenin derlemesinin her örneği için geçerli olan özellik ayarlarını not edin. Yapılandırılmış Günlük Görüntüleyicisi, her proje derlemesinde geçerli olan tüm özellik ayarlarını listeleyen bir Özellikler düğümü olduğundan bunu kolaylaştırır. Metin günlüğü kullanıyorsanız, ayrıntı ayarı Normal veya daha büyük olduğunda derleme için ayarlanan özellikler metin olarak çıkış yapar. Başarısız çıkışı oluşturan projenin her derlemesinin özellik listelerini karşılaştırın. Sorun aslında bir yarış durumuysa, bir fark görmeniz gerekir.

    Aşağıdaki ekran görüntüsünde, Özellikler düğümü bir proje derlemesi için genişletilmiş olan Yapılandırılmış Günlük Görüntüleyicisi gösterilmektedir. Bu derlemenin ProjectReferences başka bir projenin düğümü altında olduğuna dikkat edin; bu da bu derlemenin başka bir projedeki bir ProjectReference öğe tarafından tetiklendiği anlamına gelir. Ağaçta düğümleri izlerseniz, hangi projeye başvurdu olduğunu görebilirsiniz.

    Bir proje derlemesinin özelliklerini gösteren Yapılandırılmış Günlük Görüntüleyicisi'nin ekran görüntüsü.

    Listeyi aynı projenin diğer derlemesi ile karşılaştırdığınızda eksik olduğunu SpecialMode görebilirsiniz. Bu derleme üst düzey bir derlemedir; başka bir proje tarafından başvurulmadığı için çözümün kendisinde olduğu için oluşturulmuş olduğu anlamına gelir.

    Aynı proje için farklı özellik kümesini gösteren ekran görüntüsü.

  6. Özniteliğinin bu projeyi belirttiği proje Include dosyalarını ProjectReference arayın. , SetPlatformAdditionalPropertiesSetTargetFrameworkRemoveGlobalPropertiesveya GlobalPropertiesToRemovemeta verilerinden SetConfigurationherhangi birini arayın. Çözüm genelindeki farklı ProjectReference öğeler arasındaki bu meta veriler için ayarlanan değerlerdeki farkları denetleyin. Örnekte, sorunun kaynağı tutarsız AdditionalProperties meta veri ayarıdır (bir yerde, ancak diğerinde değil).

  7. Farklı özellik ayarlarının anlamını ve bunların derleme çıkışını önemli ölçüde etkileyip etkilemeyeceğini göz önünde bulundurun. Özellik ayarı farklılıkları anlamlıysa ve çıkışın ayrı olması amaçlanıyorsa düzeltme, .NET SDK'sının platform, yapılandırma (örneğin, Hata Ayıklama veya Yayın) veya hedef çerçeve için yaptığı gibi ayarın her varyasyonu için farklı bir klasör kullanmaktır. Özellik ayarı farkı istemeden veya önemsizse, özelliklerdeki farkı ortadan kaldırmak için proje kodunu değiştirmenin bir yolunu bulmayı deneyin. Örnekte bu, middle2.csproj dosyasına meta veriler ProjectReference eklenerek AdditionalProperties="SpecialMode=true" veya Middle1.csproj dosyasından AdditionalProperties meta veriler kaldırılarak gerçekleştirilebilir. Uygun değişiklik uygulamanızın, hizmetinizin veya hedefinizin belirli gereksinimlerine bağlıdır.

  8. Hata denetiminizde olmayan bir SDK'daysa, sorunu SDK sahibine bildirin.

Örnek

Deseni gösteren basit bir durum burada sunulmuştur. Bir ön uç istemcisi (App), iki sınıf kitaplığı (Middle1 ve ) ve Middle2iki sınıf kitaplığı tarafından başvurulan bir kitaplık (Base ) olmak üzere birkaç proje içeren bir çözümünüz olduğunu varsayalım.

Aşağıdaki kod bölümlerindeki proje dosyalarının tümü tek bir çözümün parçasıdır. Bu proje koleksiyonu, biri ile SpecialMode=true diğeri olmadan iki farklı derlemesine Baseneden olur. Base.dll çıkışına başvuracak aralıklı bir hata oluşabilir. Bazen "başka bir işlem tarafından kullanıldığından Base.dll " yazılamayacak bir hata alabilirsiniz.

<!-- Base.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <ItemGroup>
    <ProjectReference Include="..\Base\Base.csproj" />
  </ItemGroup>

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>
<!-- Middle1.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <ItemGroup>
    <ProjectReference Include="..\Base\Base.csproj" AdditionalProperties="SpecialMode=true" />
  </ItemGroup>

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>
<!-- Middle2.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <ItemGroup>
    <ProjectReference Include="..\Base\Base.csproj" />
  </ItemGroup>

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>
<!-- App.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <ItemGroup>
    <ProjectReference Include="..\Middle1\Middle1.csproj" />
    <ProjectReference Include="..\Middle2\Middle2.csproj" />
  </ItemGroup>

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

İstenen davranış kullanmaksaSpecialMode, uygun düzeltme Middle2.csproj dosyasına aynı AdditionalProperties meta veri değerini ProjectReference eklemektir:

<!-- Middle2.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <ItemGroup>
    <ProjectReference Include="..\Base\Base.csproj" AdditionalProperties="SpecialMode=true" />
  </ItemGroup>

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

Derleme sorunu, amacına uygunsa, AdditionalProperties meta verileri Middle1.csproj dosyasından kaldırılarak da düzeltilebilir.