Microsoft, döngüsel başvuruları olan derlemeleri nasıl yarattı?


107

.NET BCL'de şunlar arasında döngüsel başvurular vardır:

  • System.dll ve System.Xml.dll
  • System.dll ve System.Configuration.dll
  • System.Xml.dll ve System.Configuration.dll

İşte ne demek istediğimi gösteren .NET Reflector'dan bir ekran görüntüsü:

görüntü açıklamasını buraya girin

Microsoft'un bu derlemeleri nasıl yarattığı benim için bir muamma. Buna izin vermek için özel bir derleme işlemi gerekli mi? Burada ilginç bir şeyler olduğunu hayal ediyorum.


2
Çok güzel soru. Aslında bunu incelemek için hiç zaman ayırmadım ama cevabı bilmek merak ediyorum. Nitekim, Dykam mantıklı bir çözüm sunmuş gibi görünüyor.
Noldorin

3
hepsi birbirini gerektiriyorsa neden bu dll'ler tek bir dll'de birleştirilmiyor? bunun pratik bir sebebi var mı?
Andreas Petersson

1
İlginç soru ... Eric Lippert'in buna cevabını bilmek istiyorum! Andreas söylediği gibi, ben ... aynı mecliste her şeyi koymadı neden merak
Thomas Levesque

Bir montajın güncellenmesi gerekiyorsa, diğerlerine dokunmaları gerekmeyecek. Görmemin tek nedeni bu. Yine de ilginç bir soru
Atmocreations

2
Şu sunuya bir göz atın (asmmeta dosyaları): msakademik.net/academicdays2005/Serge_Lidin.ppt
Mehrdad Afshari

Yanıtlar:


58

Mono Projesinin bunu nasıl yaptığını sadece söyleyebilirim. Teorem bir kod karmaşası verse de oldukça basittir.

Önce System.Configuration.dll dosyasını, System.Xml.dll başvurusuna ihtiyaç duymadan derlerler. Bundan sonra, System.Xml.dll dosyasını normal şekilde derlerler. Şimdi sihir geliyor. System.configuration.dll dosyasını, System.Xml.dll başvurusuna ihtiyaç duyan kısımla yeniden derlerler. Şimdi dairesel referansla başarılı bir derleme var.

Kısacası:

  • A, B'ye ihtiyaç duyan kod ve B'ye referans olmadan derlenir.
  • B derlendi.
  • A yeniden derlendi.

1
Visual Studio tarafından engellenir, ancak doğrudan komut satırı derleyicisi (csc.exe) kullanılarak yapılabilir. Cevabımı gör.
Alfred Myers

14
Biliyorum. Mono'nun ana oluşturma sistemi Visual Studio değildir. Sanırım Microsofts da değil.
Dykam

35

RBarryYoung ve Dykam bir şeyin peşindeler. Microsoft, derlemeleri demonte etmek, tüm dahili / özel öğeleri ve yöntem gövdelerini çıkarmak ve IL'yi yeniden (ILASM kullanarak) 'susuz derleme' veya meta veri derlemesi olarak adlandırılan şekilde yeniden derlemek için ILDASM kullanan dahili araç kullanır. Bu, derlemenin genel arabirimi her değiştirildiğinde yapılır.

Derleme sırasında, gerçek olanlar yerine meta veri derlemeleri kullanılır. Bu şekilde döngü bozulur.


1
İlginç cevap, bağlantınız var mı?
Henk Holterman

Araca harici referans bulmaya çalışıyorum. Microsoft dışında yayınlandığını sanmıyorum, ancak konsept basit: disassemble-strip internalals-reassemble.
Srdjan Jovcic

Kabul edildi - ilginç cevap. Bunu destekleyecek bazı bağlantılar iyi olurdu.
Drew Noakes

Evet, gerçekten de böyle yapılır (kişisel deneyimlerden).
Pavel Minaev

1
Oluşturma sonrasına kadar güçlü bir şekilde imzalanmazlar (gecikme imzalanırlar), bu nedenle dehidrate montajlar imzalanmaz.
Srdjan Jovcic

26

Dykam'ın tarif ettiği şekilde yapılabilir ancak Visual Studio bunu yapmanızı engeller.

Doğrudan csc.exe komut satırı derleyicisini kullanmanız gerekecek.

  1. csc / target: kitaplık ClassA.cs

  2. csc / target: kitaplık ClassB.cs /reference:ClassA.dll

  3. csc / target: kitaplık ClassA.cs ClassC.cs /reference:ClassB.dll


//ClassA.cs
namespace CircularA {
    public class ClassA {
    }
}


//ClassB.cs
using CircularA;
namespace CircularB {
    public class ClassB : ClassA  {
    }
}


//ClassC.cs
namespace CircularA {
    class ClassC : ClassB {
    }
}

Bunu Visual Studio'da da yapabilirsiniz, çok zor olsa da, temel yol # if'leri kullanmak ve referansı üçüncü adımda tersine çevirerek çözüm gezginini kullanarak kaldırmaktır. Düşündüğüm başka bir yol, aynı dosyaları ancak farklı referansları içeren üçüncü bir proje dosyası. Bu, inşa sırasını belirleyebildiğiniz gibi çalışır.
Dykam

Bildiğim kadarıyla burada test edemezsiniz.
Dykam

Bunu gerçekten görmek isterim. Burada denediğim kadarıyla, Referans Eklemeye çalıştığınız anda IDE sizi durdurur.
Alfred Myers

Biliyorum. Ancak bu referansa VE #if sembolüne sahip olmayan üçüncü bir proje ve birinci tarafından başvurulan ikinci proje tarafından referans alınacaktır. Döngü yok. Ancak üçüncüsü, ilkinin kodunu kullanır ve ilk montaj konumuna çıktı verir. bir montaj, aynı özelliklere sahip bir başkasıyla kolayca değiştirilebilir. Ancak güçlü isimlendirmenin bu yöntemde bir soruna neden olabileceğini düşünüyorum.
Dykam

Farklı bir yöntem olsa da, biraz Srdjan'ın cevabı gibi.
Dykam

18

Proje referanslarını kullanmadığınız sürece Visual Studio'da yapmak oldukça kolaydır ... Şunu deneyin:

  1. Açık görsel stüdyo
  2. 2 Sınıf Kitaplığı projesi "ClassLibrary1" ve "ClassLibrary2" oluşturun.
  3. İnşa etmek
  4. ClassLibrary1'den 3. adımda oluşturulan dll'ye göz atarak ClassLibrary2'ye bir referans ekleyin.
  5. ClassLibrary2'den 3. adımda oluşturulan dll'ye göz atarak ClassLibrary1'e bir başvuru ekleyin.
  6. Yeniden oluşturun (Not: Her iki projede de değişiklik yaparsanız, her iki referansı da "taze" yapmak için iki kez oluşturmanız gerekir)

Demek bunu böyle yapıyorsun. Ama cidden ... Bunu ASLA gerçek bir projede yapmayın! Eğer yaparsan, Noel Baba bu yıl sana hediye getirmeyecek.


1
Bunun tek istisnası 26-31 Aralık arasındaysa ve hediyelerin zaten güvence altına alınmış olması
Jesse Hufstetler

6

Sanırım bu, döngüsel olmayan bir dizi meclisle başlayarak ve daha sonra küçük meclisleri mantıksal olarak ilişkili gruplar halinde birleştirmek için ILMerge kullanılarak yapılabilir.


4

Bunu Windows'ta hiç yapmadım, ancak bunun pratik öncüleri olarak hizmet eden birçok derleme-bağlantı-rtl ortamında yaptım. Yaptığınız şey, önce çapraz referanslar olmadan "hedefler" saplama yapmak, ardından bağlantı oluşturmak, ardından döngüsel referansları eklemek ve ardından yeniden bağlamaktır. Bağlayıcılar genellikle döngüsel referansları veya takip zincirlerini umursamazlar, sadece her bir referansı kendi başına çözebilmeyi önemserler.

Yani, A ve B olmak üzere birbirini referans göstermesi gereken iki kütüphaneniz varsa, şuna benzer bir şey deneyin:

  1. A'yı herhangi bir başvuru olmadan B'ye bağlayın.
  2. Bağlantı B ile A'ya sayılı referanslarda
  3. Bağlantı A, referansları B'ye ekleyerek.

Dykam iyi bir noktaya işaret ediyor: Derleme yapıyor, .Net'e bağlanmıyor, ancak ilke aynı kalıyor: Dışa aktarılan giriş noktalarıyla çapraz referanslı kaynaklarınızı yapın, ancak biri hariç hepsinin diğerlerine kendi referansları var. dışarı. Onları böyle inşa edin. Ardından, dış referansları kaldırın ve yeniden oluşturun. Bu, herhangi bir özel araç olmadan bile çalışmalı, aslında, bu yaklaşım şimdiye kadar denediğim her işletim sisteminde çalıştı (yaklaşık 6 tanesi). Açıkçası otomatikleştiren bir şeyin büyük bir yardımı olacaktır.


teorem doğru. Ancak .Net dünyasında, bağlantı dinamik yapılır ve bir sorun değildir. Bu çözüme ihtiyaç duyulan derleme adımıdır.
Dykam

Sizi tekrar düzelttiğim için özür dilerim: P. Ancak derleme zamanında referanslama (bağlama), o belirli ECMA spesifikasyonundan türetilen her şey olan .Net dünyasında gerçekleşir. Böylece Mono, dotGnu ve .Net. Windows'un kendisi değil.
Dykam

1

Olası bir yaklaşım, ilk önce diğer derlemelere bağlı olmayan bir System.dll'yi derlemek için koşullu derlemeyi (#if) kullanmak, ardından diğer derlemeleri derlemek ve son olarak System.dll dosyasını Xml ve Yapılandırma.


1
Maalesef bu, bir meclise şartlı olarak atıfta bulunmanıza izin vermiyor (Keşke mümkün olsaydı, projelerimden birinde gerçekten yardımcı olurdu ...)
Thomas Levesque

1
Koşullu referanslar, .csproj dosyası düzenlenerek kolayca yapılabilir. <Reference> öğesine bir Koşul niteliği eklemeniz yeterlidir.
Daniel

0

Teknik olarak bunların hiç derlenmemiş ve elle monte edilmiş olması mümkündür. Sonuçta bunlar düşük seviyeli kütüphanelerdir.


Pek sayılmaz. İçinde çok düşük seviyeli şeyler yok, sadece basit. Düşük seviye olacağını düşündüren nedir? Çalışma zamanı ve corlib düşük seviyededir. Nispeten. Yine de düz C veya C ++, JIT'in düşük seviyeli şeyler içerdiğini düşündü.
Dykam
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.