10 ポイント 投稿者 GN⁺ 2024-12-29 | 3件のコメント | WhatsAppで共有

#9512 - Rewrite It in Rust

  • Fish シェルが Rust で再実装された。C++ コードは完全になくなり、ほぼ 100% 純粋な Rust で構成されている
  • 約2年前、Fish を C++ から Rust に移行する PR(#9512)を開始した
  • Fish は過去にも C から C++ へ移行した経験があるが、Rust への移行ははるかに大規模なプロジェクトだった

C++での問題点

  • ツールとコンパイラの違い: C++ のツールは使い勝手がよくなく、最新の C++ 標準を採用するとパッケージ作成者やコントリビューターにとって複雑さが増す
  • スレッド安全性: Fish の内部コマンド実行は現在シリアルに行われており、非同期プロンプトやノンブロッキング補完機能を追加するには並列処理が必要
  • 言語の複雑さ: C++ のヘッダーファイル、テンプレート、文字列処理などは複雑で安全ではない
  • コミュニティ: C++ は多くのコントリビューターを引きつけられない
  • 依存関係の問題: 特定の C ライブラリ(curses)の不安定さやビルド問題によって手間がかかっていた

Rustを選んだ理由

  • 楽しさと面白さ: Fish は趣味プロジェクトであり、楽しくて興味深い言語が必要だった。Rust はコントリビューターにとってより魅力的
  • 優れたツール: rustup でコンパイラを簡単にインストールでき、エラーメッセージも明確
  • エルゴノミクス: 明示的な use システムと、OptionResult のような安全な機能を提供
  • 優れた言語設計: Rust のポインタとオプションのシステムは C++ よりはるかに安全
  • 並列処理のサポート: Rust の Send と Sync により安全な並列処理が可能
  • 依存関係管理: YAML、JSON など外部形式のサポートを簡単に追加できる

プラットフォーム対応

  • macOS、Linux、BSD など主要なプラットフォームの大半をサポートし、Windows のネイティブ対応は目標としていない
  • Fish は UNIX 中心のシェルであり、Windows 環境よりも UNIX API とスクリプト言語に重点を置いている

移植プロセス

  • Fish は「テセウスの魚」という方式で C++ から Rust へ段階的に移行した。コンポーネントを1つずつ Rust に移し、C++ と Rust が共存できるようにした
    • テセウスの船(Ship of Theseus): 「1隻の船の木の板をすべて新しいものに交換したら、それはなお同じ船なのか?」
  • FFI の活用: autocxx を使って C++ と Rust 間のバインディングを生成し、一度に1つのコンポーネントずつ移植した
  • 大規模な移植: 特定の部分(例: I/O 処理など)は単独で移行し、複雑な FFI コードを減らした
  • ツールの改善: 移植の過程で Rust と C++ の相互運用性の問題を解決するため、autocxx をカスタマイズした

タイムライン

  • 2023年1月: 初期 PR を開始
  • 2024年1月: C++ コードを完全に削除
  • 2024年12月: Fish 4.0 ベータ版をリリース

Rustとの摩擦

  • 移植性の問題: Rust の #[cfg(...)] アプローチは、低レベルでシステム差異を扱うには非効率
  • ローカライズ: Rust のフォーマット文字列はコンパイル時に検証されるが、翻訳できない
  • ビルド時間: LTO とデフォルトのリリースビルドの使用により、ビルド時間が長くなることがある
  • 移植の過程でいくつかミスもあったが、ほとんどは簡単に解決できた

主な成果

  • curses の削除: terminfo データベースを Rust crate に置き換え、グローバル状態とビルド問題を解決
  • 単一実行ファイル: すべての依存関係を含んだ Fish バイナリを生成可能
    • Fish パッケージを自己完結型でインストール可能にし、ユーザーが簡単に利用できるようにした
  • 性能改善: メモリ使用量を最適化し、新機能の追加も容易になった

制限事項

  • CMake を完全には排除できなかった
  • Cygwin のサポートを終了: Rust のターゲットが存在しないため
  • Windows では依然として WSL 経由でのみ実行可能

現在と今後

  • Fish 4.0 は移植に成功し、性能も向上した
  • Fish は引き続き UNIX シェルであり、Rust への移行によって新機能を追加できるようになった
  • これで完全に Rust 化されたコードベースを持つことになり、従来より保守や機能追加が容易になった。Rust の利点を生かして新機能を追加できる
  • 今回の移行は成功裏に完了し、コントリビューターとユーザーの双方に良い影響をもたらした

3件のコメント

 
annyeong 2024-12-30

fishの使い勝手がうらやましいのですが、互換性や性能などの問題のため、zshをできるだけfishに近くなるよう設定して使っています。変わったfishがどうなっているのか楽しみですね 👀

 
GN⁺ 2024-12-29
Hacker Newsのコメント
  • Fishチームに祝意を表するとともに、プロジェクトの詳細が興味深い。C++からRustへ完全移行した最大のプロジェクトなのか気になる。他のプロジェクトにとって有益な教訓になり得る

    • FishはC++とRustのハイブリッドプログラムとしてリリースされたわけではない。最終テスト段階が完了していなかったため
    • C++の機能をRustに追加する動機を理解できない人もいるが、これは良いケーススタディになり得る
    • 新しいRustコードをC++コードベースに書けるとよいという意見がある
  • Rustに関する主な不満はバージョン検出サポートである。機能検出のほうが、ディストリビューション、Webブラウザ、コンパイラではより適している

    • バージョン/名前検出は、ChromeとIEがMozillaのふりをする理由であり、ClangがGCCのふりをする理由でもある。機能検出はこのような問題を引き起こさない
  • 移植の目標の一つはCMakeの排除だったが、失敗した。Cargoはビルドには優れているが、インストールについては単純すぎる。Fishには多くのスクリプトとドキュメントがあり、Cargoのユースケースには合っていない

    • Cargoがこうしたユースケースに向けて拡張されるよりも、別のツールが実装されるほうを望む
  • 数年前にbashからzshへ切り替えたときは満足していたが、新しいコンピューターでfishを使ってみると、zshが煩雑で時代遅れに感じられた。fishを数週間使ってみることを勧める

  • Cygwinをサポートしていないのは残念だ。RustがCygwinをビルドターゲットとしてサポートしてくれることを望む

  • Fishチームの努力に感嘆しており、プロジェクトが今後どう発展していくのか楽しみだ

  • ディストリビューションのパッケージャーが、Rust版fishをDebianのガイドラインに従ってどれほど容易にパッケージ化できるのか気になる

  • Fishチームに祝意を表するとともに、最高のシェルがさらに良くなったという意見だ。プロジェクトのタグラインを "Finally, a shell for the 00s!" に更新してはどうかと提案する

  • zshからFishに切り替えてから設定が簡単になり、Fishは期待どおりに動作するので、再び変更するつもりはない

  • cfg! マクロはtrue/falseにコンパイルされるため、if ガード内のコードはコンパイルされなければならない。my_feature なしでコンパイルすると失敗する可能性がある

  • Fishは自動補完と構文ハイライトのためにスレッドを使用しており、言語に並行性を追加する長期プロジェクトがある