Ruby upgrade writes outside its new keg during `make install`
Source: Troubleshooting reference
Symptom: upgrading vim, ccache, or another Ruby dependent builds Ruby and
then fails under the global Homebrew Ruby directory:
Dir.mkdir: Permission denied @ dir_s_mkdir - .../brew/lib/rubyThe same contamination can later surface as Errno::ENOENT under
.../brew/lib/ruby/gems/... during RubyGems setup.
Root cause: the formula adds the versioned [email protected] path as a compatibility
fallback. runruby supplies the build directory through LD_LIBRARY_PATH, but
Homebrew’s GCC emits DT_RPATH, which the dynamic loader searches first. During
make install, the new Cellar lib directory is not populated yet, so the build
executable falls through to the previous keg’s libruby. The source RUBYLIB
also lacks RubyGems’ optional defaults/operating_system.rb; its require can
therefore find the previous keg’s file. Those old Homebrew defaults redirect
Gem.default_dir and Gem.ruby outside the new keg. The Linux filesystem
sandbox correctly rejects that write; the prefix permissions are not broken.
Fix: install/patch-homebrew-ruby.sh patches the local formula before Brew
Bundle runs. It enables new ELF dtags so DT_RUNPATH yields to the build-tree
library path, retains the new keg before the versioned fallback after install,
and adds a build-local empty RubyGems packager-default file so the previous
keg’s override cannot leak in. The formula replaces that empty file with the
current Homebrew configuration after installation.
This formula-local DT_RUNPATH is a deliberate exception to the prefix’s usual
DT_RPATH policy: the build runner must let its temporary LD_LIBRARY_PATH
select the new build-tree libruby.
Do not chmod the prefix or disable Homebrew’s Linux sandbox. Wait for any
active Homebrew process to exit, then rerun ~/dotfiles/bootstrap.sh upgrade so
the formula refresh and patch happen in the intended order.