12 poin oleh GN⁺ 2025-07-04 | 4 komentar | Bagikan ke WhatsApp
  • Proyek tmux-rs adalah upaya mem-porting seluruh kode tmux yang ditulis dalam C ke Rust selama sekitar 6 bulan
  • Pada awalnya dicoba konversi otomatis menggunakan alat C2Rust, tetapi karena hasilnya sulit dipelihara, akhirnya konversi dilakukan secara manual
  • Dalam proses build dan interoperabilitas Rust-C, ditemukan berbagai bug dan masalah struktural
  • Ada isu dan solusi khusus saat memindahkan pola khas C seperti pernyataan goto, struktur data berbasis makro, dan parser yacc ke Rust
  • Proyek ini masih berbasis unsafe Rust, tetapi menargetkan migrasi penuh ke Rust melalui pra-kompilasi dan eksekusi saat dijalankan

Gambaran proyek

  • tmux-rs adalah proyek yang mem-porting seluruh codebase tmux (sekitar 67.000 baris kode C) ke Rust (sekitar 81.000 baris, tidak termasuk komentar dan baris kosong)
  • Pengembang mengerjakan ini sebagai proyek hobi, dan mengalami banyak trial-and-error serta pembelajaran selama proses migrasi dari C ke Rust

Penggunaan C2Rust dan keterbatasannya

  • Awalnya digunakan alat konversi otomatis bernama C2Rust untuk memindahkan kode C tmux ke Rust
  • Kode hasil konversi otomatis sulit dibaca, ukurannya menjadi lebih dari 3 kali lebih besar dibanding kode C asli, dan karena berbagai cast yang tidak perlu serta hilangnya nama konstanta, maintainability menurun drastis
  • Dalam proses refaktorisasi manual, hasil C2Rust akhirnya dibuang, lalu pendekatan diubah menjadi menulis ulang langsung ke Rust sambil merujuk pada kode C
  • Fakta bahwa kode hasil C2Rust bisa di-build dan dijalankan pada tahap awal sangat membantu untuk memverifikasi kelayakan dan kemungkinan realisasi proyek

Perancangan proses build

  • tmux berbasis sistem build autotools, dan kode Rust serta kode C yang ada dihubungkan sebagai library statis
  • Pada awalnya library Rust di-link ke biner C, tetapi setelah sebagian besar kode dipindahkan ke Rust, strukturnya diubah menjadi biner Rust yang me-link library C (menggunakan crate cc)
  • Untuk otomatisasi build, dibuat skrip build.sh dan skrip build.rs agar pemeriksaan build bertahap tetap bisa dilakukan selama proses translasi
  • Masalah yang sering muncul selama build, seperti deklarasi header yang hilang dan ketidaksesuaian signature fungsi, diselesaikan secara bertahap per fungsi

Contoh bug yang ditemui saat translasi

Bug 1: deklarasi implisit dan pengembalian pointer

  • Pada fungsi yang dikonversi ke Rust, karena tipe pengembalian pointer dideklarasikan secara implisit di kode C, 4 byte bagian atas dari nilai return terpotong sehingga dikirim secara salah
  • Solusinya adalah menambahkan prototipe fungsi yang akurat di sisi C agar compiler menghasilkan perilaku yang benar

Bug 2: ketidaksesuaian tipe field struct

  • Karena salah menerjemahkan tipe field pada struct client (pointer vs integer), perhitungan offset memori menjadi melenceng, yang menyebabkan kesalahan interpretasi data dan segfault
  • Ini diselesaikan dengan menyamakan definisi struct secara tepat antara C dan Rust

Memindahkan pola khas C ke Rust

Pemakaian raw pointer

  • Memetakan pointer C langsung ke reference Rust dapat melanggar aturan keamanan Rust seperti nullability dan jaminan inisialisasi
  • Karena itu, sebagian besar struktur pointer dipindahkan sebagai raw pointer (*mut, *const), dan hanya digunakan di area yang tidak aman

Menangani pernyataan goto

  • Di C2Rust, kontrol alur goto diubah lewat algoritme, tetapi dalam kebanyakan kasus bisa diimplementasikan dengan cukup menggunakan labeled block + break dan labeled loop + continue di Rust

Migrasi struktur data berbasis makro

  • tmux mengimplementasikan red-black tree intrusif dan linked list dalam makro C
  • Di Rust, antarmuka serupa diimplementasikan menggunakan generic trait dan iterator kustom (masalah implementasi ganda pada satu trait diselesaikan dengan tipe dummy)

Konversi parser yacc

  • tmux menggunakan yacc(lex) untuk parser file konfigurasi
  • Di Rust, digunakan crate lalrpop yang strukturnya serupa untuk mem-porting grammar dan action secara langsung, serta dibuat juga adapter untuk interoperabilitas dengan lexer C
  • Dalam proses ini juga ditemui keterbatasan dukungan raw pointer di lalrpop (seperti penggunaan NonNull<T>)

Lingkungan pengembangan dan alat

  • Pekerjaan translasi berulang terutama dilakukan di neovim dengan makro kustom
  • Contoh: ptr == NULLptr.is_null() / ptr->field(*ptr).field dan pemetaan manual serupa lainnya
  • Alat otomatisasi (Cursor) juga sempat dicoba, tetapi karena banyak kode yang hilang atau salah, beban code review menjadi besar
  • Alat ini sedikit membantu mengurangi kelelahan jari, tetapi dari sisi produktivitas manfaatnya terbatas

Kesimpulan dan arah selanjutnya

  • Seluruh kode telah selesai dipindahkan ke Rust dan versi 0.0.1 telah dirilis
  • Dibanding C2Rust, kode manual berada pada tingkat yang sedikit lebih baik, tetapi masih berbasis unsafe Rust dan masih ada banyak bug
  • Tujuan akhirnya adalah beralih ke kode safe Rust serta menyelesaikan migrasi penuh seluruh fitur tmux ke Rust
  • Pengembang berharap dapat berkolaborasi dan menerima umpan balik dari developer yang tertarik pada Rust dan tmux melalui GitHub Discussions

4 komentar

 
brainer 2025-07-04

Oh.. tapi apakah Rust lebih ringan?

 
bus710 2025-07-04

Oh... bagus juga ya?
Di antara plugin tmux, ada resurrect yang diam-diam cukup boros memori dan kadang berjalan aneh, jadi saya sempat tidak memakainya; saya jadi penasaran apakah dengan tmux-rs hasilnya akan lebih baik.

 
youknowone 2025-07-04
 
GN⁺ 2025-07-04
Komentar Hacker News
  • Saya benar-benar ingin menyampaikan betapa terkesannya saya setelah membaca catatan proyek yang luar biasa ini. Saya sangat menghormati ketekunan dan kegigihan penulis. Ungkapan "mirip berkebun, tapi dengan lebih banyak segfault" sangat mengena. Justru dari proyek hobi yang serius seperti inilah biasanya pembelajaran terbesar datang.
    Bagian tentang pengalaman dengan c2rust sangat menarik. Saya juga pernah melihat perubahan serupa yang dibawa alat konversi kode otomatis antarbahasa. Alat seperti ini sangat berguna untuk memulai proyek dengan cepat dan membuktikan kelayakannya, tetapi pada akhirnya sering menghasilkan kode yang terasa kosong dan tidak benar-benar sesuai dengan bahasa target. Karena itu, menurut saya keputusan untuk beralih ke porting manual meski menyakitkan adalah pilihan yang sangat tepat. Ada batasan dalam menerjemahkan maksud kode C menjadi kode Rust yang aman dan idiomatik secara otomatis.
    Saat membaca bagian "bug yang menarik", khususnya soal struct layout mismatch nomor 2, saya langsung teringat mimpi buruk lama soal foreign function interface (FFI). Saya juga pernah menghabiskan seminggu untuk melacak korupsi data yang sangat halus karena struct packing antara C++ dan C# tidak cocok. Jenis bug seperti ini benar-benar bisa bikin waras dipertanyakan. Menemukannya butuh kesabaran debugging yang luar biasa. Salut untuk penulisnya.
    Secara keseluruhan, menurut saya proyek ini adalah contoh bagus yang menunjukkan tingkat kesulitan dan proses nyata dalam memodernisasi kode infrastruktur inti. Katanya target besar berikutnya adalah berpindah dari unsafe ke safe Rust, dan saya benar-benar penasaran strategi apa yang akan dipakai.
    Memperbaiki raw pointer, goto, dan seluruh alur kontrol yang rumit menjadi Rust yang idiomatik dan aman tanpa membuat keseluruhan kode ambruk, menurut saya, bisa jadi lebih sulit daripada porting awalnya. Saya penasaran apakah ada rencana untuk memperkenalkan lifetime dan borrow checker secara bertahap per modul, dan bagaimana mereka akan menangani struktur data intrusive. Kalau diganti dengan sesuatu seperti BTreeMap dari standard library, saya rasa bisa ada dampak performa, dan mungkin memang desain intrusive aslinya dibuat dengan tujuan itu.
    Pokoknya ini pekerjaan yang luar biasa. Terima kasih sudah membagikan prosesnya sedetail ini. Saya akan terus mengikuti proyeknya di GitHub.

  • Berita baru ini benar-benar menarik perhatian saya
    Sejak beberapa tahun lalu saya sedang membuat sendiri pengelola sesi tmux berbasis Rust, rmuxinator, semacam klon tmuxinator. Sebagian besar sudah berjalan baik, tetapi hidup sedang sibuk jadi perkembangannya lambat, dan belakangan saya mulai mengerjakannya lagi dengan fokus utama pada perbaikan bug. Fitur yang baru saya tambahkan adalah membuat rmuxinator juga bisa dipakai sebagai library. Saya ingin menguji apakah pendekatan mem-fork tmux-rs, menjadikan rmuxinator sebagai dependensi, lalu memulai sesi lewat file konfigurasi per proyek benar-benar bisa bekerja. Saya tidak sedang mendorong agar rmuxinator dimasukkan ke upstream, tetapi saya memang merasa fitur template sesi seperti ini akan sangat berguna bila dibangun langsung ke terminal multiplexer itu sendiri.
    Sebaliknya, saya juga sempat berpikir mungkin akan lebih baik jika rmuxinator memakai tmux-rs sebagai library sehingga seluruh manajemen sesi bisa dilakukan tanpa menghasilkan shell command sama sekali, meskipun tentu saya belum tahu apakah tmux-rs mendukung itu.
    Setelah saya menyelesaikan bug fix yang sedang dikerjakan sekarang, saya pasti akan mencoba setidaknya salah satu dari ide di atas.
    Bagaimanapun juga, salut untuk richardscollin, ini pekerjaan yang keren.

  • Saya sangat suka dengan sikap seperti, "tidak ada alasan bagus kenapa tmux ditulis ulang dalam Rust, ini cuma proyek hobi. Rasanya seperti berkebun, tapi dengan lebih banyak segfault."
    Saat membuat sesuatu yang baru, tidak harus selalu ada pembenaran besar atau nilai praktis. Penemuan tak terduga justru bisa lahir dari proyek hobi. Saya kagum dengan tulisan penulis yang begitu detail.
    Sebagai catatan, kebun saya sendiri penuh dengan segfault. Menulis proyek baru terasa lebih aman daripada berada di halaman rumah saya.

    • Sepakat semua. Tidak semua proyek harus ada untuk mengubah dunia.
      Baru-baru ini saya sempat mengimplementasikan ulang fzf dalam Rust rs-fzf-clone
      Tidak ada alasan khusus, fzf yang asli juga sudah bekerja sangat baik, dan tujuan utamanya adalah saya ingin merasakan langsung channel Rust dan algoritma pencarian fuzzy. Itu proses belajar yang sangat menyenangkan, dan meskipun fzf asli lebih unggul, itu tidak terlalu penting. Tujuannya memang untuk mencoba dan bereksperimen dengan hal baru.

    • "Berkebun adalah alasan terbaik untuk menjadi filsuf"

      • Ray Bradbury, Dandelion Wine
    • Kalau ada orang memberi nuansa bahwa Rust pasti lebih unggul daripada C, saya cenderung refleks menjadi sinis dulu. Tapi saya sering lupa bahwa orang-orang juga mengerjakan proyek seperti ini hanya untuk bersenang-senang.

    • Kalimat "kita tidak harus punya alasan hanya untuk membuat sesuatu yang baru" terasa mengena.
      Tapi tmux sebenarnya bukan sesuatu yang baru.
      Itu membuat saya berpikir apakah menulis ulang perangkat lunak yang sudah ada ke bahasa lain juga harus punya alasan.

    • Ungkapan "mirip berkebun, tapi dengan lebih banyak segfault" itu lucu. Saya sendiri belum terlalu akrab dengan Rust, jadi saya penasaran dalam situasi seperti apa unsafe benar-benar diperlukan.

  • Saya sangat terkesan dengan sikap proyek ini dan juga dengan nada positif di sebagian besar komentarnya.
    Menulis ulang aplikasi matang dalam bahasa lain memang sering dianggap bukan ide bagus, tetapi dalam praktiknya banyak pembelajaran yang datang dari benar-benar mencobanya. Prosesnya jauh lebih penting daripada hasil akhirnya.
    Melihat perhatian yang diterima proyek ini dan tren perkembangan AI, saya rasa ini bisa berkembang menjadi proyek hobi yang sangat menarik bagi pemula Rust. Memperbaiki bug yang mudah terlebih dahulu, lalu menambah fitur baru atau melakukan optimasi, akan jadi pengalaman besar.
    Sebagai salah satu ide, saya ingin mengusulkan fitur yang membuat Gemini CLI, atau LLM pilihan Anda, bertindak seperti scratch buffer untuk berinteraksi dengan berbagai window/panel dalam sesi tmux.
    Dalam kasus saya, saya menjalankan perintah ke banyak server melalui panel yang tersinkronisasi lalu menangani kegagalan dan hal lain secara manual. Jika AI bisa diberi tugas menjalankan perintah, menganalisis output secara real time, lalu menyesuaikan dan membangkitkan ulang command secara adaptif, rasanya akan seperti shell script khusus yang dibangkitkan secara dinamis.

    • Saya menghormati proyek hobi apa pun, dalam bentuk dan cara apa pun. Tapi saya tidak paham kenapa orang bisa merasa tertarik hanya dengan mem-port perangkat lunak yang sudah ada begitu saja dari satu bahasa ke bahasa lain.
      Misalnya saya memakai gvim setiap hari, tetapi kalau saya ingin membuat editor, saya tidak merasa harus membuatnya seperti gvim; saya justru ingin secara kreatif membuat sesuatu yang baru dengan fitur-fitur yang memang saya inginkan. Kalau sudah menginvestasikan waktu sebanyak ini, menurut saya lebih bermakna untuk mencoba sesuatu yang kreatif dan unik.
  • Saya baru saja mem-port tmux ke Fil-C dalam waktu kurang dari satu jam, termasuk porting libevent dan meloloskan pengujian. Hasilnya berjalan sangat baik dan sepenuhnya aman terhadap memori.

  • Saya suka proyek seperti ini. Saya juga jadi ingin benar-benar mendalami Rust.
    Sekalian saya ingin menyebut zellij, terminal multiplexer berbasis Rust.
    Saya hanya pengguna, dan saya senang terus mencari serta beralih ke solusi berbasis Rust.

  • Kebetulan saya baru saja menonton video ini, "Oxidise Your Command Line"
    https://www.youtube.com/watch?v=rWMQ-g2QDsI
    Sebagiannya mungkin tidak terlalu diperlukan kecuali Anda memang developer Rust, tetapi ada juga banyak tips yang cukup berguna bagi siapa pun yang akrab dengan lingkungan command line.

  • Saya rasa sangat mungkin ada peningkatan pada c2rust yang bisa mengurangi hilangnya informasi seperti yang disorot penulis, misalnya mempertahankan nama konstanta dan semacamnya. Karena beban konversi awal itu besar.

    • Saya benar-benar merasa C2Rust wajib punya fitur ini. Sejauh pemahaman saya, tujuan utama alat ini adalah menghasilkan kode dasar yang nantinya akan dipindahkan lagi ke Rust yang idiomatik. Tapi kalau definisi konstanta dan hal-hal seperti itu hilang semua, kerugian produktivitasnya jadi besar sekali.
  • Kalau suatu hari model bahasa besar bisa mengonversi seluruh kode C menjadi Safe Rust secara akurat dalam satu jam, proyek seperti ini akan terlihat sangat visioner dan representatif untuk masa depan.
    Namun penulis juga bilang mereka sempat mencoba tahap terakhir dengan Cursor pada pertengahan 2025, dan efisiensi konversinya turun jauh, jadi menurut saya performa nyata di dunia saat ini masih belum sampai ke sana.

    • codemod.com dan lain-lain sebenarnya sudah mencoba ini lewat konsep yang disebut "codemods"
      codemods memungkinkan transformasi dan refactoring kode dalam jumlah besar secara cepat dengan memanfaatkan AST (abstract syntax tree).
      pengantar refactoring API dengan codemods

    • Bagian "model bahasa besar bisa mengubah kode C yang kompleks menjadi Safe Rust secara sempurna dalam satu jam" terasa sangat spesifik, dan itu cukup berkesan.

  • Saya berharap ke depan kodenya jadi lebih rapi lagi. Saya sudah beberapa kali mencoba zellij, tetapi meski sudah dikembangkan selama bertahun-tahun, masih ada beberapa fitur yang di tmux tersedia dengan nyaman namun di sana belum ada.
    Yang paling mengganggu buat saya adalah tidak bisa menyembunyikan/menampilkan status bar.
    lihat zellij-org/zellij issue #694

    • Bagi saya, tidak bisa memetakan shortcut ke plugin session manager membuatnya tidak bisa dipakai.
      Key binding yang sering saya gunakan bertabrakan dengan binding bawaan plugin session manager, sehingga fungsi penting seperti memilih direktori jadi terhalang.
      Akhirnya struktur kerjanya jadi saya harus membuat sesi langsung dari command line alih-alih lewat plugin.