在 Apple Silicon Mac 上安装老版本 Ruby – zhanggui

在 Apple Silicon Mac 上安装老版本 Ruby – zhanggui


これは、macOS 上の RVM を介して Ruby バージョンをインストールするためのスキルです。これには、新しいバージョンのシステム (特に Apple Silicon M シリーズ チップ) が古い Ruby をインストールできないという問題を解決するために設計されたスクリプト script/install_ruby.sh が付属しています。

Intel の黒い Apple/古い MacBook から抜け出し、M シリーズ Mac に切り替えた後に最初に行うことは、Ruby 2.6.5 のみを認識する先祖代々のプロジェクトなど、歴史的なプロジェクトによって地面にこすりつけられることがよくあります。この記事では、RVM を使用して任意のバージョンの Ruby を arm64 Mac にインストールする場合の 3 つの落とし穴、その根本原因、および私がカプセル化した一連の自動インストール スクリプト (オープン ソース、Claude Code / CodeBuddy のスキルとして利用可能) を記録します。

背景

新しい Mac はすべて Apple Silicon (arm64) ですが、多くの既存プロジェクトは依然として古いバージョンの Ruby にロックされています。直接 rvm install 2.6.5M シリーズ Mac では障害が発生する可能性が高くなります。これは形而上学ではなく、明確に定義された 3 つの互換性の問題です。

Rubyのバージョン アップルシリコン(arm64) インテル (x86_64)
<= 2.7.1 (2.3.x ~ 2.6.x を含む) パッチ + OpenSSL 1.1 が必要です OpenSSL 1.1が必要です
2.7.2~3.0.x OpenSSL 1.1が必要です OpenSSL 1.1が必要です
>= 3.1 特別な治療は必要ありません 特別な治療は必要ありません

2 つの重要な境界 (両方とも公式のソース コード パッケージに対して検証済み):

  • 2.7.2 arm64 をネイティブにサポートする最初の Ruby です。configure の __arm64__ 枝とフィドル HAVE_FFI_CLOSURE_ALLOC 機能検出はこのバージョンにのみ組み込まれています。
  • 3.1 これは、OpenSSL 3.x をサポートする最初の Ruby です。古いバージョンは OpenSSL 1.1 に対してのみコンパイルできます。

3 つの障害を 1 つずつ打ち破っていきましょう。

障害 1:ffi_prep_closure 宣言されていません (コンパイル時の失敗)

症状

make.log 決定的な間違いは次のとおりです。

closure.c:264:14: error: call to undeclared function 'ffi_prep_closure'

根本的な原因

Ruby <= 2.7.1 ext/fiddle/closure.c 次の部分にハードコーディングがあります。

#elif defined(__OpenBSD__) || defined(__APPLE__) || defined(__linux__)
# define USE_FFI_CLOSURE_ALLOC 0

つまり、Apple プラットフォームは「レガシー クロージャ API」を強制します (ffi_prep_closure)。新しいバージョンの macOS SDK の arm64 libffi 内 FFI_LEGACY_CLOSURE_API が 0 の場合、古い API は完全に削除されているため、コンパイルでは「関数が宣言されていない」と直接報告されます。

修理

arm64 で新しい API に切り替える (ffi_closure_alloc + ffi_prep_closure_loc):

#if defined(__APPLE__) && defined(__arm64__
/* macOS SDK libffi (>= macOS 26) removed the legacy ffi_prep_closure on arm64:
 * FFI_LEGACY_CLOSURE_API is 0, so use ffi_closure_alloc + ffi_prep_closure_loc. */
# define USE_FFI_CLOSURE_ALLOC 1
#endif

これに注意してくださいコンパイルの修正だけでなく、ランタイムの正確性も修正: arm64 の古いパスには、クロージャ構造体ポインタがエントリ ポイントとして保存されていますが、これはまったく実行可能なコードではありません。このパッチがないと、たとえコンパイルできたとしても、実行時にフィドル クロージャが壊れてしまいます。

アップストリームは 2.7.2 で機能検出に変更されました (#elif !defined(HAVE_FFI_CLOSURE_ALLOC)) なので、2.7.2 以降ではこのパッチは必要ありません。

ちなみに、実現可能と思われる別の解決策は、Homebrew の libffi 3.8 (廃止されたバージョンもエクスポートします) にリンクすることです。 ffi_prep_closure)——推奨されません: コンパイルは可能ですが、arm64 ではレガシー エントリ ポイントが間違っており、実行時にクロージャが壊れます。

障害 2: OpenSSL 非推奨エラー (コンパイル時の失敗)

症状

ossl.c:311:14: error: 'ERR_get_error_line_data' is deprecated [-Werror,-Wdeprecated-declarations]

エラーの下のメモ行には、実際に使用されたヘッダー ファイルのセットが表示されます。次に例を示します。

/opt/homebrew/Cellar/openssl@4/4.0.3/include/openssl/err.h:380: note: ... marked deprecated here

根本的な原因

Ruby < 3.1 は OpenSSL 1.1 のみをサポートしますが、 ext/openssl/extconf.rb 最初に実行されます pkg_config("openssl")——Homebrew の OpenSSL 3.x/4.x に解決されます。そのため、Ruby は 1.1 時代のコードを取得して 3.x/4.x ヘッダー ファイルに対してコンパイルし、非推奨の警告は直接次のようにアップグレードされました。 -Werror 間違い。

修理

バンドル PKG_CONFIG_PATH OpenSSL 1.1 に釘付け:

PKG_CONFIG_PATH=/opt/homebrew/opt/openssl@1.1/lib/pkgconfig \
  rvm install 2.6.5

よくある誤解は、通過するだけだということです。 --with-openssl-dir–useless、pkg-config の結果が優先されるためです。

しかし、より大きな問題が背後にあります: OpenSSL 1.1 は 2024 年 9 月 30 日に EOL となり、Homebrew が店頭から撤去しています。 openssl@1.1 式、新しいマシン上で brew install openssl@1.1 直接失敗する可能性があります。私のスクリプトの最終行は次のとおりです。 openssl.org 公式ソース パッケージから 1.1.1w (sha256 を確認) をビルドし、それをインストールします。 ~/.local/openssl-1.1そして置きます PKG_CONFIG_PATH 指向性のある ~/.local/openssl-1.1/lib/pkgconfig。

障害 3:ruby -v 出力 [-darwin25](終わったけどダメダメだった)

これは最も狡猾な方法です。すべてのコンパイルはパスしますが、rvm install 正常に戻りますが、——

$ rvm list
=* ruby-2.6.5 [ x86_64 ]  # 或干脆显示 [ broken ]

$ rvm 2.6.5 do ruby -v
ruby 2.6.5p114 (2020-03-31) [ -darwin25 ]   # CPU 是空的!

RbConfig::CONFIG["sitearch"] 文字通りになります ${arch}使用するとすぐに爆発します。

根本的な原因

Ruby <= 2.7.1 configure C コードの一部を前処理して Apple の CPU モデルを検出します。

target_cpu=`$CC -E - 2>/dev/null <

認識するだけ x86_64/i386/ppc/ppc64– 全くない __arm64__ ブランチ (2.7.2 で追加)。そこでAppleシリコンについて target_cpu は空です。

修理

存在する EOF 以下の前に段落を追加します。

#ifdef __arm64__
"processor-name=arm64"
#endif

インストール後に確認します:ruby -v 出力する必要があります [arm64-darwin25]、sitearch でなければなりません arm64-darwin25。

ひっくり返されやすい隠れた穴:IDEインジェクション rm シム

PATH上にIDEインジェクションがある場合 rm シムを安全に削除します (一部の IDE では rm (確認ロジックの層を含む)、autoconf は不可解な文で終了します configure: error: failed to create .ext/include//ruby/config.h 失敗し、構成が異常に遅くなります。解決策: ビルド時にクリーンな PATH を使用し、それをスクリプト内で明示的に使用します。 /bin/rm。

初めてでも正しく実行: 自動インストール スクリプト

落とし穴はすべて明らかですが、このプロセスを毎回手で入力するのは大変なので、バージョンとアーキテクチャを意識したスクリプトにカプセル化しました。

scripts/install_ruby.sh             # 如 2.6.5、2.7.1、3.3.8
scripts/install_ruby.sh  --dry-run  # 只打印计划,不构建
scripts/install_ruby.sh  --bg       # 后台构建,轮询日志

その決定ロジックは次のとおりです。

  1. 通常ビルドを優先する:clean PATH + (Ruby < 3.1 の場合)PKG_CONFIG_PATH OpenSSL 1.1 に釘付け。パッチを適用できない場合は、パッチを適用しません。
  2. arm64 + Ruby <= 2.7.1 パッチビルドを直接使用: ネイティブ ビルドは失敗する運命にあります。最初に壁にぶつかる必要はありません。
  3. OpenSSL 1.1 レベル 4 の解析:すでにHomebrewがインストールされています → ~/.local/openssl-1.1 古いビルド→ brew install openssl@1.1 → 公式ソースパッケージから 1.1.1w をビルドします。
  4. インストール後の自動検証: アーチの正確性、OpenSSL のバージョン、フィドル クロージャのランタイム動作 (実際に BlockCaller 21×2)を計算します。

2 つの使用上の注意:

  • 正確に合格する必要があります X.Y.Z。合格 2.7 RVM によって 2.7.8 に解析されます – および 2.7.2+ はすでにアップストリームに導入されています __arm64__ ブランチとパッチの設定セクションは競合するため、使用しないでください。
  • パッチ(assets/ruby-pre-2.7.2-apple-silicon.patch)を通して patch --dry-run 2.3.8 ~ 2.7.1 シリーズ全体にクリーンに適用できることが確認されています。完全なビルドは 2.6.5 (arm64、macOS 26 SDK) でテストされています。古いブランチでは、これら 3 つの落とし穴とは関係のないコンパイラの問題が発生する可能性があります。

AI にインストールしてもらいましょう

この一連のものは AI コーディング ツール スキルにもパッケージ化されており、スキル ディレクトリに複製できます。

# Claude Code
git clone  \
  ~/.claude/skills/ruby-macos-compat-install

# CodeBuddy Code
git clone  \
  ~/.codebuddy/skills/ruby-macos-compat-install

次に、「rvm を使用して Ruby 2.6.5 をインストールするのを手伝ってください」と言うだけで、スキルが自動的にトリガーされ、端末に触れることなく AI がドキュメントを読み取り、スクリプトを実行し、結果を検証します。

倉庫の住所:https://github.com/ScottZg/ruby-macos-compat-install(MIT ライセンス)、完全なエラー署名クイック チェック、rvm ログの場所の方法、およびパッチ再生成ガイドを含む (references/troubleshooting.md)。

要約する

新しい Mac での古い Ruby の失敗は形而上学ではありません。 3 つの問題にはそれぞれ明確な境界があります。

# 症状 根本的な原因 境界
1 ffi_prep_closure 宣言されていない SDK arm64 libffi は従来のクロージャ API を削除します Ruby <= 2.7.1、arm64 のみ
2 ERR_get_error_line_data 廃止された pkg-config は OpenSSL 3/4 に解決されます Ruby < 3.1、デュアル アーキテクチャ
3 [-darwin25] / [ broken ] 設定なし __arm64__ 支店 Ruby <= 2.7.1、arm64 のみ

境界を理解すれば、「どのアーキテクチャでどのバージョンに何が必要か」は表を見ればわかるマトリクスとなり、あとはスクリプトに任せます。



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *