12 puan yazan GN⁺ 2025-07-04 | 4 yorum | WhatsApp'ta paylaş
  • tmux-rs projesi, yaklaşık 6 ay boyunca C ile yazılmış tmux’un tüm kodunu Rust’a port etme çalışmasıdır
  • Başlangıçta C2Rust aracı kullanılarak otomatik dönüşüm denendi, ancak ortaya çıkan kodun bakım yapılabilirliği düşük olduğundan sonunda elle dönüştürme yapıldı
  • Derleme sürecinde ve Rust-C karşılıklı etkileşiminde çeşitli hatalar ve yapısal sorunlar yaşandı
  • goto ifadesi, makro veri yapıları, yacc ayrıştırıcısı gibi C’ye özgü kalıpları Rust’a taşırken özel sorunlar ve çözümler ortaya çıktı
  • Proje hâlâ unsafe Rust temelli, ancak ön derleme ve çalıştırma denemeleriyle Rust’a tam geçiş hedefleniyor

Proje genel bakışı

  • tmux-rs, tmux’un tüm kod tabanını (yaklaşık 67.000 satır C kodu) Rust’a (yorumlar ve boş satırlar hariç yaklaşık 81.000 satır) port eden bir projedir
  • Geliştirici bu çalışmayı bir hobi projesi olarak yürüttü ve C’den Rust’a taşıma sürecinde çok sayıda deneme-yanılma ve öğrenme deneyimi yaşadı

C2Rust kullanımı ve sınırları

  • Başlangıçta C2Rust adlı otomatik dönüşüm aracıyla tmux C kodunu Rust’a taşımayı denedi
  • Otomatik dönüştürülen kodun okunabilirliği düşüktü, kaynak C koda kıyasla 3 kattan fazla büyümüştü ve çeşitli gereksiz tür dönüşümleri ile sabit adlarının kaybı yüzünden bakım yapılabilirlik ciddi biçimde azaldı
  • Elle refaktör sürecinde sonunda C2Rust çıktısı tamamen bırakıldı ve C kodunu referans alarak doğrudan Rust’a taşıma yöntemine geçildi
  • Yine de C2Rust’un ilk aşamada derlenip çalışabilen çıktı üretebilmesi, projenin geçerliliğini ve uygulanabilirliğini doğrulamada çok yardımcı oldu

Derleme sürecinin tasarımı

  • tmux, autotools tabanlı bir derleme sistemi kullanıyor ve Rust kodu ile mevcut C kodu statik kütüphane olarak bağlanıyor
  • Başlangıçta Rust kütüphanesi C ikilisine bağlanıyordu, ancak kodun büyük kısmı Rust’a taşındıktan sonra yapı, Rust ikilisinin C kütüphanesini bağladığı bir düzene dönüştürüldü (cc crate kullanılarak)
  • Derlemeyi otomatikleştirmek için, çeviri sürerken bile kademeli derleme kontrolü yapılabilsin diye build.sh betiği ve build.rs betiği yazıldı
  • Eksik header bildirimleri, işlev imzası uyumsuzlukları gibi derleme sırasında sık görülen sorunlar işlev bazında adım adım çözüldü

Taşıma sırasında karşılaşılan hata örnekleri

Hata 1: Örtük bildirim ve pointer dönüşü

  • Rust’a çevrilen bir işlevde, pointer dönüş tipi C kodunda örtük bildirilmiş olduğu için dönüş değerinin üst 4 baytı kesiliyor ve yanlış aktarılıyordu
  • Çözüm, C tarafına doğru işlev prototipini ekleyerek derleyicinin doğru davranmasını sağlamak oldu

Hata 2: Struct alan türü uyumsuzluğu

  • client struct’ında alan türünün (pointer ve tamsayı) yanlış çevrilmesi nedeniyle bellek ofseti hesaplaması kaydı, veri yorumlama hataları ve segfault oluştu
  • Bu sorun, C ve Rust tarafındaki struct tanımlarını birebir uyumlu hâle getirerek çözüldü

C’ye özgü kalıpların Rust’a taşınması

Raw pointer kullanımı

  • C pointer’larını doğrudan Rust referanslarına eşlemek, null kabul edebilme, başlatma garantisi gibi Rust güvenlik kurallarıyla çelişebilir
  • Bu nedenle pointer yapılarının çoğu raw pointer (*mut, *const) olarak taşındı ve yalnızca güvenli olmayan alanlarda kullanıldı

goto ifadesinin ele alınması

  • C2Rust, goto akış kontrolünü algoritmik olarak dönüştürüyor, ancak çoğu durumda Rust’ın etiketli blok + break ve etiketli döngü + continue yapıları yeterli oldu

Makro veri yapılarının taşınması

  • tmux, intrusive red-black tree ve bağlı listeleri C makrolarıyla uyguluyor
  • Rust tarafında benzer bir arayüz, generic trait ve özel iterator’lar kullanılarak kuruldu (tek bir trait’in tekrar eden implementasyon sorunu dummy türle çözüldü)

yacc ayrıştırıcısının dönüştürülmesi

  • tmux, yapılandırma dosyası ayrıştırıcısı için yacc(lex) kullanıyor
  • Rust’ta yapısı benzer olan lalrpop crate kullanılarak dil bilgisi ve eylemler olduğu gibi port edildi; ayrıca C lexer ile bağlantı için bir adaptör de yazıldı
  • Bu süreçte lalrpop’un raw pointer desteği sınırları (ör. NonNull<T> kullanımı) gibi konular da deneyimlendi

Geliştirme ortamı ve araçlar

  • Tekrarlayan dönüşüm işlerinde çoğunlukla neovim üzerinde özel makrolar kullanıldı
  • Örnek: ptr == NULLptr.is_null() / ptr->field(*ptr).field gibi eşlemeler elle yapıldı
  • Otomasyon aracı (Cursor) da denendi, ancak kaybolan ya da yanlış kod çok olduğu için kod inceleme yükü arttı
  • Parmak yorgunluğunu azaltmada bir miktar yardımcı olsa da, üretkenlik açısından etkisi sınırlı kaldı

Sonuç ve sonraki yön

  • Tüm kod tamamen Rust’a taşındı ve sürüm 0.0.1 yayımlandı
  • Elle yazılan kod, C2Rust çıktısına göre bazı açılardan daha iyi olsa da hâlâ unsafe Rust temelli ve çok sayıda hata içeriyor
  • Nihai hedef, safe Rust koda geçmek ve tmux işlevlerinin Rust tarafındaki tam taşınmasını tamamlamak
  • Geliştirici, Rust ve tmux ile ilgilenen geliştiricilerden GitHub Discussions üzerinden iş birliği ve geri bildirim bekliyor

4 yorum

 
brainer 2025-07-04

Oo.. ama Rust daha hafif mi?

 
bus710 2025-07-04

Oo... güzelmiş?
tmux eklentileri arasında resurect de fark ettirmeden epey bellek tüketip garip çalıştığı için çıkarmıştım; tmux-rs ile birlikteyken daha iyi olup olmayacağını merak ediyorum.

 
GN⁺ 2025-07-04
Hacker News görüşü
  • Gerçekten harika bir proje günlüğü okuma deneyimiydi; bundan ne kadar etkilendiğimi iletmek istiyorum. Yazarın istikrarına ve inatçı azmine büyük saygı duyuyorum. "Bahçeciliğe benziyor ama daha fazla segfault var" ifadesiyle derinden empati kurdum. En çok öğrenmenin böyle ciddi hobi projelerinde gerçekleştiğini düşünüyorum.
    Özellikle c2rust ile ilgili deneyim çok ilginçti. Daha önce de diller arası otomatik kod dönüştürücülerin benzer bir etki yarattığını görmüştüm. Bu tür araçlar bir projeyi hızlıca başlatmak ve fizibiliteyi kanıtlamak için çok faydalı, ama sonunda hedef dile ait hissettirmeyen, içi boş bir kod ortaya çıkarmaya meyilli oluyorlar. Sonunda acı verici de olsa manuel portlamaya geçme kararının gerçekten doğru olduğunu düşünüyorum. C kodunun niyetini güvenli ve Rust usulü bir koda çevirmede otomasyonun sınırları var.
    "İlginç bug'lar" bölümünde #2 numaralı struct layout mismatch meselesini görünce geçmişte yaşadığım harici işlev arayüzü (FFI) kâbusları aklıma geldi. Ben de bir kez C++ ile C# arasında struct packing uyuşmazlığı yüzünden bir haftayı, sinsi veri bozulmasını yakalamaya harcamıştım. Anlam düzeyinde insanı delirten türden bug'lardan biri; gerçekten akıl sağlığınızı sorgulatıyor. Böyle bir şeyi bulmak için olağanüstü bir debug sabrı gerekiyor. Yazarı alkışlıyorum.
    Genel olarak bu projenin, temel altyapı kodunu modernleştirmenin gerçekçi zorluğunu ve sürecini çok iyi gösteren bir örnek olduğunu düşünüyorum. Bir sonraki büyük hedefin unsafe'den safe Rust'a geçmek olduğu söyleniyor; nasıl bir strateji izleyeceğini gerçekten merak ediyorum.
    raw pointer, goto ve benzeri karmaşık kontrol akışlarının tamamını, tüm kod tabanı çökmeyecek şekilde idiomatic ve güvenli Rust'a dönüştürmenin, aslında ilk porttan bile daha zor olabileceğini düşünüyorum. Lifetime ve borrow checker'ı modül modül kademeli olarak mı devreye almayı planlıyor, intrusive veri yapılarını nasıl ele alacak, merak ediyorum. Bunları standart kütüphanedeki BTreeMap gibi yapılarla değiştirmek performansı etkileyebilir; zaten özgün intrusive tasarımın amacı da bu değil miydi diye düşünüyorum.
    Her hâlükârda inanılmaz bir iş. Süreci bu kadar ayrıntılı paylaştığı için teşekkürler. GitHub'da projeyi takip etmeye devam edeceğim.

  • Bu yeni haber beni kendine çekiyor gibi.
    Birkaç yıldır Rust tabanlı bir tmux oturum yöneticisi olan rmuxinator'ı (bir nevi tmuxinator klonu) kendim geliştiriyorum. Büyük ölçüde çalışıyor ama hayat yoğun olduğu için ilerleme yavaştı; son zamanlarda tekrar ağırlıklı olarak bug düzeltmelerine dönmüş durumdayım. Yakın zamanda eklediğim bir özellik, rmuxinator'ın bir kütüphane olarak da kullanılabilmesi oldu. tmux-rs'i fork'layıp rmuxinator'ı bağımlılık olarak ekledikten sonra, proje başına ayar dosyalarıyla oturum başlatma yönteminin gerçekten işe yarayıp yaramayacağını test etmek istiyorum. rmuxinator'ın upstream'e alınmasını savunuyor değilim, ama bu tür oturum şablonu işlevlerinin terminal multiplexer'ın kendisine gömülü olmasının gerçekten faydalı olacağını düşünüyorum.
    Tersinden bakınca, rmuxinator'ın tmux-rs'i bir kütüphane olarak kullanıp tüm oturum yönetimini shell command üretmeden çözmesi daha da iyi olmaz mı diye de düşünüyorum (tabii tmux-rs bunun için destek veriyor mu henüz bilmiyorum).
    Şu anda üzerinde çalıştığım bug fix'leri bitirince, yukarıdaki fikirlerden en az birini kesinlikle deneyeceğim.
    Her durumda, richardscollin'in yaptığı iş gerçekten çok iyi.

  • "tmux'u neden Rust ile yeniden yazdın sorusuna verecek çok iyi bir cevabım yok, sadece bir hobi projesi. Bahçeciliğe benziyor ama daha fazla segfault var." Bu tavrı çok seviyorum.
    Yeni bir şey üretirken her zaman büyük bir misyon ya da pratik fayda olmak zorunda değil. Hobi projelerinde beklenmedik keşifler ortaya çıkabilir. Yazarın ayrıntılı yazısına hayran kaldım.
    Bu arada benim bahçemde segfault dolu. Yeni bir projeyi kodlamak benim avlumda daha güvenli geliyor.

    • Kesinlikle katılıyorum. Her projenin dünyayı değiştirmek için var olması gerekmiyor.
      Yakın zamanda fzf'yi Rust ile yeniden uygulamıştım: rs-fzf-clone
      Bunun özel bir nedeni yoktu; mevcut fzf zaten çok iyi çalışıyordu. Asıl amaç Rust'ın channel'larını ve fuzzy search algoritmalarını bizzat deneyimlemekti. Gerçekten eğlenceli bir öğrenme süreciydi. Orijinal fzf daha iyi olsa da bu o kadar önemli değildi. Amaç yeni şeyler denemek ve deney yapmaktı.

    • "Bahçecilik, filozof olmak için en iyi bahanedir."

      • Ray Bradbury, Dandelion Wine
    • Birisi Rust'ın C'den koşulsuz olarak daha üstün olduğu imasında bulunduğunda refleks olarak önce alaycı tepki verme eğilimim var. Ama insanların sırf eğlence için böyle projeler yaptığını kendime sürekli hatırlatmam gerekiyor.

    • "Bizim mutlaka yalnızca yeni bir şey yaratmak için gerekçeye ihtiyacımız yok" sözü etkileyici geldi.
      Gerçi tmux aslında yeni bir şey değil.
      Mevcut bir yazılımı başka bir dilde yeniden yazmak için de bir gerekçe gerekip gerekmediğini düşündürüyor.

    • "Bahçeciliğe benziyor ama daha fazla segfault var" sözü komik. Rust'a henüz hâkim değilim; özellikle hangi durumlarda unsafe gerektiğini merak ediyorum.

  • Bu projenin tavrı ve yorumların çoğunun olumlu havası beni çok etkiledi.
    Olgun bir uygulamayı başka bir dilde yeniden yazmak için hep kötü yorumlar yapılır, ama gerçekten deneyince bununla birlikte çok fazla öğrenme geliyor. Sonuçtan çok süreç önemli.
    Buradaki ilgi ve yapay zeka gelişiminin yönü düşünülünce, bunun Rust'a yeni başlayanlar için çok çekici bir hobi projesine dönüşebileceğini düşünüyorum. Basit bug'ları düzeltmek, yeni özellik eklemek ya da optimizasyon yapmak çok büyük bir deneyim olur.
    Bir fikir olarak, Gemini CLI'yi (veya sevdiğiniz başka bir LLM'yi) bir scratch buffer gibi kullanıp tmux oturumundaki farklı pencere/panellerle etkileşime sokan bir özellik önermek istiyorum.
    Benim kullanımımda, birden fazla sunucuda senkronize panellerle komut çalıştırıyor ve başarısızlıkları elle yönetiyorum; eğer yapay zekaya komut yürütmeyi devredip çıktıyı gerçek zamanlı analiz ederek komutları uyarlamalı biçimde yeniden üretmesini sağlayabilsem, bu dinamik olarak oluşturulan özel bir shell script gibi hissettirirdi.

    • İnsanların hobi projesi olarak ne yaptığına, bunu nasıl yaptığına saygım var. Ama neden mevcut bir yazılımı bir dilden diğerine neredeyse olduğu gibi portlamaktan heyecan duyulduğunu anlayamıyorum.
      Örneğin her gün gvim kullanıyorum, ama bir editör yapmak istesem illa gvim gibi olmak zorunda olmazdı; sadece benim istediğim özelliklere sahip yeni bir şeyi yaratıcı biçimde yapmak isterdim. Bu kadar zaman yatırılacaksa yaratıcı ve özgün bir şey denemenin daha anlamlı olduğunu düşünüyorum.
  • Az önce tmux'u Fil-C'ye bir saatten kısa sürede portladım (libevent portu ve testlerin geçmesi dâhil). Gayet iyi çalışıyor ve tam bellek güvenliği sağlıyor.

  • Bu tür projeleri seviyorum. Ben de Rust'a kendimi kaptırmak istiyorum.
    Bu arada zellij'yi (Rust tabanlı bir terminal multiplexer) anmak isterim.
    Ben sadece bir kullanıcısıyım; Rust tabanlı çözümleri aramaya ve onlara geçmeye devam etmek hoşuma gidiyor.

  • Tam da şu videoyu yeni izliyordum: "Oxidise Your Command Line"
    https://www.youtube.com/watch?v=rWMQ-g2QDsI
    Bazı kısımlar Rust geliştiricisi olmayanlar için gereksiz olabilir, ama komut satırı ortamına alışkın herkes için oldukça faydalı ipuçları da var.

  • c2rust'ta, sabit isimlerini koruma gibi, yazarın işaret ettiği bilgi kaybını azaltacak iyileştirmelerin gayet mümkün olduğunu düşünüyorum. İlk dönüşümün yükü büyük çünkü.

    • Bence de C2Rust'ın bu özelliğe kesinlikle ihtiyacı var. Benim anladığım kadarıyla bu aracın temel amacı, daha sonra idiomatic Rust'a taşınacak bir temel kod üretmek. Ama sabit tanımları gibi şeyler tamamen kaybolursa üretkenlik kaybı ciddi olur.
  • Büyük dil modellerinin tüm C kodunu bir saat içinde doğru şekilde Safe Rust'a otomatik dönüştürebildiği bir döneme gelirsek, bu proje oldukça ileri görüşlü, simgesel bir örnek gibi görünecek.
    Yine de yazar, son aşamada bunu Cursor ile denediğini ama (2025 ortası itibarıyla) dönüşüm veriminin belirgin şekilde düştüğünü söylediği için, pratik performans açısından daha gidilecek yol olduğunu düşünüyorum.

    • codemod.com gibi yerlerde buna zaten "codemods" kavramıyla yaklaşılıyor.
      codemods, AST'leri (soyut sözdizimi ağaçları) kullanarak hızlı ve büyük ölçekli kod dönüşümü ile refactoring yapılmasını sağlıyor.
      codemods API refactoring tanıtımı

    • "Büyük dil modelleriyle karmaşık C kodunu bir saat içinde kusursuz biçimde Safe Rust'a dönüştürebilmek" kısmı kulağa çok spesifik geldiği için etkileyici.

  • Kodun zamanla daha temiz hâle gelmesini umuyorum. zellij'yi birkaç kez denedim ama yıllardır geliştirilmesine rağmen tmux'un rahatça sunduğu bazı özellikler hâlâ eksik.
    Özellikle status bar'ı gizleyip göstermenin olmaması benim için en can sıkıcı konu.
    zellij-org/zellij issue #694'e bakın

    • Oturum yöneticisi eklentisine kısayol tuşu eşleyemediğim için benim için kullanılamaz durumda.
      Sık kullandığım key binding'ler, oturum yöneticisi eklentisinin varsayılan bağlarıyla çakışıyor; bu yüzden dizin seçimi gibi önemli işlevler engelleniyor.
      Sonuçta oturum oluşturmayı da eklenti yerine doğrudan komut satırından yapmak zorunda kalıyorum.