ruby-build: Apple M1: `rbenv install 3.1.2` fails but installing ruby 3.1.2 from source succeeds
Hardware: Apple M1 MacBook Air running Big Sur 11.6.8 OpenSSL: Both 1.1 and 3.0 installed using brew with 3.0 as the linked default
Step 1: Run rbenv install 3.1.2
milos@air:~$ rbenv install 3.1.2
To follow progress, use 'tail -f /var/folders/y5/vfyf5lqj655g_zbm8pvdgmkr0000gn/T/ruby-build.20221029165815.98770.log' or pass --verbose
Downloading openssl-3.0.5.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/aa7d8d9bef71ad6525c55ba11e5f4397889ce49c2c9349dcea6d3e4f0b024a7a
Installing openssl-3.0.5...
Installed openssl-3.0.5 to /Users/milos/.rbenv/versions/3.1.2
Downloading ruby-3.1.2.tar.gz...
-> https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.2.tar.gz
Installing ruby-3.1.2...
ruby-build: using readline from homebrew
ruby-build: using gmp from homebrew
BUILD FAILED (macOS 11.6.8 using ruby-build 20221004)
Inspect or clean up the working tree at /var/folders/y5/vfyf5lqj655g_zbm8pvdgmkr0000gn/T/ruby-build.20221029165815.98770.ztN4k5
Results logged to /var/folders/y5/vfyf5lqj655g_zbm8pvdgmkr0000gn/T/ruby-build.20221029165815.98770.log
Last 10 log lines:
from ./tool/rbinstall.rb:899:in `block in install'
from ./tool/rbinstall.rb:713:in `no_write'
from ./tool/rbinstall.rb:899:in `install'
from ./tool/rbinstall.rb:1068:in `block (2 levels) in <main>'
from ./tool/rbinstall.rb:1043:in `foreach'
from ./tool/rbinstall.rb:1043:in `block in <main>'
from ./tool/rbinstall.rb:1127:in `block in <main>'
from ./tool/rbinstall.rb:1124:in `each'
from ./tool/rbinstall.rb:1124:in `<main>'
make: *** [do-install-all] Error 1
Step 2: Notice that rbenv versions
does not show 3.1.2 because it failed to install using ruby-build
milos@air:~$ rbenv versions
system
* 2.7.4 (set by /Users/milos/.rbenv/version)
3.0.4
Step 3: Install 3.1.2 manually from source, bypassing ruby-build entirely
wget https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.2.tar.gz
tar xf ruby-3.1.2.tar.gz
cd ruby-3.1.2
./configure --prefix=/Users/milos/.rbenv/versions/3.1.2 # add `--with-openssl-dir=/opt/homebrew/opt/openssl\@1.1` or @3 as preferred, if needed
make -j9
make install
Step 4: Notice that rbenv versions
now shows 3.1.2 successfully installed
milos@air:~$ rbenv versions
system
* 2.7.4 (set by /Users/milos/.rbenv/version)
3.0.4
3.1.2
milos@air:~$ rbenv global 3.1.2
milos@air:~$ ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [arm64-darwin20]
milos@air:~$ ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION'
OpenSSL 3.0.5 5 Jul 2022
Please do not move this to the Discussions tab as the installation works when not using ruby-build. This leads me to believe that it is indeed a ruby-build issue.
For what it’s worth, I can install ruby 3.1.2 this way with either OpenSSL 3.0 or OpenSSL 1.1 depending on what I provide in the configure step. I can provide --with-openssl-dir=/opt/homebrew/opt/openssl\@1.1
to override the 3.0 default that brew linked. Both work. However, again, with ruby-build the installation fails as per my report in https://github.com/rbenv/ruby-build/discussions/1961
Thanks to https://github.com/rbenv/ruby-build/discussions/1961#discussioncomment-3953774 for finding this workaround that makes the source build usable with rbenv.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 38 (15 by maintainers)
Hi there, I’ve investigated this issue a little bit, and finally got a repro on my end. Let me put my idea before going that direction.
The essential requirement for repro is that SIP is disabled.
TL;DR: Please re-enable SIP by following the official instruction and retry
rbenv install 3.1.3
Why?
The error repoted during rbs_extension build is produced by the dynamic loader dyld. It says that the Mach-O executable file and the inserted Mach-O dylib by
DYLD_INSERT_LIBRARIES
have incompatible cpu-subtype. Especially, the executable (/usr/bin/clang
) is compiled for arm64e but the dylib (libruby.3.1.dylib
) is compiled for arm64. (arm64e is a new arch supported by recent Apple devices basically arm64 + pointer authentication support.)Okay, so we can’t set
DYLD_INSERT_LIBRARIES
while running/usr/bin/clang
. But why it fails only when SIP is disabled?Executable binaries that is code-signed with Apple certificates are called platform binaries: https://developer.apple.com/documentation/endpointsecurity/es_process_t/3228979-is_platform_binary Platform binaries are usually located under
/usr/bin
, and macOS applies additional security protections for them when SIP is enabled. (Hardened Runtime: https://developer.apple.com/documentation/security/hardened_runtime).The additional security protections, Hardened Runtime, disables
DYLD_*
environment variables, soDYLD_INSERT_LIBRARIES
does not have any effect under SIP. Therefore the arch incompatibility error is not raised under SIP.Considering the above discussion, we have two workarounds for now:
Workaround 1: Re-enable SIP
This is a little bit tricky, but enabling SIP would also solve the issue because it prevents loading incompatible library through
DYLD_INSERT_LIBRARIES
(Potential) Workaround 2: Use clang compiled for arm64
/usr/bin/clang
is compiled for arm64e, but it’s just a shim and the actual clang binary is usually compiled for arm64:So building with explicit compiler path may solve the issue:
Yes, I’ll track this issue now. But I couldn’t reproduce this with Ventura 13.1 beta and Xcode 14 🤔
We will release all stable versions includes the fixes of Ventura and Xcode14 in Nov 2022. We will wait to try them for users who get same issues.
I just found that there is a major difference in the
./configure
output of the rbenv installation vs manual installation:rbenv:
manual:
We can see that
* enable shared libs: no
is shown when compiling manually per Step 3. This means that the difference between the the manual step vs rbenv is that rbenv enables shared libraries by default, and for some reason that creates an incompatible libruby3.1.dylib. Since we do not specify--enable-shared
when compiling manually, we do not get the cpu subtype error since there is no shared library to load.To recap:
When compiling manually, the full
./configure
command (as per Step 3) is:If we then add
--enable-shared
like this:Then we get the same error as with rbenv.
So I think you may be right - it may not be a ruby-build issue after all. Please do try to check if it’s an issue with ruby’s build system or toolchain and let me know if I can help with troubleshooting since I can reproduce both scenarios consistently.
Thanks so much @milosivanovic for excellent sleuthing and @hsbt for helping.
Agreed this should be primarily handled in the Ruby issue tracker. But, is there something that we could do from ruby-build in the meantime as a workaround for all people affected?