1 puan yazan GN⁺ 2024-08-26 | 1 yorum | WhatsApp'ta paylaş
  • Dozer, Rust’ın daha erken bir bootstrap aşamasında kullanılabilmesini amaçlayan, saf C tabanlı bir Rust derleyicisidir; C++·flex·yacc·Makefile kullanılmadan yazılıyor
  • Resmî derleyici rustc Rust ile yazılmıştır; yeni sürümler önceki rustc sürümleriyle derlenir ve bu zincir OCaml ile yazılmış ilk Rust derleyicisine, oradan da Guile ve C katmanlarına kadar uzanır
  • Bootstrappable Builds’in Linux bootstrap süreci 512 baytlık ikili seed ile başlar; basit derleyiciler, shell, C alt kümesi, TinyCC, yacc, coreutils, Bash, autotools, GCC ve Linux’a doğru genişler
  • Rust bugün, C++ ile yazılmış mrustc üzerinden rustc 1.56’yı derleyen geç bir aşamada ortaya çıktığı için, C++ devreye girmeden önce Rust kullanmak zordur
  • Dozer, TinyCC ile bootstrap edilebilen bir Rust derleyicisi olmayı hedefler; sonrasında libcore, rustc’nin Cranelift backend’i, cargo alternatifi araçlar ve canonical rustc/cargo’nun yeniden derlenmesine kadar uzanmayı amaçlar

Dozer’in hedefi ve kısıtları

  • Dozer, saf C ile yazılmakta olan bir Rust derleyicisidir
  • C++ kullanmaz; flex, yacc veya Makefile da kullanmaz
  • Temel hedefi, Rust’ın C’den bootstrap edilebilmesini sağlayan bir derleyici oluşturmaktır
  • Özellikle TinyCC ile bootstrap edilebilir olmalı; sistemde bir C derleyicisi ve çok temel bir shell dışında kullanışlı araçlar olmadığı varsayılır

Rust derleyicisinin kendini derleme sorunu

  • Rust kodunu çalıştırmak için derlemek gerekir ve genellikle cargo build içeride rustc çağırır
  • rustc’nin kendisi de Rust ile yazılmış bir Rust derleyicisi olduğundan, yeni rustc önceki sürüm rustc ile derlenir
    • rustc 1.80.0, rustc 1.79.0 ile derlenir
    • Bu zincir rustc 1.78.0 gibi daha eski sürümlere doğru devam eder
  • İlk aşamalar Rust 0.7 sürümüne kadar gider; bu noktadaki derleyici OCaml ile yazılmıştı
  • OCaml derleyicisi de gerektiğinden, bootstrap zinciri yeniden başka dil uygulamalarına uzanır
    • camlboot, Guile kullanarak OCaml derleyicisini derleyebilir
    • Guile yorumlayıcısı C ile yazılmıştır

Bootstrappable Builds’in alt zinciri

  • Bootstrappable Builds, küçük bir ikili seed’den tüm sistemi bootstrap etmeye yönelik akışı ele alır
  • Linux bootstrap process, 512 baytlık ikili seed ile başlar
    • Bu seed, onaltılık sayıları alıp karşılık gelen ham baytları çıktılar veren çok basit bir derleyici içerir
    • Yorumlar ve boşluklar çıkarıldıktan sonra kalan onaltılık bayt listesi de teknik olarak çözümlenebilir kaynak kod kabul edilir
  • Sonraki aşamalar giderek daha yüksek seviyeli araçlar inşa eder
    • Çok basit bir işletim sistemi
    • Temel shell
    • Biraz daha gelişmiş bir derleyici
    • Assembly koduna benzeyen bir aşama
    • Çok temel bir C alt kümesi
    • Bu C alt kümesiyle yazılmış daha gelişmiş bir C derleyicisi
  • Birkaç aşama sonra TinyCC derlenebilir hale gelir; ardından yacc, temel coreutils, Bash, autotools, GCC ve Linux’a kadar ilerler
  • Her aşama live-bootstrap parts.rst içinde listelenmiştir

Rust bootstrap zincirine çok geç dahil oluyor

  • Rust şu anda bu süreçte çok geç bir aşamada ortaya çıkıyor
  • Kullanılan uygulama mrustc olup C++ ile yazılmış alternatif bir Rust uygulamasıdır
  • mrustc, rustc 1.56’yı derleyebilir ve bundan sonra modern Rust koduna kadar derleme devam eder
  • Ancak C++’ın bootstrap zincirine dahil edildiği noktada bootstrap fiilen neredeyse bitmiş olur
  • C++ devreye girmeden önceki aşamalarda Rust kullanmak için, C’den bootstrap edilebilen bir Rust derleyicisi gerekir

Dozer’in mevcut uygulama durumu

  • Dozer üzerinde yaklaşık iki aydır çalışılıyor ve uzantısız yazılıyor
  • Şu anda hem TinyCC hem de cproc ile sorunsuz derlenebiliyor
  • Backend olarak QBE kullanıyor
  • Uygulama hâlâ erken aşamada
    • Lexer tamamlandı
    • Parser’ın önemli bir bölümü uygulandı
    • Makro/modül genişletmesi mümkün olduğunca sonraya bırakılıyor
    • Tip denetimi şu an yalnızca i32 destekliyor
    • Kod üretimi henüz kaba durumda
  • Şu Rust kodunu şu anda başarıyla derleyebiliyor
fn rust_main() -> i32 {
    (2 - 1) * 6 + 3
}

rustc’ye uzanan plan

  • Hedef, Dozer’i kademeli olarak geliştirip temel libc kullanım örneklerini, ardından libcore ve rustc’yi derleyebilmek
  • rustc derlemesinde Cranelift backend’inin kullanılması planlanıyor
    • Cranelift backend’i tamamen Rust ile yazılmıştır
    • C++ olmadığı varsayıldığından LLVM derlenemez
  • Dozer ile Rust paketlerini derleyebilen bir cargo alternatifi araç da yapılması planlanıyor
  • rustc kaynaklarındaki otomatik üretilmiş dosyaların bulunup kaldırılması gerekiyor
    • Bootstrappable projesinin kurallarında otomatik üretilmiş koda izin verilmez
  • Nihai hedef, rustc ve cargoyu derledikten sonra, doğrudan derlenmiş rustc/cargo ile canonical rustc/cargoyu yeniden derleme sürecini oluşturmaktır
  • Proje şimdiye kadar üstlenilen en zor işlerden biri; tamamlanabilirliği konusunda şüpheler olsa da denemeye devam edileceği belirtiliyor

1 yorum

 
GN⁺ 2024-08-26
Hacker News yorumları
  • Rust’u bootstrap edecek olsaydım, tüm Rust yerine özellikleri daha az olan bir proto-Rust’ı C ile yazar, sonra o proto-Rust ile tam teşekküllü bir Rust derleyicisi yazardım
    Örneğin proto-Rust’ta borrow checker olmazdı, macro desteği sınırlı olurdu ya da hiç olmazdı, belleği serbest bırakmıyor bile olabilirdi ve iyi kod üretmesi de gerekmezdi
    Esasen Rust söz dizimine sahip C’ye daha yakın olurdu, ama Rust meraklısı açısından bakınca bu projenin hedeflediği “C söz dizimli C” ile Rust derleyicisi yazmaktan daha iyi görünüyor
    Neden bu yolun seçilmediğini merak ediyorum

    • Bu arada mevcut önde gelen Rust dışı Rust derleyicisi mrustc’de de zaten borrow checker yok
      Borrow checker’ı kaldırmak doğru programları bozmaz, sadece çok sayıda hatalı programın derlenmesini mümkün kılar
      mrustc’nin ana kullanım amacı rustc’yi derlemek ve rustc’nin borrow checker hatası olmadan kendisini derleyebildiğini zaten biliyoruz, o yüzden sorun değil
    • Mozart/Oz bunu gerçekten yaptı. Scala ile yazılmış bir proto-Oz derleyicisi var ve onunla Oz ile yazılmış gerçek derleyiciyi derliyorlar
      Scala derleyicisi verimsiz kod ürettiği için, sonrasında gerçek derleyici yeniden kendi kendisiyle derleniyor
      Böylece sonunda iyi kod üreten verimli gerçek derleyici elde ediliyor ve bu süreç dilin standart build’ine dahil
      https://github.com/mozart/mozart2
    • O zaman sonuçta iki derleyici yazmış oluyorsunuz; ek iş dışında pratikte ne kazanıldığını anlamıyorum
  • Hobi olarak Rust ile bir C derleyicisi yapıyorum ve Rust’ın C’den doğal olarak daha ağır olması şakasıyla ona Small C Compiler diyorum. “Tiny C Compiler”a bir parodi
    Arka uçta Cranelift kullanıyor ama genel derleyici yapısını çok sayıda trait ile tak-çıkar yapılabilir ve hack’lenmesi kolay olacak şekilde kuruyorum
    printf("%s", "Hello World!") işleyecek kadar çalışır hâle gelene kadar bunu açık kaynak olarak yayımlamayı düşünmüyorum
    Preprocessor ve parser yazmaya çalıştım, ayrıca meşhur typedef sorunu yüzünden rust-peg ve HimeCC’ye de bulaştım
    Sektörde typedef bağlamını korumak için symbol table kullanıldığını biliyorum, ama bunun alt taraftaki türleri okuyamama gibi bir sınırı vardı. Akademik taraftaki çözümün ne olduğunu merak ediyorum; aklıma gelen tek şey transactional memory
    Yardımcı olacak bir şey çıkarsa sonunda muhtemelen yayımlarim

  • Gerçekten çok havalı; ilginç olan şu ki aynı türden bootstrap problemi donanımda da var
    Bilgisayarları ne yapar? Daha önce yapılmış bilgisayarlar ve onların üzerinde çalışan yazılımlar. Üzerine düşündükçe daha da ilginç geliyor

    • Aynı bootstrap problemi her şeyde var. Yolları ne yapar? İnşaat ekipmanları yapar. Peki henüz yol yoksa o ekipmanı şantiyeye nasıl götürüyorsun?
      Birkaç ay önce inşaat projesi malzemelerinin teslimatı/fulfillment işini yapan bir startup’ta çalışan biriyle tanıştım
      Bu işin Amazon gibi genel teslimattan farklı bir uzmanlık gerektirdiğini anlattı; çünkü malzemeler çoğu zaman alışılmadık ya da tehlikeli fiziksel özelliklere sahip oluyor, ayrıca teslimat yeri çoğu zaman henüz bir adrese bile sahip olmuyor
      Çözülebilir bir mesele ama modern teslimat şirketlerinin tipik yetkinliklerinin ötesinde bir uzmanlık gerektiriyor gibi görünüyor
    • Veri merkezi inşa eden bir şirkette çalışmıştım; amaç yazılımı tüm veri merkezini tek bir dizüstü bilgisayarla ayağa kaldırabilecek seviyeye getirmekti
      Sebep, Avrupalı şirketlerle çalışırken düzenleyici kurumlara arka kapı olmadığını kanıtlayabilmekti
      Son derece ilginç ama çok zor bir problemdi; bizim ekip dolaylı şekilde işin içindeydi, ama tüm verinin denetlenebilir olmasını ve gönderilmemesi gereken hiçbir şeyin gönderilmemesini garanti eden bir proxy üzerinden veri aktarma kısmında çalışıyorduk
      Bitmeden şirketten ayrıldım; sonra da fazla zor olduğu için projenin rafa kaldırıldığını duydum
    • Eski Cray-1’in assembly sekizlik opcode’larına ya da IBM System/360’ın word opcode’larına bakınca, insanların opcode baytlarını doğrudan yazıp elle assembly yapabilmesi için ne kadar şaşırtıcı derecede basit tasarlandıklarını görüyorsunuz
      Sonrasında x86, devasa bütçeler ya da büyük alıcılar olmadan ortaya çıktı ve assembly olabildiğince verimli ve yoğun olacak şekilde tasarlandı
      Sonuç olarak diğer makinelerde daha rahat bulunabilecek bazı özellikler kaybedildi
    • Bu, bu tür bootstrap projelerinde ve yeniden üretilebilir build çalışmalarında en havalı taraflardan biri
      Teorik olarak yalnızca tek tek bileşenlerden çok basit bir bilgisayarı kendiniz inşa edebilirsiniz
      Büyük, verimsiz ve aşırı yavaş olurdu ama belirli bir instruction set architecture’ı izleyecek şekilde yapılabilir ve onun üzerinde bootstrap programı inşa edilebilir
      Sonra da tamamen anlayabildiğiniz kötü bir bilgisayardan elde edilen sonucun, tamamen güvenmediğiniz modern donanımdan elde edilen sonuçla aynı olduğunu iddia edebilirsiniz
    • İnsan uygarlığı düzeyinde de ilginç bir düşünce. İnsanlık bir şekilde tam şu anda Taş Devri’ne geri dönse, bugünkü seviyeye yeniden çıkabilir miydi?
      Bu da bir tür bootstrap problemi. Örneğin günümüzdeki petrol yataklarını çıkarmak 100 yıl öncesine göre daha zor; oraya kadar yeniden bootstrap etmek mümkün olur muydu diye merak ediyorum
  • Önyüklemenin faydalarını açıklayan üst düzey gerekçeyi bulmak için bağlantıları tam 4 kez takip etmek zorunda kalmak biraz sinir bozucuydu
    Başlıktaki “Why” kısmının bunu ele almasını beklemiştim
    https://bootstrappable.org/benefits.html

    • Önyüklemenin neden önemli olduğunu açıklamak zor olabilir. Bu yüzden benim önyüklenebilir derleyici README dosyamda da bir “Why?” bölümü var
      Güvenlik bunun büyük nedenlerinden biri ve bootstrappable ekibinin esas vurguladığı nokta da bu
      trusting trust problemi ve yakın zamandaki xz backdoor gibi saldırılardan kaçınmak için, her şeyin saf kaynak koddan önyüklenebilir olması gerekir
      Bunlar, elle yazılmış ve denetlenebilir olanlara dayanmak için önceden üretilmiş dosyaların tamamını bile kaldırıyor. Örneğin Python önyükleme süreci, kaynak içinde Python scriptlerinin ürettiği kodu içerdiği için epey karmaşık hale geliyor
      Ben ise daha çok kültürel koruma tarafıyla ilgileniyorum. Arctic World Archive gibi yerlere modern medyayı geleceğin arkeologları için saklamak istiyorum, ama çözümlenecek bir yol yoksa bunun anlamı kalmıyor
      Spesifikasyonları koruyabiliriz, ama onların x265’i ve gerekli her şeyi sıfırdan uygulamasını bekleyemeyiz. İkili dosyaları korursanız, bin yıllık donanımı çalıştırmanız ya da bin yıllık CPU’yu sanallaştırmanız gerekir
      Basit bir Lisp tanımı ve onun üzerinde çalışan kod verebilirsiniz, ama kim temel Lisp ile x265 uygular ki. Bu gerçekçi değil
      Bu yüzden projemde basit bir sanal makine yaptım ve onun üzerinde C’yi önyükledim
      Bu, yalnızca mevcut mimarilere değil, gelecekteki ya da uzaylı mimarilerine bile çok kolay taşınabilir. Geleceğin arkeologları ya da uzaylı uygarlıklar bir gün içinde VM’i uygular, onun üstünde C önyüklemesini çalıştırır, ardından ffmpeg vb. derleyerek medyamızın kodunu çözebilir
      Kara kutu yok; her şey debug edilebilir, denetlenebilir ve açık, elle yazılmış kaynak koddur
      https://github.com/ludocode/onramp?tab=readme-ov-file#why-bo...
      https://en.wikipedia.org/wiki/Arctic_World_Archive
  • Biraz kafa karıştırıcı. Yazının ancak ortalarında, başlıktaki yolculuğa neden başlandığı ortaya çıkıyor; esas mesele, C++ önyükleme zincirine girdiğinde önyüklemenin fiilen zaten bitmiş olması, dolayısıyla ondan önce Rust kullanmak isteseniz bile bunu yapacak bir yol olmaması gibi görünüyor
    Bu yüzden amaç, C’den — daha spesifik olarak, henüz kullanışlı araçların olmadığı varsayılan bir sistemde TinyCC’den — önyüklenebilen bir Rust derleyicisine sahip olmak gibi görünüyor
    Ama bu, önceki öncüllerle çelişiyor. rustc, 1.80.0’ın 1.79.0 ile, 1.79.0’ın 1.78.0 ile derlenmesi şeklinde 0.7’ye kadar geri gidiyor ve o dönemdeki derleyici OCaml ile yazılmıştı
    Ayrıca Guile ile bir OCaml derleyicisini başarıyla derleyen bir proje olduğu ve Guile yorumlayıcısının da C ile yazıldığı söylenmişti
    O halde yazarın istediği C++ içermeyen yol zaten var; sadece rustc ekibinin günlük olarak kullandığı yol bu değil
    Sonuçta motivasyon net değil. Daha iyi bir C tabanlı önyükleme süreci mi yapmak istiyor, bunu rustc’nin günlük önyükleme yöntemi haline mi getirmek istiyor, neden C++ aşamasını kaldırmak istiyor, neden C aşamasını tercih ediyor, anlaşılmıyor
    Sırf yapmak istediği için yapıyorsa sorun değil, ama oldukça uzun bir yazı okuduktan sonra bunun dışında bir amacı pek anlaşılmıyor

    • Rust’ı Guile ve Rust 0.7 derleyicisinden önyüklemek teknik olarak mümkün olabilir, ancak bunun için Rust derleyicisini yaklaşık 100 kez yeniden derlemeniz gerekir
      Her aşama saatler sürer ve 1.80’in 1.79’u, 1.79’un 1.78’i gerektirmesi gibi, 0.7’ye kadar hiçbir adımı atlayamazsınız
      Tamamen otomatikleştirilse bile bu önyükleme aylar sürebilir
      Ayrıca, erken rustc sürümlerinin yalnızca LLVM çıktısı verdiğini sanıyorum; dolayısıyla LLVM’i derlemek için her hâlükârda bir C++ derleyicisini önyüklemeniz gerekir
      C++ derleyiciniz varsa, doğrudan mrustc derlersiniz. Mevcut durumda mrustc yalnızca rustc 1.54’e kadar destek verdiğinden, yine de yaklaşık 35 sürüm boyunca derleme yapmanız gerekir
      Bütün bu süreç pratik değil. Dozer’ın hedefi küçük bir C derleyicisini önyüklemek, Dozer’ı derlemek ve ardından doğrudan güncel rustc’yi derlemek
      Böylece C++’ı ya da ara aşamaları önyüklemeden doğrudan Rust elde edilebilir
  • GCC 4 ve binutils’i asıl build scriptinden ayırmak mümkünse, listedekilerin yaklaşık yarısı çıkarılabilir gibi görünüyor
    Oradaki öğelerin önemli bir kısmı yalnızca autoconf türü araçları ve onların bağımlılıklarını tekrar tekrar yeniden derlemekten ibaret
    https://github.com/fosslinux/live-bootstrap/blob/master/part...

  • Ana fikri tam anlayamadım. Hedef makinede çalışan yeni bir binary üretmek için rustc’nin hedef mimariyi desteklemesi gerekir
    Eğer bu desteği rustc’ye eklediyseniz, bırakın rustc kendi kendini derlesin

    • Mesele yeni mimari desteğinden çok, çok daha kısa ve denetlenebilir bir önyükleme sürecine sahip olmak
  • Bazen Scheme ile bir C++ yorumlayıcısı ya da derleyicisi yazmayı hayal ediyorum
    Scheme’den doğrudan bugünkü GCC’ye gitmek inanılmaz bir kısayol olabilir
    Ama genel kanı, C++ derleyicisi yazmanın neredeyse imkânsıza yakın olduğu yönünde. Yine de öğrenmek için faydalı olabilir gibi geliyor

  • Alt assembler’dan tüm yığına bakınca, bu trusting trust problemini aşmanın bir yolu olabilir mi?
    https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_Ref...

    • Ancak her şeyi denetleyip tüm süreci bizzat çalıştırırsan mümkün olur
      Yine de https://en.m.wikipedia.org/wiki/Underhanded_C_Contest gibi şeyler var; oradaki bazı gönderileri ben denetlesem bile muhtemelen gözden kaçırırdım
    • Mesele zaten bu değil miydi?
  • C’yi biraz öğrenirken insanlar C’de C++ benzeri şeyleri nasıl yapıyor diye araştırmış, nesneler, istisnalar, eşzamanlılık gibi uygulamalara bakmıştım
    Eğer mrustc C++ ile yazılmışsa, böyle C++ tarzı C ilkel öğeleri kullanarak çalışan C++ kodunu C’ye port etmek daha kolay olabilir mi?
    C++ ile C arasındaki güçlü birlikte çalışabilirlikten yararlanıp parça parça taşımak da mümkün görünüyor
    Elbette bunun tuzakları bol, zor bir port işi olduğunun farkındayım. Yine de karşılaştırma noktasının C ile sıfırdan bir Rust derleyicisi yazmak olduğunu unutmamak lazım
    Eskiden var olan C++ to C derleyicileri de aklıma geliyor. Hâlâ varlar mı bilmiyorum
    Bugün bile Rust to C/C++ ve C++ to insan tarafından okunabilir C derleyicileri faydalı olabilir gibi geliyor. Çünkü bir tarafın güvenlik avantajlarını, diğer tarafın araç ekosistemiyle birleştirebilirler