- 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
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
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
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
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üyorumPreprocessor 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
Daha sonra James Hendrix bunu daha eksiksiz bir uygulama içeren bir kitaba dönüştürdü. Çocukken CompUSA’nın indirim rafında bu kitaba rastladığım için C öğrenmeye başladım ve kitap hâlâ bende
https://archive.org/details/dr_dobbs_journal_vol_05_201803/p...
https://www.amazon.com/Small-Compiler-Language-Theory-Design...
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
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
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
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
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
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
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
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
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...
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
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