M1 Macで古いRuby(2.3.0)をrbenvでインストールしようとしたらハマりました

新しくM1　Macを購入したので、過去のプロジェクト等で使っているRubyをインストールしようとしたら、思いの外ハマってしまいました。

前提として、rbenvでのインストールです。（rvmは同じ問題が出るのかはわかりませんが、出そうな感じでした）

## 普通にインストールしようとしたら

以下のようにエラーが出てしまった

~~~
rbenv install 2.3.0
Downloading openssl-1.0.2u.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/ecd0c6ffb493dd06707d38b14bb4d8c2288bb7033735606569d8f90f89669d16
Installing openssl-1.0.2u...

BUILD FAILED (macOS 12.0.1 using ruby-build 20211109)

Inspect or clean up the working tree at /var/folders/5w/3gb4_24j54g14xnxsn0_czph0000gn/T/ruby-build.20211116154747.22853.vSq0Kf
Results logged to /var/folders/5w/3gb4_24j54g14xnxsn0_czph0000gn/T/ruby-build.20211116154747.22853.log

Last 10 log lines:
      _dgram_write in libcrypto.a(bss_dgram.o)
      _RAND_query_egd_bytes in libcrypto.a(rand_egd.o)
      ...
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[4]: *** [link_a.darwin] Error 1
make[3]: *** [do_darwin-shared] Error 2
make[2]: *** [libcrypto.1.0.0.dylib] Error 2
make[1]: *** [shared] Error 2
make: *** [build_crypto] Error 1
~~~

どうも、M1 macにインストールされていたOpenSSLは **1.1** で、２．３未満は __1.0__ のOpenSSLが必要とのこと

## ではOpenSSL　１．０をインストールしてみよう

### でも普通にはインストールできないので

すでにbrew-coreからはOpenSSL1.0が消えているとのことで、
[こちらのissueを参考に](https://github.com/rbenv/ruby-build/issues/1353)
以下のコマンドでインストールを試みた、がビルドでエラー

~~~
brew install rbenv/tap/openssl@1.0

==> Downloading https://www.openssl.org/source/openssl-1.0.2t.tar.gz
Already downloaded: /Users/nakahiro/Library/Caches/Homebrew/downloads/5d2da6a9ed1a20ef9d1b1418d79aa674cf5577b70ca1ce436fdaadfa04f0429c--openssl-1.0.2t.tar.gz
==> Installing openssl@1.0 from rbenv/tap
==> perl ./Configure --prefix=/opt/homebrew/Cellar/openssl@1.0/1.0.2t --openssldir=/opt/homebrew/etc/openssl no-ssl2 no-ssl3 no-zlib shared enable-cms darwin64-x86_64-cc enable-e
==> make depend
==> make
Last 15 lines from /Users/nakahiro/Library/Logs/Homebrew/openssl@1.0/03.make:
 ^
x86_64cpuid.s:273:10: error: unknown token in expression
 cmpq $0,%rax
         ^
x86_64cpuid.s:273:10: error: invalid operand
 cmpq $0,%rax
         ^
x86_64cpuid.s:274:9: error: unknown token in expression
 cmoveq %rcx,%rax
        ^
x86_64cpuid.s:274:9: error: invalid operand
 cmoveq %rcx,%rax
        ^
make[1]: *** [x86_64cpuid.o] Error 1
make: *** [build_crypto] Error 1

If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):
  https://github.com/rbenv/homebrew-tap/issues
~~~

どうもこのインストール方法ではM1 Macには対応していないらしい。

### M1 MacでOpenSSL１．０をインストールするには

ありがたいことに、[こちらに解決策を載せてもらっていた](https://github.com/rbenv/homebrew-tap/pull/2)

~~~
curl https://raw.githubusercontent.com/rbenv/homebrew-tap/e472b7861b49cc082d1db0f66f265368da107589/Formula/openssl%401.0.rb -o openssl@1.0.rb

brew install ./openssl@1.0.rb

rm -rf ./openssl@1.0.rb
~~~

~~~
brew install ./openssl@1.0.rb

Error: Failed to load cask: ./openssl@1.0.rb
Cask 'openssl@1.0' is unreadable: wrong constant name #<Class:0x000000010ebd9930>
Warning: Treating ./openssl@1.0.rb as a formula.
==> Downloading https://www.openssl.org/source/openssl-1.0.2u.tar.gz
######################################################################## 100.0%
==> Patching
==> perl ./Configure --prefix=/opt/homebrew/Cellar/openssl@1.0/1.0.2u --openssldir=/opt/homebrew/etc/openssl no-ssl2 no-ssl3 no-zlib shared enable-cms darwin64-arm64-cc enable-ec
==> make depend
==> make
==> make test
==> make install MANDIR=/opt/homebrew/Cellar/openssl@1.0/1.0.2u/share/man MANSUFFIX=ssl
==> Caveats
A CA file has been bootstrapped using certificates from the SystemRoots
keychain. To add additional certificates (e.g. the certificates added in
the System keychain), place .pem files in
  /opt/homebrew/etc/openssl/certs
~~~

無事、OpenSSL 1.0 がインストールできました


## ようやくM1 MacにRuby 2.3.0をインストール

[改めてこちらを参考に](https://github.com/rbenv/ruby-build/issues/1353)以下のコマンドでインストールを試みる

~~~
RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.0)" rbenv install 2.3.0
~~~
これで、ようやく念願のRuby 2.3.0がインストールできまｓ
が、**エラー**

~~~
RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.0)" rbenv install 2.3.1

Downloading ruby-2.3.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.bz2
Installing ruby-2.3.1...

WARNING: ruby-2.3.1 is past its end of life and is now unsupported.
It no longer receives bug fixes or critical security updates.

ruby-build: using readline from homebrew

BUILD FAILED (macOS 12.0.1 using ruby-build 20211109)

Inspect or clean up the working tree at /var/folders/5w/3gb4_24j54g14xnxsn0_czph0000gn/T/ruby-build.20211116163007.87317.fPCEfh
Results logged to /var/folders/5w/3gb4_24j54g14xnxsn0_czph0000gn/T/ruby-build.20211116163007.87317.log

Last 10 log lines:
date_core.c:8422:37: note: expanded from macro 'f_getlocal'
#define f_getlocal(x) rb_funcall(x, rb_intern("getlocal"), 0)
                                    ^~~~~~~~~~~~~~~~~~~~~
../.././include/ruby/ruby.h:1737:51: note: expanded from macro 'rb_intern'
        __extension__ (CONST_ID_CACHE((ID), (str))) : \
                                                  ^
494 warnings generated.
454 warnings generated.
linking shared-object date_core.bundle
make: *** [build-ext] Error 2
~~~

かなり挫けそうですが、心を無くして頑張りましょう。

### ffi周りで失敗してそうなログがあった


ログファイルを見てね！とのことだったので、ログを見ていったところ、このようなログがありました

~~~
14: error: implicit declaration of function 'ffi_prep_closure' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
#define ID2SYM(x) RB_ID2SYM(x)
date_core.c:3739:
~~~

これを基に調べてみると、[こちらの記事を発見](https://secret-garden.hatenablog.com/entry/2021/01/02/220713)

こちらもM1 Macのみの問題で、

~~~
RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install x.x.x
~~~
とすればいけるよ、とのこと

なので、最終的にはこうなりました

~~~
RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.0)" rbenv install 2.3.0

Installed ruby-2.3.0 to /Users/nakahiro/.rbenv/versions/2.3.0
~~~

無事インストールできました。

## 結果、こうすれば大丈夫

M1 Macで2.3.6？未満をインストールする場合は、以下のように実行すれば大丈夫そうです。

~~~
% curl https://raw.githubusercontent.com/rbenv/homebrew-tap/e472b7861b49cc082d1db0f66f265368da107589/Formula/openssl%401.0.rb -o openssl@1.0.rb

% brew install ./openssl@1.0.rb
==  ここまでは最初だけ

% RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.0)" rbenv install 2.3.0
~~~