Closed tenderlove closed 1 year ago
Just to be more concrete, I was thinking of having something like $HOME/.rubies/x86_64/ruby-*
and $HOME/.rubies/arm64e/ruby-*
, then have my shell set an env var that points at the right place.
~/.rubies/<arch>/
seems a little too bespoke, and would cause issues with listing rubies from the directory; all other ruby switchers would need to filter out known architectures or having some kind of branching-logic to check if ~/.rubies/$(uname -m)
exists. The only other standards I am aware of for this are Debian's MultiArch Implementation, Ubuntu's MultiArch Spec, and Fedora's mention of /usr/<target>/
, all of which only focus on /usr
. While I have wanted to transition away from ~/.rubies/
and switch to the more standardized XDG directories (ex: ~/.local/share/
), the XDG specification makes no mention of storing executable software within their directories; maybe in the future XDG might support ~/.<target>/local/share
?
We could easily add RUBY_INSTALL_*
env variables for globally configuring ruby-install's default settings; or maybe even a configuration file? Then you could setup your shell's configuration to set the appropriate RUBY_INSTALL_DEFAULT_INSTALL_DIR
based on the current $MACHINETYPE
or uname -m
. That seems like the quickest way to support multi-arch environments.
~/.rubies/<arch>/
seems a little too bespoke, and would cause issues with listing rubies from the directory; all other ruby switchers would need to filter out known architectures or having some kind of branching-logic to check if~/.rubies/$(uname -m)
exists.
I was thinking, since there's a way to teach chruby
about installations from "other" switchers, I could (in my shell init file) do something like:
if test (arch) = "i386"
RUBIES += (~/.rubies/x86_64/*)
else
RUBIES += (~/.rubies/arm/*)
end
Adding something like ^^^ to my shell init doesn't seem like a big deal since I have to do it for Homebrew anyway. Maybe I have to change the target install base directory away from ~/.rubies
as not to confuse chruby
, but I'd be OK with that.
We could easily add
RUBY_INSTALL_*
env variables for globally configuring ruby-install's default settings;
This would work for me!
or maybe even a configuration file?
A config file seems like overkill to me, but it's up to you 😄
I was thinking, since there's a way to teach
chruby
about installations from "other" switchers, I could (in my shell init file) do something like:if test (arch) = "i386" RUBIES += (~/.rubies/x86_64/*) else RUBIES += (~/.rubies/arm/*) end
I would probably change that to RUBIES=(~/.rubies/<arch>/*)
, since chruby.sh
will pre-populate RUBIES
based on the contents of ~/.rubies/
; and currently doesn't filter out the sub-directories which lack a bin/ruby
executable file.
Finally got around to adding support for the RUBY_INSTALL_SRC_DIR
and RUBY_INSTALL_RUBIES_DIR
env variables. Will be released in version 0.9.0. 43e837b3dff60163b21b70dd3262fbd6e0f7f147
I'm trying out @tenderlove's setup and it's working great for installing rubies in different folders based on the arch. However, I haven't found an easy way to get gems to work in both architectures at the same time for the same Ruby version.
Here's an example:
ruby-install ruby-2.7.6 --install-dir "/Users/moncef/.rubies/i386/ruby-2.7.6"
chruby 2.7.6
gem env
=> worksruby-install ruby-2.7.6 --install-dir "/Users/moncef/.rubies/arm64/ruby-2.7.6"
chruby 2.7.6
gem env
=> fails with this error:
/Users/moncef/.rubies/arm64/ruby-2.7.6/lib/ruby/2.7.0/yaml.rb:3: warning: It seems your ruby installation
is missing psych (for YAML output).
To eliminate this warning, please install libyaml and reinstall your ruby.
...
dlopen(/Users/moncef/.gem/ruby/2.7.6/gems/strscan-3.0.4/lib/strscan.bundle, 0x0009): tried: '/Users/moncef/.gem/ruby/2.7.6/gems/strscan-3.0.4/lib/strscan.bundle' (mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e))) - /Users/moncef/.gem/ruby/2.7.6/gems/strscan-3.0.4/lib/strscan.bundle (LoadError)
Which makes sense because `~/.gem/ruby/2.7.6/` was first created under Intel, and I guess it doesn't get overwritten when installing the same Ruby version again with a different arch.
So, the question is, is it possible to specify different `~/.gem/ruby/*` directories based on the arch?
My current workaround is to delete the `~/.gem/ruby/{version}` every time I switch from one arch to the other, which means reinstalling gems. @tenderlove how are you dealing with this issue?
@monfresh this problem is due to the fact that chruby originally tried to share gems between ruby minor version families (e.g. upgrading from ruby-2.7.0
to ruby-2.7.1
would re-use the gems from ruby-2.7.0
), and assumed you would only be using one architecture. However, this approach has ran into multiple problems over the years (ex: rubygems using explicit #!/path/to/ruby
for installed gem executables, TruffleRuby ABI changes, and now multi-arch issues). In an ideal world, rubygems would automatically handle these edge-cases for us, regardless of where GEM_HOME
is pointed or it's current state. I will need to find spare time to start incrementally adding new features to chruby
to allow overriding how GEM_HOME
or GEM_PATH
are set (or even allow them not to be set). Although, I can't make breaking changes to how chruby behaves by default until 1.0.0 which will have to come after 0.4.0, 0.5.0, etc, where new additional features can be user tested. There are 0.4.0 and 1.0.0 branch branches where I've been experimenting with new API ideas. Currently, I'm trying to wrap up another big refactor on another project (down to just 62 remaining issues) that I want to wrap up before EoY so it doesn't drag on indefinitely.
FYI one way to avoid all these issues is to use this branch of my fork: https://github.com/eregon/chruby/tree/do-no-set-gem-home That does not set GEM_HOME, which means each ruby has its own separate gems and there is never invalid gem sharing. The only requirement is you install your Rubies in a user-writable directory.
@postmodern Thanks for the details!
@eregon Thanks, I'll try your branch.
My current workaround is to delete the
~/.gem/ruby/{version}
every time I switch from one arch to the other, which means reinstalling gems. @tenderlove how are you dealing with this issue?
I'm not dealing with it well. I just rm the ~/.gem
directory once in a while 😆
I think @eregon's solution would work fine, and I should probably do that
I'm not dealing with it well. I just rm the ~/.gem directory once in a while
So I'm curious, and maybe it's been mentioned before in other issue threads, but why doesn't rubygems simply allow you to run gem pristin --extensions
to build the missing C exts for the alternate architecture? It would be a less extreme workaround than rm -r ~/.gem/
. Also seems like rubygems could use a more helpful error message when the built C extensions are missing.
Finally got around to adding support for the
RUBY_INSTALL_SRC_DIR
andRUBY_INSTALL_RUBIES_DIR
env variables. Will be released in version 0.9.0. 43e837b
@postmodern That's great news - any idea when 0.9 might be available? Thanks!
@lougreenwood maybe next week? I also wanted to add additional environment variables like RUBY_INSTALL_PKG_MANAGER
or (I ended up deciding against this one env variable).RUBY_INSTALL_DOWNLOADER
(curl
or wget
)
Closing this as I prepare for a 0.9.0 release. The RUBY_INSTALL_RUBIES_DIR
environment variable have been added for configuring the default installation directory. If we want to add additional logic to automatically detect architecture-specific sub-directories (ex: ~/.rubies/aarch64/
) based on uname -m
(or if there's a better standardized directory within $HOME
for storing multi-arch software), that can be added in 0.10.0.
I upgraded to an M1, but I need to work with Rosetta sometimes. In order to accomplish that I've installed two versions of Homebrew, one that targets arm64e and one that targets x86_64. Then I taught Fish to fix the path depending on the architecture.
I'd like to do something similar with ruby-install, namely automatically change the install directory based on the target architecture. I was hoping to do that with an environment variable because I don't want to have to remember to check the architecture and then pass the right thing to
--install-dir
. However, it doesn't look like I can control the installation directory via ENV var.First, does the "separate path per architecture" approach make sense? If so, does adding an ENV var seem like an acceptable solution?
If not, I was thinking of building universal binaries, but I think that will be its own can of worms especially if I (for example) link against OpenSSL in one Homebrew installation, but then switch to a different architecture and try to use the same Ruby.
Thanks for your time!