世界を動かす技術を、日本語で。

tmux-rsの紹介

概要

  • tmux をCからRustへ完全移植した個人プロジェクトの紹介
  • C2Rust による自動変換の限界と手動移植への切り替え経緯
  • ビルドプロセス やC/Rust間連携の工夫と最適化
  • バグ発生例 とその原因・解決策の具体的な解説
  • Rust移植で直面した C特有パターン の扱いとRust流の実装手法

tmuxのRust移植プロジェクト「tmux-rs」紹介

  • Collin Richards によるtmuxのC→Rust移植プロジェクト
  • 元のCコード 約67,000行約81,000行 のRust(unsafe)に変換
  • 趣味として始めたが、 100% Rust化 という大きなマイルストーンを達成
  • C2Rustによる自動変換を試すも、 可読性・保守性の低下 により断念
  • 手動でC→Rust 移植を進める方針へ転換

C2Rust利用とその課題

  • C2Rust はC→Rust変換ツールだが、セットアップや出力コードの品質に課題
    • 例:定数名喪失(COLOUR_FLAG_256→0x1000000)、不要なキャスト多発
  • 生成コードは 3倍の行数、可読性・保守性が著しく低下
  • 意図把握のためC原文参照 が必須となり、手動リファクタリングに限界
  • 結果として 全ファイル手動変換 を決断
  • C2Rust自体は他プロジェクトで有用性を実感

ビルドプロセス最適化

  • tmuxautotools ベースの複雑なビルドシステム
  • Rust静的ライブラリ(staticlib)をMakefileに組み込み、 cargo→make の2段階ビルド
  • ミニクレート分割 を試すも、循環依存・リンク問題で断念
    • 単一クレート集中方式へ移行
  • 関数単位の逐次変換&テスト でデバッグ効率化
  • Rustバイナリ主導+Cライブラリ連携へとビルド手法を進化
    • ccクレート 利用でC側の残存コードをRustからビルド

典型的なバグとその解決

  • バグ例1:関数プロトタイプ不一致
    • C側で関数宣言抜け→戻り値型不一致→ポインタ値破壊
    • 原因:暗黙宣言(int返却)がRust側のポインタ返却と齟齬
    • 対策: 正しい関数宣言追加
  • バグ例2:構造体定義不一致
    • CとRustでポインタ型を値型に誤訳→メモリアクセス誤り・セグフォ
    • 対策: 型定義の正確な同期

C特有のパターンをRustでどう扱うか

  • 生ポインタ(raw pointer)
    • Rustの参照(&T, &mut T)は非null・有効性保証が必須
    • C→Rust直訳では **生ポインタ(mut T, const T) を多用
    • unsafeブロック下でのみ利用可能、 安全性担保に注意
  • gotoの移植
    • CのgotoはRustでは ラベル付きbreak/continue で表現可能
    • 複雑なフローは紙に書き出して変換
  • 侵入型データ構造(Intrusive Macros)
    • CのマクロベースのRed-Black TreeやリストをRust流に再現
    • 構造体内部にコレクション用フィールドを持たせる設計

開発ワークフローとツール

  • 関数単位でC→Rust変換→即ビルド&テスト の反復
  • エディタは Vim、AIツールも一部活用
  • ビルドスクリプト やCI設定も適宜調整

まとめ

  • tmux-rs はC→Rust手動移植の実践知・ノウハウの宝庫
  • C2Rustなどの自動変換ツールの限界と手動変換の意義
  • 型・ビルド・バグ対応・設計パターン移植のポイント
  • Rust移植で得られる 安全性・拡張性 の実感
  • 今後のRust移植プロジェクト の参考事例

Hackerたちの意見

「なんでtmuxをRustで書き直したの?」って思うかもしれないけど、正直なところ、いい理由はないんだ。趣味のプロジェクトみたいなもので、ガーデニングみたいな感じだけど、もっとセグフォルトが多い。こういう姿勢、好きだな。新しいものを作るのに理由はいらないし、趣味のプロジェクトから何が生まれるかわからないからね。素晴らしい記事を書いてくれた著者に感謝!それに、私のガーデニングもセグフォルトだらけだから、新しいプロジェクトをコーディングする方が庭には安全だね。

これ、めっちゃ面白いと思った!彼がこれにどれくらいの時間を費やしたのか気になるな。すごく単調そうだし、ハハ。

もしかしたら、いくつかの概念についての理解が間違ってるかもしれないけど、「もっとセグフォルト」って部分が混乱するな。Rustのコンパイラは、セグフォルトする可能性のあるコードをコンパイルさせないはずじゃないの?たくさんのunsafeブロックが関わってる場合を除いては。編集:どうやら、かなりの量のunsafeコードがあったみたい。

ガーデニングみたいだけど、もっとセグフォルトが多い。面白いね、Rustは初心者なんだ。unsafeを使う必要があるのは何をしてるの?

「ガーデニングは哲学者でいるための一番便利な言い訳だ。」 - レイ・ブラッドベリ、『ダンデライオン・ワイン』

完全に同意!すべてのプロジェクトが世界を変えるためにある必要はないよね。最近、fzfをRustで書き直したんだ。特に理由があったわけじゃないけど、普通のfzfでも全然問題ないし、ファジー検索アルゴリズムの仕組みを学ぶいい口実になるかなと思ったんだ。楽しかったよ。普通のfzfの方が良いのは間違いないけど、それが目的じゃなくて、遊びながら学ぶことが大事なんだよね。

偶然この動画を見てたところだよ、「Oxidise Your Command Line」 https://www.youtube.com/watch?v=rWMQ-g2QDsI その動画の一部は、Rust開発者じゃないと役に立たない内容だけど、コマンドラインインターフェースに慣れてる人には役立つこともあるよ。

この投稿、いいね!たくさん学べることがある。RustをCに自動翻訳するのはあまり良いアイデアじゃないみたいだね。「C2Rustの出力を全部捨てて、CからRustに手動で翻訳することにした。」って言ってるし。手動でやるのも大変そうだし:「コードを翻訳する際に多くのバグを導入してしまった。いくつかのバグを見つけて修正する過程を共有したい。」とか、AIを使うのも:「カーソルを使ってコードを翻訳すると、たまにバグが入るから、私と同じだね。生成されたコードをレビューするのにかかる時間は、自分で書くのと同じくらいだった。」趣味のプロジェクトとしては素晴らしいけど、動いているコードを再構築するのはやめた方がいいかもね…。

これ、ノーコードを思い出した! https://github.com/kelseyhightower/nocode

でも、動いているコードをリライトしない方がいいかもね…最終的な結果がメモリ安全な言語での拡張や改善を可能にするなら別だけど。

いいね、tmux好きだし、毎日使ってる。tmuxの中で生活してる感じ。今回のバージョンで、スクロールホイールやctrl-page-up/down、ctrlタブでパネルを簡単にスクロールできるようになったらいいな。あとは、左下に全体のタイトルを表示できるようになったら最高!ごめん、ここで文句を言うのは場違いだってわかってるけど、すごく嬉しいんだ!

自分にとっては、スクロールホイールは普通に使えるよ。他の設定もbind-keyで簡単にできるし。ウィンドウ内のペインを切り替えるのにctrl-spaceを使ってる:bind-key -n C-Space select-pane -t +1

zellijの方がtmuxより好きかもしれないよ。

自分はbyobuを使ってるけど、基本的にはtmuxの意見が強いディストリビューションだよ。スクロールホイールも問題なく動くし、Alt-PgUp/PgDnも大丈夫。Ctrl-Tabは多分使えないと思う、ターミナルがTabと区別できないことが多いから。でも、tmuxの設定でAlt-Tabとか他のコンボをペイン切り替えにバインドできるかもしれない。たぶん一行で済むはず。

この発表、すごく気になる。数年前からRustベースのtmuxセッションマネージャー「rmuxinator」を作ってるんだ(tmuxinatorのクローンみたいなもの)。ほぼ動いてるけど、生活のせいで進みが遅い。でも最近、バグを修正するために再開したんだ。最後に追加した新機能の一つは、rmuxinatorを他のRustプログラムでライブラリとして使えるようにすることだった。tmux-rsをフォークして、rmuxinatorを依存関係として追加して、プロジェクトごとの設定ファイルを使ってセッションを開始できるか試してみたいな。rmuxinatorを上流に追加することを勧めてるわけじゃないけど、こういうセッションテンプレートが「ターミナルマルチプレクサ」に組み込まれてたら素晴らしいと思う。逆に、rmuxinatorがtmux-rsをライブラリとして使ってセッションを設定・管理するのも面白いかも。シェルコマンドをただ出力するだけじゃなくてね。これがtmux-rsで現在可能かはわからないけど。今やってるバグ修正が終わったら、このプロジェクトをフォークして、上のどちらかを試してみるかも。とにかく、richardscollinの素晴らしい仕事だね!

これは、非自明なCコードベースを高精度で1時間以内にSafe Rustに翻訳する完全自動プロセスの素晴らしい未来の活用例になりそうですね。ただ、著者が指摘しているように、開発の終わりにCursorを使っても、翻訳を効果的に加速することはできなかったみたいです(2025年中頃)。だから、可能性はあるけど、まだ少し時間がかかりそうですね。

この人たち[0]は、ASTを利用した「codemods」[1]でやってるみたい。 0. https://codemod.com/ 1. https://martinfowler.com/articles/codemods-api-refactoring.h...

これは、非自明なCコードベースを高精度で1時間以内にSafe Rustに変換するための大規模言語モデルによる完全自動化プロセスの素晴らしい将来のユースケースのように思えますね。具体的ですね。

いいね、時間が経てばコードがもっときれいになることを願ってる。zellijを何度も試したけど、何年も開発してるのにtmuxが提供する多くの機能がまだ欠けてる。ステータスバーを表示/非表示にできないのが一番イライラする。 [1] https://github.com/zellij-org/zellij/issues/694

これめっちゃ好き!錆びるものを愛することにも挑戦したいな!ここで「zellij」を紹介したい。zellijはRustベースのターミナルマルチプレクサなんだ。俺はユーザーであってクリエイターじゃないけど、Rustのことが大好きで、可能な限りRustベースのソリューションを見つけて移行してるよ。

c2rustに改善を加えて、定数名による情報損失を減らし、初期の変換負担を軽減することはできませんか?

このプロジェクトの姿勢が大好きで、ほとんどのコメントもサポートしてるね。成熟したアプリケーションを別の言語に書き直すのはいつも悪いアイデアに聞こえるけど、その過程で学ぶことがたくさんあるんだ。結局、目的じゃなくてプロセスが大事なんだよね。ここでの反響やAIの進展を考えると、Rust初心者にとってとても魅力的な趣味プロジェクトになると思うよ。簡単に直せるバグもたくさんありそうだし。バグを直したり、新機能を追加したり、コードを最適化することが必要なことだね。アイデアを一つ提案すると、Gemini CLI(またはお気に入りのLLM)のためのスクラッチバッファを作って、tmuxセッションのさまざまなウィンドウやペインとやり取りできるようにするのはどうかな。俺の使い方としては、同期されたペインを使って複数のサーバーにコマンドを送信してるんだけど、時々いろんな理由でコマンドが失敗することがあるんだ。もしAIに一連のコマンドを送らせて、出力に基づいて反応して調整できたらどうだろう。まるでその場で動的に生成されるカスタムシェルスクリプトみたいだね。