1 puan yazan GN⁺ 2025-01-25 | 1 yorum | WhatsApp'ta paylaş
  • Wild, yinelemeli geliştirmede çok hızlı linkleme hedefleyen bir linker’dır; artımlı linkleme henüz uygulanmamış olsa da yalnızca artımsız linkleme ile bile hızlı durumdadır
  • Mevcut hızlı linker mold’un artımlı linkleme yapmaması ve bunu planlamaması, Wild’ın çıkış noktasıdır; Wild, artımlı linklemenin karmaşıklığını ele almak amacıyla Rust ile yazılmıştır
  • Şu anda desteklenen platformlar Linux üzerinde x86-64, ARM64, RISC-V, LoongArch64, PPC64LE’dir; statik binary’ler, static-PIE, dinamik linkli binary’ler, paylaşımlı nesneler, Rust proc-macro, debug bilgisi vb. desteklenir
  • GCC ve Clang’de mevcut linker gibi çağrılan bir drop-in replacement olarak kullanılabilir; Cargo, C/C++ build sistemleri ve CI için wild-action ile birlikte çalıştırılabilir
  • Artımlı linkleme, daha karmaşık linker script’leri, Mach-O ve Windows desteği henüz uygulanmamıştır; gerçekten linkleme yapıp yapmadığı, readelf veya strings ile binary içindeki Linker: Wild version... dizesi kontrol edilerek doğrulanmalıdır

Wild’ın hedefi ve konumu

  • Wild, yinelemeli geliştirmede çok hızlı linkleme hedefleyen bir linker’dır
  • Uzun vadeli plan artımlı linklemeyi uygulamaktır, ancak şu anda henüz uygulanmış değildir
  • Artımlı linkleme olmadan da artımsız linkleme performansının şimdiden hızlı olduğu belirtiliyor
  • mold zaten çok hızlı olsa da artımlı linkleme yapmaması ve yazarının artımlı linkleme planı olmadığını açıklaması, Wild’ın ayrı bir linker olarak geliştirilmesinin nedenidir
  • Wild Rust ile yazılmıştır ve artımlı linklemenin karmaşıklığının Rust ile yönetilebilmesi beklenmektedir

Kurulum yöntemi

  • Release tarball’ları releases page üzerinden indirilebilir; arşivi açıp wild binary’sini PATH içinde bulunan bir konuma kopyalamak yeterlidir
  • cargo-binstall varsa aşağıdaki komutla kurulabilir
cargo binstall wild-linker
  • Homebrew kurulum komutu şöyledir
brew install wild-linker/wild/wild
  • crates.io’daki en yeni release’i derlemek için aşağıdaki komut kullanılır
cargo install --locked wild-linker
  • Git’teki en yeni yayımlanmamış kodu kurmak için aşağıdaki komut kullanılır
cargo install --locked --bin wild --git https://github.com/wild-linker/wild.git wild-linker
  • Nixpkgs’teki kararlı Wild sürümü pkgs.useWildLinker pkgs.stdenv üzerinden kullanılabilir
  • En yeni kararsız Git revizyonu için nix/nix.md belgesine bakılmalıdır

Varsayılan linker olarak kullanma yöntemi

  • Wild, drop-in replacement olarak tasarlanmıştır ve GCC veya Clang’in çağırdığı şekilde kullanılabilir
  • Seçenekler şunlardır
    • Yalnızca Clang’e özel --ld-path=wild seçeneği
    • GCC 16.1 ve üzeri ile Clang’de -fuse-ld=wild
      • Clang için ld.wild binary’si veya sembolik link gerekir
    • Genel olarak desteklenen -B <path>
      • <path>, wild’ı işaret eden ld dosyasının bulunduğu dizindir
  • Rust ve Cargo

    • ~/.cargo/config.toml içinde Clang ve --ld-path=wild birlikte kullanılabilir
    [target.x86_64-unknown-linux-gnu]
    linker = "clang"
    rustflags = ["-Clink-arg=--ld-path=wild"]
    
    • Alternatif olarak -fuse-ld=wild kullanılabilir
    [target.x86_64-unknown-linux-gnu]
    
    # linker = "clang" # Uncomment this line if your GCC is older than version 16.
    rustflags = ["-Clink-arg=-fuse-ld=wild"]
    
  • C/C++ build sistemleri

    • autotools, CMake, meson gibi sistemlerde genellikle yalnızca LDFLAGS ayarı yeterlidir
    export LDFLAGS="${LDFLAGS} -fuse-ld=wild"
    
    • Eski GCC sürümlerinde, wild’ı işaret eden bir ld sembolik linki oluşturup ilgili dizini -B ile geçirmek mümkündür
    ln -s /usr/bin/wild /tmp/ld
    
    export CFLAGS="${CFLAGS} -B/tmp"
    export CXXFLAGS="${CXXFLAGS} -B/tmp"
    export LDFLAGS="${LDFLAGS} -B/tmp"
    
    • Bu tür build sistemleri karmaşık olabileceğinden, Wild’ın gerçekten binary linkleme için kullanılıp kullanılmadığını readelf ile kontrol etme yöntemi önerilir
  • Illumos için Cargo ayarı

    • Illumos’ta Clang’in mutlak yolu belirtilmeli, Wild da mutlak yol olarak geçirilmelidir
    • Wild’ın mutlak yolu verilmezse sessizce GNU ld veya Sun ld’ye devredebilir
    [target.x86_64-unknown-illumos]
    
    # Absolute path to clang - on OmniOS this is likely something like /opt/ooce/bin/clang.
    linker = "/usr/bin/clang"
    
    rustflags = [
    
    # Will silently delegate to GNU ld or Sun ld unless the absolute path to Wild is provided.
        "-Clink-arg=-fuse-ld=/absolute/path/to/wild"
    ]
    

Destek durumu ve desteklenmeyenler

  • Şu anda desteklenen platformlar ve mimariler şunlardır
    • Linux üzerinde x86-64

    • Linux üzerinde ARM64

    • Linux üzerinde RISC-V(riscv64gc)

      • Linux üzerinde LoongArch64
      • İlk destek aşamasındadır
      • Linux üzerinde PPC64LE
      • İlk destek aşamasındadır
      • Çalışan özellikler aşağıdaki gibidir, ancak hata bulunabileceği notu düşülmüştür
      • Statik linklenmiş non-relocatable binary çıktısı
      • Statik linklenmiş position-independent binary, yani static-PIE çıktısı
      • Dinamik linkli binary çıktısı
      • Paylaşımlı nesne .so dosyası çıktısı
      • Wild ile linklenmiş Rust proc-macro
      • crates.io’dan indirme sıralamasında üstlerde olan çoğu crate’in testlerinden geçme
      • Debug bilgisi
      • GNU jobserver desteği
      • Kısmi linker script desteği
      • Ayrıntılar için linker script support matrix sayfasına bakılır
      • Linker plugin LTO
      • known issues bulunur
      • Henüz uygulanmamış büyük maddeler, mevcut önceliğe yakın sırayla şöyledir
    • Artımlı linkleme

      • Daha karmaşık linker script’leri
      • Mach-O desteği
      • Windows desteği

Wild kullanılıp kullanılmadığını doğrulama

  • readelf, binutils paketinden kurulabilir; aşağıdaki komutla .comment bölümündeki dizeler kontrol edilir
readelf --string-dump .comment my-executable
  • Aşağıdaki gibi bir satır varsa binary Wild ile linklenmiştir
Linker: Wild version 0.1.0
  • strings de binutils paketinden kullanılabilir ve aşağıdaki komutla da kontrol edilebilir
strings my-executable | grep 'Linker:'

Benchmark’lar ve test hedefleri

  • Wild’ın hedefi, nihayetinde artımlı linkleme ile çok hızlı bir linker olmaktır
  • Artımsız linkleme ile artımlı linkleme etkinleştirildiğinde yapılan ilk linklemenin de mümkün olduğunca hızlı olması hedeflenir
  • Tüm benchmark’lar, çıktının tmpfs’e yazıldığı koşullarda çalıştırılır
  • Benchmark çalıştırma yöntemi BENCHMARKING.md içinde özetlenmiştir
  • Benchmark hedef sistemleri şunlardır
  • Örnek benchmark’lar arasında Chromium linkleme süresi ve bellek kullanımı, librustc-driver linkleme süresi, Wild’ın kendi linkleme süresi ve Raspberry Pi 5’te rust-analyzer linkleme süresi yer alır

Rust kodu linkleme örneği ve proje bilgileri

  • cargo test içinde Wild kullanarak crate derleme ve test etme örneği şöyledir
  • Bu komut ripgrep, serde, tokio, rand, bitflags gibi bazı popüler crate’lerde başarıyla çalıştırılmıştır
  • wild binary’sinin PATH içinde olması gerekir; GCC rastgele linker kullanımına izin vermediği için Clang kurulumu gerekir
RUSTFLAGS="-Clinker=clang -Clink-args=--ld-path=wild" cargo test
  • ld.wild sembolik linki wild’ı işaret ediyorsa aşağıdaki yöntem de mümkündür
RUSTFLAGS="-Clinker=clang -Clink-args=-fuse-ld=wild" cargo test
  • CI’da Rust kodu linkeri olarak Wild kullanmak için wild-action sayfasına bakılır
  • Katkı bilgileri CONTRIBUTING.md, üst seviye tasarım özeti ise DESIGN.md içindedir
  • Wild ile ilgili sohbetler Zulip server üzerinde yapılır
  • David’in blogunda Wild linker’ın çeşitli yönlerini ele alan birçok yazı bulunur
  • Lisans, Apache License 2.0 veya MIT license arasından seçilebilir

1 yorum

 
GN⁺ 2025-01-25
Hacker News görüşleri
  • mold AGPL'den MIT'ye yeniden lisanslandıktan sonra (mold 2.0 sürümünün bir parçası), dünya genelinde bir başka hızlı linker yapma ihtiyacının epey azaldığını düşündüğüm için böyle bir projenin çıkacağını beklemiyordum.
    Üstelik bazı durumlarda şimdiden mold'dan 2 kat hızlı olması daha da beklenmedik; nasıl gelişeceğini izleyeceğim ve yazarına başarılar diliyorum.

    • mold'un artımlı linkleme yapma niyeti yok; bu yüzden başka bir linker'ın var olması için güçlü bir neden var.
      Microsoft'un linker'ı onlarca yıldır varsayılan olarak artımlı linkleme yapıyor; Linux'ta hâlâ üretime hazır bir artımlı linker olmaması biraz utandırıcı.
    • Bir linker'da AGPL ile MIT farkı neden önemli?
    • mold'un Windows desteğinin ne durumda olduğunu bilmiyorum.
      GitHub issue'larına bakınca yazarın başta desteklemeye çalıştığı, sonra Windows desteğini sold linker'a taşıdığı görülüyor; ama sold yakın zamanda arşivlendiğine göre sonuçta Windows desteği yok mu, yoksa akışı yanlış mı anladım, kafam karıştı.
    • Yanlış kullanıyor olabilirim ama muhtemelen kullanılması gereken LTO'yu kullanınca mold hiç de daha hızlı değil.
    • Bir dakika, GPL olan bir şeyi MIT olarak yeniden lisanslamak mümkün mü?
  • Daha önce bakmıştım ama henüz üretimde kullanılmaya hazır olup olmadığından emin değilim.
    README'ye göre hazır değil gibi, bu yüzden hâlâ mold kullanıyorum.
    macOS kullanıcısıysanız Apple 1-2 yıl kadar önce yeni bir linker çıkardı; bu yüzden mold'un yazarı macOS sürümü üzerindeki çalışmayı bıraktı.
    Rust'ta kullanmak için config.toml dosyasına şunu koyabilirsiniz:

    [target.aarch64-apple-darwin]

    rustflags = [

    "-C",

    "link-arg=-fuse-ld=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",

    "-C",

    "link-arg=-ld_new",

    ]

    • Yazar, bunun henüz üretimde kullanılmaması gerektiğini oldukça net söylüyor.
    • mold'u da üretimde değil, geliştirme amaçlı kullanıyorum.
    • Günümüzde yeni linker zaten varsayılan değil mi? Bunu eklemenin etkisi olup olmadığından pek emin değilim.
    • Sequioa'da da bu konumun doğru olduğunu doğrulayabilir misiniz?
      Komut satırı araçlarını kurdum ama yalnızca /usr/bin/ld ve /usr/bin/ld-classic var.
  • C/C++ derleyicilerinin linkleme denen ara aşamayı ortadan kaldırıp tüm programı tek bir birim olarak derlemesi ilginç olurdu.
    Derleyici baştan tüm programı görebilseydi LTO'nun kendisine gerek kalmazdı.
    Artımlı derlemeler için bazı derleme çıktılarının saklanması gerekir, ama nesne dosyası biçiminde değil; doğru parçaların değiştirilebilmesi için üretilen kodun kaynağını ve bağımlılıklarını bilen metadata gerekir.
    Günümüzde harici kütüphaneler çoğunlukla dinamik linklendiği için kaynaktan derlenmeleri gerekmez ve linker'ı kaldırmak özel bağımlılıklar açısından da sorun yaratmaz.
    Yine de yetmezse derleyici nesne dosyalarını da kabul ederek, ikili dosyaya statik linklenmesi gereken eski ya da özel durumları ele alabilir.

    • SQLite3 her şeyi birleştirip tek bir derleme birimi hâline getiriyor.
      Muhtemelen düşündüğümüzden çok daha fazla kişi bu yöntemi zaten kullanıyor.

      https://sqlite.org/amalgamation.html

  • Hızlı linker'lara ilgi Rust'ın benimsenmesi ve popülerliği nedeniyle ciddi ölçüde arttı.
    Orta büyüklükte statik linklenmiş bir Rust ikili dosyası bile release modunda derlemenin link aşamasında birkaç dakika sürebiliyor (mold kullanıldığında).
    Bu yalnızca Rust'a özgü bir sorun değil; daha çok katı statik linkleme, LLVM'in sunduğu LTO ve BOLT gibi gelişmiş link zamanı optimizasyonları ve Rust topluluğunun derleme sürelerinden şikâyetlerinin birleşimi.
    Rust, LLVM ile güçlü ilişkisi ve fiilî bağımlılığı nedeniyle LLVM'in link zamanı sihirlerinin en yaygın benimsendiği dil hâline geldi; C++'ta da aynı sorun yaşanabilir ama o durumda bunun dilden çok araç zincirinin suçu sayılması daha olası.
    wild'ı bir optimize edici artımlı linker olma ihtimali nedeniyle bir süredir izliyordum; ama açıkçası gerçekten artımlı linkleme yapabilene kadar denemek için hiçbir motivasyonum yok.

    • C++'ta bazı derleyiciler artımlı derleme ve artımlı linklemeyi desteklediği için Rust'tan çok daha hızlı derlenebiliyor.
      Ayrıca C/C++ ekosisteminde ikili kütüphaneleri kabul eden bir kültür var; bu yüzden bir depoyu klonladığınızda ya da geliştirme dalını değiştirdiğinizde tüm dünyayı yeniden derlemek yerine çoğu zaman yalnızca kendi uygulamanızı derlemeniz yeterli oluyor.
    • Bu sorunu Wasm ile çözdüm.
      Dış uygulama kabuğunun Wasm iş mantığını çağırmasını sağlarsanız yalnızca iç mantığı yeniden derlemeniz gerekir; dış uygulama kabuğunun yeniden başlatılması bile gerekmez.
  • 2008: GNU ld'den daha hızlı olacak şekilde yapılmış yeni linker gold

    2015 civarı: gold'dan en az 2 kat hızlı, drop-in yedek linker lld

    2021: lld'den birkaç kat hızlı yeni linker mold

    2025: yeni linker wild...

    • Pek dile getirilmiyor ama bunların hepsi, gerçek programların kullandığı pek çok faydalı özelliği uygulamama pahasına mümkün oluyor.
    • Bunun olumsuz mu olumlu mu söylendiğini, yoksa kısa bir tarih özeti mi olduğunu bilmiyorum; ama linker'lardan hâlâ daha iyi performans çıkarılabildiği gerçeği oldukça cesaret verici.
    • gold, binutils 2.44.0'da kaldırılacak; yani resmen ölmüş sayılır.
    • Windows için henüz erken aşamada olsa da The RAD Linker da var.
  • Konuyla ilgili eski ama iyi bir kitap olarak John Levine'in Linkers and Loaders kitabı var.
    Aşağıdaki listedeki son kitap.

    https://www.johnlevine.com/books.phtml

    Birkaç yıl önce okumuştum; oldukça ilginçti ve bu alanın standart kitabı sayılır.
    Bağlantıda görüldüğü gibi başka popüler bilgisayar kitapları da yazmış.

  • Oldukça umut verici görünüyor.
    Baştan Rust ile yazılmış ve hedefi hızlı olup artımlı linklemeyi desteklemek.
    Rust'ta kullanmak için muhtemelen gcc'yi linker sürücüsü olarak kullanmak da mümkün olur.
    Projenin .cargo/config.toml dosyasına:

    [target.x86_64-unknown-linux-gnu]

rustflags = ["-C", "link-arg=-fuse-ld=wild"]

Yan konu ama Rust burada neden gcc ya da clang'e takılmak zorunda? Eksik bir özellik mi var?

  • Ne yazık ki gcc, -fuse-ld= bayrağıyla rastgele bir linker kabul etmiyor
    Kabul ettiği linker'lar yalnızca bfd, gold, lld ve mold
    gcc'nin wild'ı linker olarak çağırmasını sağlamak mümkün, ancak şu anda wild linker'ın bulunduğu bir dizin oluşturup ikili dosyanın ya da sembolik bağlantının adını "ld" olarak değiştirmek, ardından gcc'ye -B/path/to/directory/containing/wild vermek gerekiyor
    Rust'ın linker'ı doğrudan çağırmayıp linker'ı gcc ya da clang üzerinden çağırmasının nedeni, C derleyicisinin mevcut platformda libc ve C runtime'a linklemek için gereken linker bayraklarını bilmesidir
    Örneğin Scrt1.o, crti.o, crtbeginS.o, crtendS.o, crtn.o gibi şeyler

  • Çünkü Rust derleyicisi makine kodu değil IR bytecode üretiyor

  • Merak ediyorum; artımsız durumda bunun mold'dan daha hızlı olabilmesinin teorik nedeni ne olabilir?
    “Rust olduğu için” birçok şey için makul bir açıklama, ama beklenen performans avantajını açıklamıyor
    “Rust'ın kullanmayı kolaylaştırdığı, düşük zorlukta paralelleştirme fırsatları olduğu için” ise ilginç olurdu, ama bu açıkça belirtilmiş ya da ima edilmiş değil

    • Kesin bilmiyorum; bunun başlıca nedeni Mold kod tabanına aşina olmamam
      Bir ipucu, Mold'un daha hızlı ayırıcı mimalloc kullanınca yaklaşık %10 hızlandığını duyduğum
      Wild'da mimalloc'u denedim ama ölçülebilir bir hız artışı olmadı
      Bu, Mold'un ayırıcıyı Wild'dan daha fazla kullandığını düşündürüyor; Wild'da ise heap allocation sayısını optimize etmeye kesinlikle uğraştım
      Genel olarak bunun tasarım kararlarındaki farklardan kaynaklandığını düşünüyorum
      Bunun Rust'la nasıl ilgili olabileceğine gelince: Wild'ı Rust'tan C ya da C++'a port etsek performansın neredeyse aynı olacağından eminim
      Ancak Rust'ta borrow checker sayesinde iyi olan kod kalıpları, C ya da C++'ta tuzak hâline gelebilir ve bakımı zorlaşabilir
      Eskiden C++ ile kod yazarken, küçük bir performans maliyetini kabul ederek bile daha savunmacı yazardım; Rust'ta ise derleyicinin arkamı kolladığını bildiğim için çok daha cesur yazabiliyorum
  • Tesadüf olmuş
    Bir saat önce üzerinde çalıştığım bir C projesinde wild, mold, ld performansını karşılaştırdım
    23 bin satır, 172 dosya; gcc+ld ile kullanıcı zamanı yaklaşık 23,4 saniye, gcc+mold 22,5 saniye, gcc+wild 21,8 saniye sürdü
    Bu yüzden iyi yapılandırılmış bir projede link süresinin o kadar büyük bir sorun olmayabileceğini düşünüyorum

    • Sıfırdan tam build yapıyormuşsunuz gibi geliyor
      Bu durumda zamanın çoğu linklemeye değil, kodun derlenmesine gider
      Hızlı linker'ın avantajı en çok tekrarlamalı geliştirme sırasında ortaya çıkar
      Yani kodda küçük bir değişiklik yapıp yeniden build ederek sonucu çalıştırdığınızda, derleyicinin yapacağı iş genelde çok azdır; ancak linkleme hâlâ baştan yapıldığı için baskın süre hâline gelmesi kolaydır
    • Link süresi küçük projelerde değil, Chrome gibi şeyleri build ederken önemlidir
    • Hızlı linker'lar genel olarak artımlı derleme durumlarında düzenleme döngüsünü kısaltmak için kullanışlıdır
    • ld.lld nasıl?
  • “Bu benchmark David Lattimore'un dizüstü bilgisayarında (2020 model System76 Lemur Pro) çalıştırıldı; 4 çekirdek (8 thread) ve 42GB RAM bulunuyor”

    https://news.ycombinator.com/item?id=33330499

    Bu arada wild'ın şişkin olduğunu söylemeye çalışmıyorum
    Bir sorun varsa, onunla geliştirilen yazılımlarda ve bu tür yazılımları kullanacak insanların bilgisayarlarında var

    • https://news.ycombinator.com/item?id=42896619

      “... RAM 16GB ve yükseltilemiyor...”

    • Yarı şaka olarak söylüyorum ama Rust ile kod yazan birinin zaten 32GB RAM'i vardır diye düşünüyorum
      Kendi adıma, dizüstü bilgisayarımı 64GB'a yükseltmek için kelimenin tam anlamıyla diğer her şeyden feragat etmem neredeyse harika bir karardı
      Neredeyse dememin nedeni, tüm bütçeyi RAM'e gömmek yerine hem RAM'e hem ekrana para harcamalıydım
      Tek dezavantajı, haftada bir açık sekmeleri temizleme işinin tüm akşamı alan bir işe dönüşmüş olması