🔗 M1 MacでRuby 2.4〜3.2をrbenvでビルドするための要点
要点から先に書きます。
基本的には、以下の公式ドキュメントの記載通りにすればビルドできます。
参考: Building Ruby -- ruby/building_ruby.md at master · ruby/ruby
ビルドで使うOpenSSLについては以下に注意してください。
- Ruby 3.1以降: OpenSSL 3系とOpenSSL 1.1.1系の両方が使える
- Ruby 2.4〜3.0: OpenSSL 1.1.1系が必要
ただし、OpenSSL 1.1.1は2023/09/11にEOLとなり、以後のアップデートには有償サポートが必要です↓。特に業務で古いRubyのビルドが必要な場合はご注意ください。
参考: OpenSSL 1.1.1 End of Life - OpenSSL Blog
Ruby 3.0とOpenSSL 1.1.1の関連については、Rubyコミッターのhsbtさんによる記事がおすすめです↓。
参考: Ruby 3.0 がセキュリティメンテナンスフェーズになったのでいくつか補足 - HsbtDiary(2023-03-31)
追記(2023/04/14)
hsbtさんのブログで本記事を取り上げていただきました。
🔗 ビルドでハマっている人のための最小ビルドオプション
公式ドキュメントの記載通りにすればビルドできると書きましたが、環境のセットアップによってはハマることがあります。
インストールでハマる場合、現在のbashの環境変数セットアップで何かをしくじっている可能性があります。私も.profileでの環境設定が適切でなかったためにハマりました😅。
忙しい人向けに、そうした既存のセットアップを一時的に上書きすることで確実にビルドできるビルドオプションを手短にまとめました。
🔗 ざっくりとした前提
詳しい前提については後述します。
- M1 MacBook環境(検証できませんでしたが、Intel Macなどでも使えると思います)
- bash環境であること
- Homebrew自身のインストールとHomebrew用の環境変数のセットアップ↓が終わっていること
git
、rbenv
、ruby-build
がインストールされて利用可能な状態であること- ビルドに必要なライブラリやツールが「Homebrewでインストールするもの」に示したとおりにHomebrewでインストールされていること
- コンパイラはCommand Line Toolsを使いました(他のコンパイラでもよいはずです)
# Homebrew用の環境変数セットアップ
eval "$(/opt/homebrew/bin/brew shellenv)"
export LDFLAGS="-L$HOMEBREW_PREFIX/lib"
なお、HOMEBREW_PREFIX
はeval
で自動的に設定されます。
追記
Command Line Toolsが古くなっているとconfigure: error: C compiler cannot create executables
エラーになる可能性があります。その場合は以下を実行してCommand Line Toolsを再インストールしましょう。
sudo rm -rf /Library/Developer/CommandLineTools
sudo xcode-select --install
🔗 A: Ruby 2.7〜3.2をビルドする場合
- シェルで以下を実行する
# あえてbrew shellenvのevalを現在のbashでのみ再実行する
eval "$(/opt/homebrew/bin/brew shellenv)"
# 現在のbashでのみbisonパスを設定する
export PATH="$HOMEBREW_PREFIX/opt/bison/bin:$PATH"
# 現在のbashでのみLDFLAGSを上書きする
export LDFLAGS="-L$HOMEBREW_PREFIX/lib"
# 邪魔になりそうな環境変数を現在のbashでのみクリアする
export CPPFLAGS=""
export optflags=""
export OPENSSL_CFLAGS=""
export RUBY_CONFIGURE_OPTS=""
# 続けて以下のいずれかを実行
# Ruby 3.2の場合の例
rbenv install 3.2.2
# Ruby 3.1の場合の例
rbenv install 3.1.4
# Ruby 3.0の場合の例
rbenv install 3.0.6
# Ruby 2.7の場合の例
rbenv install 2.7.8
ビルドが完了したら、シェルを終了して再起動します。
追記(2024/06/13)
その後、Ruby 3.0.xに限ってCommand Line Toolsでコンパイルするとエラーが発生するようになりました(他のRubyバージョンでは発生しませんでした)。
以下のようにコンパイラをgccに変更することでRuby 3.0.xをビルドできました。
brew install gcc
export CC=gcc
rbenv install 3.0.6
参考: rbenv install 3.0.4
fails on macOS 13.3.1 · rbenv/ruby-build · Discussion #2185
🔗 B: Ruby 2.4〜2.6をビルドする場合
# あえてbrew shellenvのevalを現在のbashでのみ再実行する
eval "$(/opt/homebrew/bin/brew shellenv)"
# 現在のbashでのみbisonパスを設定する
export PATH="$HOMEBREW_PREFIX/opt/bison/bin:$PATH"
# 現在のbashでのみLDFLAGSを上書きする
export LDFLAGS="-L$HOMEBREW_PREFIX/lib"
# Ruby 2.4〜2.6で必要なオプション
export RUBY_CFLAGS="-w"
# 邪魔になりそうな環境変数を現在のbashでのみクリアする
export CPPFLAGS=""
export optflags=""
export OPENSSL_CFLAGS=""
export RUBY_CONFIGURE_OPTS=""
追記(2023-07-10)
その後Ruby 2.4.10のOpenSSLを1.1.1uにアップグレードするためインストールすると、ffi_prep_closureでエラーが発生しました。
RUBY_CFLAGS
を以下のように変更することでインストールできました。
export RUBY_CFLAGS="-w -DUSE_FFI_CLOSURE_ALLOC"
# 続けて以下のいずれかを実行
# Ruby 2.6の場合の例
rbenv install 2.6.8
# Ruby 2.5の場合の例
rbenv install 2.5.9
# Ruby 2.4の場合の例
rbenv install 2.4.10
ビルドが完了したら、シェルを終了して再起動します。
なお、Ruby 2.4〜2.6の場合の違いはexport RUBY_CFLAGS="-w"
を追加していることだけです。
🔗 参考: ビルド内容をチェックする方法
irb -r rbconfig
でIRBを起動してから、RbConfig::CONFIG
のキーを指定することで、ビルドの詳細な内容を表示できます。この方法は、今回試したすべてのRubyバージョンで使えます。
たとえばRbConfig::CONFIG['configure_args']
でビルドに指定したオプションを表示できます。
$ irb -r rbconfig
irb(main):001:0> RbConfig::CONFIG['configure_args']
=> " '--prefix=/Users/hachi8833/.anyenv/envs/rbenv/versions/2.4.10' '--with-openssl-dir=/Users/hachi8833/.anyenv/envs/rbenv/versions/2.4.10/openssl' '--enable-shared' '--with-readline-dir=/opt/homebrew/opt/readline' '--with-libyaml-dir=/opt/homebrew/opt/libyaml' '--with-gmp-dir=/opt/homebrew/opt/gmp' 'CC=clang' 'CFLAGS= -w' 'LDFLAGS=-L/Users/hachi8833/.anyenv/envs/rbenv/versions/2.4.10/lib -L/opt/homebrew/lib' 'CPPFLAGS=-I/Users/hachi8833/.anyenv/envs/rbenv/versions/2.4.10/include -I /opt/homebrew/include -I/opt/homebrew/opt/libpq/include -I/opt/homebrew/opt/sqlite/include -I/opt/homebrew/opt/binutils/include'"
たとえばCPPFLAGS
のオプションを知るにはRbConfig::CONFIG['CPPFLAGS']
で表示できます。
$ irb -r rbconfig
irb(main):001:0> RbConfig::CONFIG['CPPFLAGS']
=> "-I/Users/hachi8833/.anyenv/envs/rbenv/versions/3.2.2/include -I /opt/homebrew/include -I/opt/homebrew/opt/libpq/include -I/opt/homebrew/opt/sqlite/include -I/opt/homebrew/opt/binutils/include -I/opt/homebrew/opt/gmp/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT "
たとえばjemalloc
が有効かどうかを知るにはRbConfig::CONFIG['MAINLIBS']
で表示できます。
irb -r rbconfig
irb(main):001:0> RbConfig::CONFIG['MAINLIBS']
=> "-ljemalloc -lgmp -ldl -lobjc -lpthread "
また、OpenSSLのバージョンはIRBで以下を実行するとチェックできます。
require 'openssl'
puts OpenSSL::OPENSSL_VERSION
参考: Rubyから使用しているOpenSSLのバージョン確認
🔗 詳細
ここからは読みたい人だけ読めばよいと思います。
以下は最小限のRubyビルドを確かめた結果です。YJITやjemalloc、--disable-install-doc
などのオプションは含めていません。
環境変数の具体的な設定方法については省略します。私は環境変数のセットアップを.profileに書いていますが、人によっては.bashrcなどに書いていたりするかもしれません。詳しくは以下の記事をどうぞ。
Homebrew以外のパッケージ管理(MacPortsなど)や、rbenv以外のRubyバージョン管理(rvmやadsfなど)については本記事では試していません🙏
🔗 環境
バージョン表示方法もメモします。
- マシン
- M1 MacBook Pro 2021
- macOS
- Ventura 13.2.1
- シェル: bash 3.2.57(1)-release (arm64-apple-darwin22)
bash --version
- CommandLine Tools:
14.2.0.0.1.1668646533
14.3.0.0.1.1679647830 pkgutil --pkg-info=com.apple.pkg.CLTools_Executables
- Git 2.39.2
git --version
- Ruby: 3.2.2 (2023-03-30 revision e51014f9c0) +YJIT [arm64-darwin22](ビルドで使われるカレントのRuby)
ruby --version
- Homebrew 4.0.6
brew --version
- rbenv 1.2.0-16-gc4395e5
rbenv --version
- ruby-build
RUBY_BUILD_VERSION="20230330"
- Release ruby-build 20230330 · rbenv/ruby-build
rbenvとruby-buildのセットアップについては省略します。インストールについては以下を参考にしてください。
🔗 Homebrewでインストールするもの
以下を実行してからシェルを再起動します。
$ brew install readline libyaml bison gperf zlib libffi
OpenSSLもインストールする場合は以下を実行してからシェルを再起動します。
$ brew install openssl@3 openssl@1.1 readline libyaml bison gperf zlib libffi
以下は参考までにバージョンを示します。
🔗 必須
openssl@3
- stable 3.1.0 (bottled) [keg-only]
openssl@1.1
- stable 1.1.1t (bottled) [keg-only]
後述するように、rbenvを使う場合はOpenSSLが自動ダウンロードされるので、HomebrewでインストールしなくてもOKです。
openssl@3
とopenssl@1.1
はHomebrewで両方インストールしておくことも可能ですが、環境変数はどちらか一方だけを指定する必要があります。
libyaml
- stable 0.2.5 (bottled)
zlib
- stable 1.2.13 (bottled), HEAD [keg-only]
🔗 Gitリポジトリからのビルドで必要なもの
autoconf
- stable 2.71 (bottled)
bison
(Ruby 3.2で必要)- stable 3.8.2 (bottled) [keg-only]
gperf
(なくてもいいらしいけど念のためインストール)- stable 3.1 (bottled)
🔗 オプション
readline
- stable 8.2.1 (bottled) [keg-only]
libffi
- stable 3.4.4 (bottled), HEAD [keg-only]
gmp
- stable 6.2.1 (bottled), HEAD
🔗 参考: rbenvによるOpenSSLの自動ダウンロード
細かい話ですが、rbenvでRubyをビルドする場合、ローカル環境にOpenSSLがなければ自動インストールされます。Ruby 3.1以上なら自動的にOpenSSL 3系を、Ruby 2.4〜3.0では自動的にOpenSSL 1.1.1系をダウンロードします。
通常はこれで十分でしょう。
ビルドを頻繁に行うのであれば、HomebrewでOpenSSLをインストールしておけば、ダウンロードの時間を節約できます。
インストールするならbrew install openssl@3
またはbrew install openssl@1.1
のどちらかをインストールし、以下のいずれかをセットアップします。
# OpenSSL@3 の場合のセットアップ
export PATH="$HOMEBREW_PREFIX/opt/openssl@3/bin:$PATH"
export PKG_CONFIG_PATH="$HOMEBREW_PREFIX/opt/openssl@3/lib/pkgconfig"
export RUBY_CONFIGURE_OPTS="$RUBY_CONFIGURE_OPTS --enable-yjit --with-openssl-dir=$HOMEBREW_PREFIX/opt/openssl@3"
# OpenSSL@1.1 の場合のセットアップ
export PATH="$HOMEBREW_PREFIX/opt/openssl@1.1/bin:$PATH"
export PKG_CONFIG_PATH="$HOMEBREW_PREFIX/opt/openssl@1.1/lib/pkgconfig"
export RUBY_CONFIGURE_OPTS="$RUBY_CONFIGURE_OPTS --with-openssl-dir=$HOMEBREW_PREFIX/opt/openssl@1.1"
Homebrewでは両方のバージョンをインストールしても構いませんが、環境変数セットアップには2つのバージョンを混ぜないようご注意ください。
🔗 参考: bison 3について
新しめのRubyでは、bison 3をHomebrewでインストールしたうえで、以下のパスを設定する必要があります。なお、Ruby 2.4〜3.2はすべてbison 3で問題なくビルドできました。
export PATH="$HOMEBREW_PREFIX/opt/bison/bin:$PATH"
参考: RubyをVisual C++でビルドする 2022.04版(+2022.12追記)
🔗 ビルドの結果
以下はビルドの記録です。どのRubyバージョンについても最新バージョンのみビルドを確認しました。
🔗 Ruby 3.1〜3.2
$ rbenv install 3.2.2
# 略
$ ruby -v
ruby 3.2.2 (2023-03-30 revision e51014f9c0)
$ rbenv install 3.1.4
# 略
$ ruby -v
ruby ruby 3.1.4p223 (2023-03-30 revision 957bb7cb81) [arm64-darwin22]
- OpenSSLのパスを設定しない場合: ビルド成功
- rbenvがOpenSSL 3.1.xを自動ダウンロードします
- OpenSSL 1.1.1をhomebrewでインストールしてパスを設定: ビルド成功
- OpenSSL 3.1をhomebrewでインストールしてパスを設定: ビルド成功
なお、Ruby 3.2からは--disable-install-rdoc
が無効になったのでご注意ください。
ドキュメントのインストールを無効にするのであれば、RUBY_CONFIGURE_OPTS
に--disable-install-doc
を指定します。
# 使ったセットアップ(自動ダウンロードが前提)
# Homebrew -----------------------------------
eval "$(/opt/homebrew/bin/brew shellenv)"
export LDFLAGS="$LDFLAGS -L $HOMEBREW_PREFIX/lib"
# bison 3--------------------------------------
export PATH="$HOMEBREW_PREFIX/opt/bison/bin:$PATH"
Ruby 3.2でRust版YJITもビルドに含める方法について詳しくは、以下の記事をどうぞ。
🔗 Ruby 2.7〜3.0
$ rbenv install 3.0.6
# 略
$ ruby -v
ruby ruby 3.0.6p216 (2023-03-30 revision 23a532679b) [arm64-darwin22]
$ rbenv install 2.7.8
# 略
$ ruby -v
ruby 2.7.8p225 (2023-03-30 revision 1f4d455848) [arm64-darwin22]
- OpenSSLのパスを設定しない場合: ビルド成功
- rbenvがOpenSSL 1.1.1を自動ダウンロードします
- OpenSSL 1.1.1をhomebrewでインストールしてパスを設定: ビルド成功
Ruby 3.0から下のバージョンではOpenSSL 3系が使えないので、OpenSSL 1.1.1系が必要です。rbenvの自動ダウンロードもOpenSSL 1.1.1系になります。
# 使ったセットアップ(自動ダウンロードが前提)
# Homebrew -----------------------------------
eval "$(/opt/homebrew/bin/brew shellenv)"
export LDFLAGS="$LDFLAGS -L $HOMEBREW_PREFIX/lib"
# bison 3--------------------------------------
export PATH="$HOMEBREW_PREFIX/opt/bison/bin:$PATH"
🔗 Ruby 2.4〜2.6
$ rbenv install 2.6.8
# 略
$ ruby -v
ruby 2.6.8p205 (2021-07-07 revision 67951) [arm64-darwin22]
$ rbenv install 2.5.9
# 略
$ ruby -v
ruby 2.5.9p229 (2021-04-05 revision 67939) [-darwin22]
$ rbenv install 2.4.10
# 略
$ ruby -v
ruby 2.4.10p364 (2020-03-31 revision 67879) [-darwin22]
- OpenSSLのパスを設定しない場合: ビルド成功
- rbenvがOpenSSL 1.1.1を自動ダウンロードします
- OpenSSL 1.1.1をhomebrewでインストールしてパスを設定: ビルド成功
2.4〜2.6では、export RUBY_CFLAGS="-w"
を追加する必要があります。
# 使ったセットアップ(自動ダウンロードが前提)
# Homebrew -----------------------------------
eval "$(/opt/homebrew/bin/brew shellenv)"
export LDFLAGS="$LDFLAGS -L $HOMEBREW_PREFIX/lib"
# bison 3--------------------------------------
export PATH="$HOMEBREW_PREFIX/opt/bison/bin:$PATH"
# Ruby 2.6.x以下用
export RUBY_CFLAGS="-w"
🔗 おまけ1: Ruby 2.3
Ruby 2.3.xはOpenSSL 1.0.2uまでしか使えないようです。
しかしrbenvにOpenSSL 1.0.2uを自動ダウンロードさせてもエラーになります。いろんなオプションを試しましたが失敗しました。
以下の記事によると、Ruby 2.3のビルドについては、OpenSSL 1.0.2uをソースでインストールしたりM1用のパッチを当てるなどしてRubyそのものはビルドできたものの、C拡張を使うgemが動かなかったりしたそうです。
参考: M1 Mac に古い ruby をインストールしてみたけど業務利用を諦めた話 - エムスリーテックブログ
Ruby 2.3以前はDocker Hubから探して使う方が無難なようです。もちろんRubyをアップグレードするに越したことはないのですが。
参考: ruby - Official Image | Docker Hub
🔗 おまけ2: 不要だったオプション
以下の設定オプションは検索するとよく見かけますが、少なくとも今回試したRuby 3.2〜Ruby 2.4では不要でした。Command Line Tools以外のCコンパイラで必要になるのかもしれないと想像しています。
export optflags="-Wno-error=implicit-function-declaration"
export OPENSSL_CFLAGS=-Wno-error=implicit-function-declaration
RUBY_CONFIGURE_OPTS
に--enable-shared"
を追加
🔗 参考
- Installation issues with Arm Mac (M1 Chip) · rbenv/ruby-build · Discussion #1853
- rbenv で ld: symbol(s) not found for architecture arm64 - AR ホームベーカリー
- asdf-vm/asdf-ruby: Ruby plugin for asdf version manager
- ruby installs failing for Macs (openssl 1.1.1q) · Issue #285 · asdf-vm/asdf-ruby
- Bug #18912: Build failure with Xcode 14 and macOS 13 (Ventura) Beta - Ruby master - Ruby Issue Tracking System
- Undefined symbols for architecture arm64: "__mh_execute_header", referenced from: _fill_lines in addr2line.o · rbenv/ruby-build · Discussion #2072
- Ruby 2.6.5 fails to compile on MacOS Big Sur · Issue #184 · asdf-vm/asdf-ruby
- rbenvからasdfへ - :wq
- Can't install ruby on M1 Mac "use of undeclared identifier 'RSA_SSLV23_PADDING'" · Issue #409 · postmodern/ruby-install
CONFIGURE_OPTS="--disable-install-rdoc" rbenv install 3.2.0
not working · rbenv/ruby-build · Discussion #2122- Cannot install Ruby versions < 2.4 because of openssl@1.1 dependency · rbenv/ruby-build · Discussion #1883
- MAC M1 Big Sur ruby compile issue for all rubies. Error running '__rvm_make -j8', · Issue #5033 · rvm/rvm
- Installing ruby 3.0 with rbenv/ruby-build with openssl 3
- Bug #18658: Need openssl 3 support for Ubuntu 22.04 (Ruby 2.7.x and 3.0.x) - Ruby master - Ruby Issue Tracking System
- RubyをVisual C++でビルドする 2022.04版(+2022.12追記)
注
OpenSSLの最も細かいバージョンは割と変わりやすいので、本記事では基本的にそれぞれ3系と1.1.1系と表記します。