1 पॉइंट द्वारा GN⁺ 2025-01-25 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Wild एक linker है जिसका लक्ष्य iterative development में बेहद तेज़ linking देना है। इसमें अभी incremental linking लागू नहीं है, लेकिन केवल non-incremental linking के साथ भी यह तेज़ स्थिति में है
  • मौजूदा तेज़ linker mold incremental linking नहीं करता और इसकी कोई योजना भी नहीं है—यही Wild का शुरुआती कारण है। Wild को Rust में लिखा गया है ताकि incremental linking की जटिलता को संभालने का लक्ष्य रखा जा सके
  • अभी समर्थित प्लेटफ़ॉर्म Linux पर x86-64, ARM64, RISC-V, LoongArch64, PPC64LE हैं। यह static binaries, static-PIE, dynamically linked binaries, shared objects, Rust proc-macro, debug information आदि को support करता है
  • इसे GCC·Clang में मौजूदा linker की तरह बुलाए जाने वाले drop-in replacement के रूप में इस्तेमाल किया जा सकता है, और Cargo, C/C++ build systems, CI के लिए wild-action के साथ जोड़ा जा सकता है
  • अभी incremental linking, अधिक जटिल linker script, Mach-O और Windows support लागू नहीं हैं। सच में link हुआ या नहीं, यह readelf या strings से binary में Linker: Wild version... string देखकर verify करना चाहिए

Wild का लक्ष्य और स्थिति

  • Wild एक linker है जिसका लक्ष्य iterative development में बेहद तेज़ linking देना है
  • दीर्घकालिक योजना incremental linking लागू करने की है, लेकिन फिलहाल यह अभी लागू नहीं है
  • बताया गया है कि incremental linking के बिना भी non-incremental linking performance पहले से तेज़ है
  • mold पहले से बहुत तेज़ है, लेकिन यह incremental linking नहीं करता, और लेखक ने कहा है कि incremental linking करने की योजना नहीं है—इसी वजह से Wild को अलग linker के रूप में बनाया गया
  • Wild Rust में लिखा गया है, और उम्मीद है कि incremental linking की जटिलता को Rust से संभाला जा सकेगा

इंस्टॉलेशन तरीका

  • release tarball releases page से लिया जा सकता है। उसे extract करके wild binary को PATH में मौजूद किसी location पर copy कर दें
  • अगर cargo-binstall है, तो इसे नीचे दिए command से install किया जा सकता है
cargo binstall wild-linker
  • Homebrew install command यह है
brew install wild-linker/wild/wild
  • crates.io की latest release build करने के लिए नीचे दिया command इस्तेमाल करें
cargo install --locked wild-linker
  • Git का latest unreleased code install करने के लिए नीचे दिया command इस्तेमाल करें
cargo install --locked --bin wild --git https://github.com/wild-linker/wild.git wild-linker
  • Nixpkgs का stable version Wild pkgs.useWildLinker pkgs.stdenv के जरिए इस्तेमाल किया जा सकता है
  • latest unstable Git revision के लिए nix/nix.md document देखें

default linker के रूप में इस्तेमाल करने का तरीका

  • Wild को drop-in replacement के रूप में design किया गया है और इसे GCC या Clang द्वारा call किए जाने वाले तरीके से इस्तेमाल किया जा सकता है
  • विकल्प ये हैं
    • सिर्फ Clang के लिए option --ld-path=wild
    • GCC 16.1 या उससे ऊपर और Clang में -fuse-ld=wild
      • Clang को ld.wild binary या symbolic link चाहिए
    • सामान्य तौर पर supported -B <path>
      • <path> वह directory है जिसमें wild की ओर इशारा करने वाला ld मौजूद हो
  • Rust और Cargo

    • ~/.cargo/config.toml में Clang और --ld-path=wild को साथ इस्तेमाल किया जा सकता है
    [target.x86_64-unknown-linux-gnu]
    linker = "clang"
    rustflags = ["-Clink-arg=--ld-path=wild"]
    
    • या -fuse-ld=wild इस्तेमाल किया जा सकता है
    [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 system

    • autotools, CMake, meson आदि में आमतौर पर केवल LDFLAGS setting ही पर्याप्त होती है
    export LDFLAGS="${LDFLAGS} -fuse-ld=wild"
    
    • पुराने GCC versions में wild की ओर इशारा करने वाला ld symbolic link बनाकर उस directory को -B से pass किया जा सकता है
    ln -s /usr/bin/wild /tmp/ld
    
    export CFLAGS="${CFLAGS} -B/tmp"
    export CXXFLAGS="${CXXFLAGS} -B/tmp"
    export LDFLAGS="${LDFLAGS} -B/tmp"
    
    • ऐसे build systems जटिल हो सकते हैं, इसलिए यह verify करने के लिए readelf इस्तेमाल करने की सलाह दी जाती है कि Wild सच में binary linking में इस्तेमाल हुआ या नहीं
  • Illumos के लिए Cargo settings

    • Illumos में Clang का absolute path specify करना होगा, और Wild को भी absolute path के रूप में pass करना होगा
    • अगर Wild का absolute path नहीं दिया गया, तो यह चुपचाप GNU ld या Sun ld को delegate कर सकता है
    [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"
    ]
    

support status और unsupported items

  • अभी supported platforms और architectures ये हैं
    • x86-64 on Linux

    • ARM64 on Linux

    • RISC-V(riscv64gc) on Linux

      • LoongArch64 on Linux
      • शुरुआती support स्थिति में है
      • PPC64LE on Linux
      • शुरुआती support स्थिति में है
      • काम करने वाली capabilities नीचे दी गई हैं, लेकिन caveat है कि bugs हो सकते हैं
      • statically linked non-relocatable binary output
      • statically linked position-independent binary, यानी static-PIE output
      • dynamically linked binary output
      • shared object .so file output
      • Wild से link किया गया Rust proc-macro
      • crates.io से सबसे ज़्यादा download होने वाले ज्यादातर crates के tests pass
      • debug information
      • GNU jobserver support
      • partial linker script support
      • details के लिए linker script support matrix देखें
      • Linker plugin LTO
      • known issues हैं
      • अभी लागू नहीं किए गए बड़े items, मौजूदा priority के लगभग क्रम में, ये हैं
    • incremental linking

      • अधिक जटिल linker script
      • Mach-O support
      • Windows support

Wild के इस्तेमाल की पुष्टि

  • readelf को binutils package से install किया जा सकता है, और नीचे दिए command से .comment section की strings देखी जाती हैं
readelf --string-dump .comment my-executable
  • अगर नीचे जैसी line हो, तो binary Wild से linked है
Linker: Wild version 0.1.0
  • strings भी binutils package से इस्तेमाल किया जा सकता है, और नीचे दिए command से भी verify किया जा सकता है
strings my-executable | grep 'Linker:'

benchmarks और test targets

  • Wild का लक्ष्य अंततः incremental linking के जरिए बेहद तेज़ linker बनना है
  • non-incremental linking और incremental linking enabled होने पर initial linking को भी जितना हो सके तेज़ बनाना इसका लक्ष्य है
  • सभी benchmarks tmpfs पर output करने की condition में run किए गए हैं
  • benchmark run करने का तरीका BENCHMARKING.md में व्यवस्थित है
  • benchmark target systems ये हैं
  • example benchmarks में Chromium link time और memory usage, librustc-driver link time, Wild का खुद का link time, और Raspberry Pi 5 पर rust-analyzer link time शामिल हैं

Rust code linking example और project information

  • cargo test में Wild का इस्तेमाल करके crate build और test करने का example नीचे है
  • यह command ripgrep, serde, tokio, rand, bitflags जैसे कुछ popular crates पर सफलतापूर्वक run हुआ
  • wild binary PATH में होनी चाहिए, और GCC arbitrary linker use करने की अनुमति नहीं देता, इसलिए Clang install होना जरूरी है
RUSTFLAGS="-Clinker=clang -Clink-args=--ld-path=wild" cargo test
  • अगर ld.wild symbolic link wild की ओर point करता है, तो नीचे वाला तरीका भी संभव है
RUSTFLAGS="-Clinker=clang -Clink-args=-fuse-ld=wild" cargo test
  • CI में Rust code linker के रूप में Wild इस्तेमाल करने के लिए wild-action देखें
  • contribution information CONTRIBUTING.md में है, और high-level design overview DESIGN.md में है
  • Wild से जुड़ी बातचीत Zulip server पर होती है
  • David के blog में Wild linker के कई पहलुओं पर लिखे गए बहुत से posts हैं
  • license Apache License 2.0 या MIT license में से चुना जा सकता है

1 टिप्पणियां

 
GN⁺ 2025-01-25
Hacker News की राय
  • mold को AGPL से MIT में relicense किए जाने के बाद (mold 2.0 रिलीज़ का हिस्सा), मुझे लगा था कि दुनिया भर में एक और तेज linker बनाने की ज़रूरत काफी कम हो गई है, इसलिए उम्मीद नहीं थी कि ऐसा कोई प्रोजेक्ट आएगा
    ऊपर से कुछ मामलों में यह पहले से ही mold से 2 गुना तेज है, यह और भी अप्रत्याशित है; देखूंगा यह कैसे आगे बढ़ता है, और लेखक को शुभकामनाएँ

    • mold की incremental linking करने की कोई योजना नहीं है, इसलिए दूसरे linker के मौजूद होने की बड़ी वजह है
      Microsoft का linker दशकों से default रूप से incremental linking करता आया है, लेकिन Linux पर अभी तक production-ready incremental linker नहीं है—यह थोड़ा शर्मनाक है
    • linker में AGPL और MIT का फर्क क्यों महत्वपूर्ण है?
    • mold के Windows support की स्थिति क्या है, मुझे नहीं पता
      GitHub issues देखकर लगता है कि लेखक ने पहले support करने की कोशिश की, फिर Windows support को sold linker में शिफ्ट कर दिया, लेकिन sold हाल में archive हो गया है; तो क्या आखिरकार Windows support नहीं है, या मैं flow गलत समझ रहा हूँ?
    • हो सकता है मैं गलत तरीके से इस्तेमाल कर रहा हूँ, लेकिन शायद जिस LTO का इस्तेमाल करना चाहिए, उसे इस्तेमाल करने पर mold बिल्कुल भी तेज नहीं है
    • ठहरिए, GPL वाली चीज़ को MIT में relicense करना संभव है?
  • पहले देखा था, लेकिन अभी भी पता नहीं कि यह production में इस्तेमाल करने के लिए तैयार है या नहीं
    README के हिसाब से तो नहीं लगता, इसलिए मैं अभी भी mold इस्तेमाल कर रहा हूँ
    अगर आप macOS user हैं, तो Apple ने लगभग 1–2 साल पहले नया linker निकाला था, और इसी वजह से mold के लेखक ने macOS version पर काम बंद कर दिया
    Rust में इस्तेमाल करने के लिए config.toml में इसे डालें

    [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",

    ]

    • लेखक काफी साफ कह रहा है कि इसे अभी production में इस्तेमाल नहीं करना चाहिए
    • mold भी production में नहीं, बल्कि development के लिए इस्तेमाल करता हूँ
    • क्या आजकल नया linker पहले से default नहीं है? यह जोड़ने से असर होता है या नहीं, पक्का नहीं
    • क्या कोई पुष्टि कर सकता है कि Sequioa में भी यह location सही है?
      मैंने command line tools install किए हैं, लेकिन सिर्फ /usr/bin/ld और /usr/bin/ld-classic हैं
  • अगर C/C++ compiler linking नाम के intermediate step को हटाकर पूरे program को एक unit की तरह build करे, तो यह नया और दिलचस्प होगा
    अगर compiler शुरुआत से ही पूरा program देख सके, तो LTO की जरूरत ही नहीं रहेगी
    incremental build के लिए कुछ build artifacts तो store करने होंगे, लेकिन object files के रूप में नहीं; ऐसे metadata की जरूरत होगी जिसे generated code के source और dependencies का पता हो, ताकि सही हिस्सों को ही replace किया जा सके
    आजकल external libraries आम तौर पर dynamically link होती हैं, इसलिए उन्हें source से build करने की जरूरत नहीं होती, और linker हटाने से private dependencies में भी समस्या नहीं होगी
    फिर भी अगर यह पर्याप्त न हो, तो compiler को object files भी accept करने दिया जा सकता है, ताकि ऐसे legacy या खास cases संभाले जा सकें जिन्हें binary में statically link करना जरूरी है

    • SQLite3 सब कुछ जोड़कर एक compilation unit बना देता है
      शायद जितने लोग सोचते हैं, उससे ज्यादा लोग पहले से ही यह तरीका इस्तेमाल कर रहे हैं

      https://sqlite.org/amalgamation.html

  • तेज linkers में दिलचस्पी Rust adoption और popularity की वजह से काफी बढ़ी है
    ठीक-ठाक आकार की statically linked Rust binary भी release mode compile के link stage में कई मिनट ले सकती है (mold इस्तेमाल करने पर भी)
    यह सिर्फ Rust की समस्या नहीं है; कुल मिलाकर strict static linking, LLVM द्वारा दिए गए LTO और BOLT जैसे advanced link-time optimizations, और Rust community की compile time को लेकर शिकायतें—इन सबका नतीजा है
    LLVM के साथ मजबूत रिश्ते और व्यवहार में उस पर dependency की वजह से, Rust वह भाषा बन गई है जहाँ LLVM का link-time जादू सबसे व्यापक रूप से अपनाया गया है; C++ में भी वही समस्या आ सकती है, लेकिन तब इसे भाषा से ज्यादा toolchain की गलती माना जाएगा
    wild को मैं कुछ समय से देख रहा था क्योंकि इसमें optimizing incremental linker बनने की संभावना है, लेकिन सच कहूँ तो जब तक यह सच में incremental link नहीं कर पाता, इसे आज़माने की मेरे पास कोई प्रेरणा नहीं है

    • C++ में कुछ compilers incremental compilation और incremental linking support करते हैं, इसलिए वह Rust से काफी तेज compile हो सकता है
      साथ ही C/C++ ecosystem में binary libraries स्वीकार करने की संस्कृति है, इसलिए repository clone करने या development branch बदलने पर हर बार पूरी दुनिया को फिर से compile करने के बजाय कई बार सिर्फ अपनी application compile करनी होती है
    • इस समस्या को Wasm से हल किया
      बाहरी application shell को Wasm business logic call कराने पर सिर्फ अंदर की logic फिर से compile करनी होती है, और बाहरी app shell को restart करने की भी जरूरत नहीं पड़ती
  • 2008: GNU ld से तेज होने के लिए बनाया गया नया linker gold

    करीब 2015: gold से कम से कम 2 गुना तेज drop-in replacement linker lld

    2021: lld से कई गुना तेज नया linker mold

    2025: नया linker wild...

    • यह बात कम कही जाती है, लेकिन यह सब उन कई उपयोगी features को implement न करने की कीमत पर संभव हुआ है जिन्हें real programs इस्तेमाल करते हैं
    • यह नकारात्मक टिप्पणी है, सकारात्मक है या बस छोटी history recap है, पता नहीं; लेकिन यह तथ्य कि linkers से अभी भी बेहतर performance निकाली जा सकती है, काफी उत्साहजनक है
    • gold को binutils 2.44.0 से हटाया जाने वाला है, तो आधिकारिक तौर पर यह खत्म ही समझिए
    • Windows पर अभी शुरुआती stage में ही सही, The RAD Linker भी है
  • इससे संबंधित, थोड़ी पुरानी लेकिन अच्छी किताब John Levine की Linkers and Loaders है
    नीचे की सूची में आखिरी किताब

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

    मैंने कुछ साल पहले पढ़ी थी, काफी दिलचस्प लगी, और इस field की standard किताब है
    link में दिखता है कि उन्होंने दूसरी लोकप्रिय computer books भी लिखी हैं

  • काफी promising लग रहा है
    शुरू से Rust में लिखा गया है, और लक्ष्य है तेज होना तथा incremental linking support करना
    Rust में इस्तेमाल करने के लिए शायद gcc को linker driver के रूप में इस्तेमाल करके भी काम हो सकता है
    project के .cargo/config.toml में:

    [target.x86_64-unknown-linux-gnu]

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

थोड़ा अलग सवाल है, लेकिन Rust को यहां gcc या clang से ही क्यों जुड़ना पड़ता है? क्या कोई missing feature है?

  • दुर्भाग्य से gcc -fuse-ld= flag के जरिए मनचाहा linker स्वीकार नहीं करता
    स्वीकार किए जाने वाले linker सिर्फ bfd, gold, lld, mold हैं
    gcc से wild को linker के रूप में call करवाया जा सकता है, लेकिन फिलहाल इसके लिए wild linker वाली directory बनानी पड़ती है, binary या symbolic link का नाम "ld" रखना पड़ता है, और फिर gcc को -B/path/to/directory/containing/wild pass करना पड़ता है
    Rust linker को सीधे call करने के बजाय gcc या clang के जरिए linker क्यों call करता है, इसकी वजह यह है कि C compiler को मौजूदा platform पर libc और C runtime से link करने के लिए जरूरी linker flags पता होते हैं
    उदाहरण के लिए Scrt1.o, crti.o, crtbeginS.o, crtendS.o, crtn.o जैसी चीजें

  • क्योंकि Rust compiler machine code नहीं, बल्कि IR bytecode generate करता है

  • जिज्ञासा है: non-incremental case में यह mold से तेज़ हो सकता है, इसका theoretical reason क्या हो सकता है?
    “क्योंकि Rust है” कई चीजों के लिए ठीक explanation है, लेकिन expected performance advantage नहीं समझाता
    अगर वजह यह हो कि “parallel processing के ऐसे low-difficulty opportunities हैं जिन्हें Rust इस्तेमाल करना आसान बना देता है”, तो यह दिलचस्प होगा, लेकिन यह न तो साफ तौर पर लिखा है और न ही implied है

    • पक्के तौर पर नहीं जानता, और मुख्य वजह यह है कि मैं Mold codebase से बहुत familiar नहीं हूं
      एक clue यह है कि मैंने सुना है कि Mold ज्यादा तेज allocator mimalloc इस्तेमाल करे तो करीब 10% तेज हो जाता है
      Wild में mimalloc आजमाया, लेकिन measurable speedup नहीं मिला
      इससे लगता है कि Mold, Wild की तुलना में allocator का ज्यादा उपयोग करता है, और Wild में heap allocation की संख्या optimize करने की साफ कोशिश की गई है
      कुल मिलाकर इसे design decisions का फर्क मानता हूं
      इसका Rust से क्या संबंध हो सकता है: अगर Wild को Rust से C या C++ में port भी किया जाए, तो मुझे भरोसा है कि performance लगभग वैसी ही रहेगी
      लेकिन Rust में borrow checker की वजह से जो code patterns ठीक रहते हैं, वे C या C++ में pitfalls बन सकते हैं, इसलिए maintenance मुश्किल हो सकती है
      पहले जब C++ में coding करता था, तो छोटे performance cost के बावजूद ज्यादा defensive तरीके से लिखता था; Rust में compiler साथ देगा यह जानते हुए कहीं ज्यादा boldly लिख सकता हूं
  • क्या संयोग है
    एक घंटे पहले ही जिस C project पर काम कर रहा हूं, उसमें wild, mold, ld की performance compare की
    23 हजार lines, 172 files हैं, और gcc+ld में user time करीब 23.4 seconds, gcc+mold में 22.5 seconds, gcc+wild में 21.8 seconds लगा
    इसलिए अगर project की structure अच्छी है, तो link time शायद इतना बड़ा issue न हो

    • सुनने में ऐसा लग रहा है जैसे शुरुआत से fresh build किया गया
      उस case में ज्यादातर time linking में नहीं, code compile करने में जाता है
      तेज linker का फायदा iterative development में सबसे ज्यादा होता है
      यानी code में छोटा बदलाव करने के बाद फिर build करके result चलाते समय compiler के पास आमतौर पर बहुत कम काम होता है, लेकिन linking फिर भी शुरुआत से होती है, इसलिए वही dominant time बन जाती है
    • link time छोटे projects में नहीं, बल्कि Chrome जैसी चीजें build करते समय important होता है
    • तेज linker आमतौर पर incremental compilation scenarios में edit cycle कम करने के लिए useful होते हैं
    • ld.lld कैसा है?
  • “यह benchmark David Lattimore के laptop (2020 model System76 Lemur Pro) पर run किया गया था, जिसमें 4 cores (8 threads) और 42GB RAM है”

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

    वैसे, मेरा मतलब यह नहीं है कि wild bloated है
    अगर समस्या है, तो वह इससे develop होने वाले software और ऐसे software इस्तेमाल करने वाले लोगों के computers में है

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

      “... RAM 16GB है, और upgrade नहीं की जा सकती...”

    • आधा मजाक है, लेकिन जो लोग Rust में coding करते हैं, उनके पास शायद पहले से 32GB RAM तो होगी ही
      निजी तौर पर, laptop को 64GB में upgrade करने के लिए सचमुच बाकी सब कुछ sacrifice करना लगभग एक शानदार decision था
      “लगभग” इसलिए कहा, क्योंकि सिर्फ RAM पर all-in करने के बजाय RAM और display दोनों पर पैसा लगाना चाहिए था
      एकमात्र downside यह है कि हफ्ते में एक बार खुले tabs साफ करना अब पूरी शाम लगने वाला काम बन गया है