-
-
Notifications
You must be signed in to change notification settings - Fork 192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A way to not set GEM_HOME if the installed ruby is under $HOME #422
Comments
Proof-of-concept PR for |
The reason why chruby sets Also, for the record, I'm adverse to adding yet more |
Right, I know. This is very inconvenient when actually developing a Ruby implementation though, as it prevents using the current Ruby selected with chruby and the Ruby being developed without switching everytime when doing anything using gems.
That would not keep built-in and user-installed gems separated, so I (maybe wrongly?) assumed it's not an approach you wanted to take.
I'd still want
@postmodern What other solution do you think is better for my use case presented in this issue? |
@postmodern Any thoughts on my reply? I like the idea of detecting if GEM_HOME is writable, it sounds like a much cleaner check than "is root" or "env var", should I proceed with that and make a PR then if you're not against it? |
@postmodern Here is a PR implementing the idea of setting GEM_HOME only if the default gem directory is not writable. It looks very elegant to me, please review it: #431 |
Due to this, I've been forced to switch to @eregon's fork of chruby that have #431: https://github.com/eregon/chruby/tree/do-no-set-gem-home It was needed because I have a computer with Apple silicon (M2), and I want to be able run Ruby apps either on arm64 or x86_64 ("Intel"). Using ruby-build it was very easy to install Rubies for different architectures to different directories (and configure your shell for it), but I can't have them install native extensions (like for Nokogiri) to the same directory ( arm64 $ env | grep GEM
GEM_ROOT=/Users/dentarg/.arm64_rubies/2.7.6/lib/ruby/gems/2.7.0
GEM_HOME=/Users/dentarg/.gem/ruby/2.7.6
GEM_PATH=/Users/dentarg/.gem/ruby/2.7.6:/Users/dentarg/.arm64_rubies/2.7.6/lib/ruby/gems/2.7.0
intel $ env | grep GEM
GEM_ROOT=/Users/dentarg/.rubies/2.7.6/lib/ruby/gems/2.7.0
GEM_HOME=/Users/dentarg/.gem/ruby/2.7.6
GEM_PATH=/Users/dentarg/.gem/ruby/2.7.6:/Users/dentarg/.rubies/2.7.6/lib/ruby/gems/2.7.0 As an example, before switching to the chruby fork (using chruby 0.3.9 installed from Homebrew), I did arm64 $ b e rake
Traceback (most recent call last):
13: from /Users/dentarg/.gem/ruby/2.7.6/gems/rake-13.0.6/lib/rake/rake_test_loader.rb:6:in `<main>'
12: from /Users/dentarg/.gem/ruby/2.7.6/gems/rake-13.0.6/lib/rake/rake_test_loader.rb:6:in `select'
11: from /Users/dentarg/.gem/ruby/2.7.6/gems/rake-13.0.6/lib/rake/rake_test_loader.rb:21:in `block in <main>'
10: from /Users/dentarg/.gem/ruby/2.7.6/gems/rake-13.0.6/lib/rake/rake_test_loader.rb:21:in `require'
9: from /Users/dentarg/starkast/wikimum/test/unit/markup_test.rb:4:in `<top (required)>'
8: from /Users/dentarg/starkast/wikimum/test/unit/markup_test.rb:4:in `require_relative'
7: from /Users/dentarg/starkast/wikimum/lib/services/markup.rb:3:in `<top (required)>'
6: from /Users/dentarg/starkast/wikimum/lib/services/markup.rb:3:in `require'
5: from /Users/dentarg/.gem/ruby/2.7.6/gems/html-pipeline-2.14.2/lib/html/pipeline.rb:3:in `<top (required)>'
4: from /Users/dentarg/.gem/ruby/2.7.6/gems/html-pipeline-2.14.2/lib/html/pipeline.rb:3:in `require'
3: from /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri.rb:10:in `<top (required)>'
2: from /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri.rb:10:in `require_relative'
1: from /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/extension.rb:7:in `<top (required)>'
/Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/extension.rb:7:in `require_relative': cannot load such file -- /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/2.7/nokogiri (LoadError)
14: from /Users/dentarg/.gem/ruby/2.7.6/gems/rake-13.0.6/lib/rake/rake_test_loader.rb:6:in `<main>'
13: from /Users/dentarg/.gem/ruby/2.7.6/gems/rake-13.0.6/lib/rake/rake_test_loader.rb:6:in `select'
12: from /Users/dentarg/.gem/ruby/2.7.6/gems/rake-13.0.6/lib/rake/rake_test_loader.rb:21:in `block in <main>'
11: from /Users/dentarg/.gem/ruby/2.7.6/gems/rake-13.0.6/lib/rake/rake_test_loader.rb:21:in `require'
10: from /Users/dentarg/starkast/wikimum/test/unit/markup_test.rb:4:in `<top (required)>'
9: from /Users/dentarg/starkast/wikimum/test/unit/markup_test.rb:4:in `require_relative'
8: from /Users/dentarg/starkast/wikimum/lib/services/markup.rb:3:in `<top (required)>'
7: from /Users/dentarg/starkast/wikimum/lib/services/markup.rb:3:in `require'
6: from /Users/dentarg/.gem/ruby/2.7.6/gems/html-pipeline-2.14.2/lib/html/pipeline.rb:3:in `<top (required)>'
5: from /Users/dentarg/.gem/ruby/2.7.6/gems/html-pipeline-2.14.2/lib/html/pipeline.rb:3:in `require'
4: from /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri.rb:10:in `<top (required)>'
3: from /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri.rb:10:in `require_relative'
2: from /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/extension.rb:4:in `<top (required)>'
1: from /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/extension.rb:30:in `rescue in <top (required)>'
/Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/extension.rb:30:in `require': dlopen(/Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/nokogiri.bundle, 0x0009): tried: '/Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/nokogiri.bundle' (mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e))) - /Users/dentarg/.gem/ruby/2.7.6/gems/nokogiri-1.13.6/lib/nokogiri/nokogiri.bundle (LoadError)
rake aborted! I know chruby 1.0.0 will bring changes to |
@dentarg Indeed, this is a clear real-world example of why sharing gem homes is problematic and AFAIK the only completely safe and solution is to just let gems be installed inside that Ruby's prefix, i.e., the default, which chruby unfortunately overrides. I am thinking to make my own Ruby switcher based on chruby for that, but I'm not sure I have the time. |
@postmodern It has been 3 years since #419. Do you plan to release chruby 1.0.0 one day? This bug existing since 3 years and having no release fixing it seems to clearly indicate chruby is completely unmaintained. This is very unfortunate given how widely chruby is used. What are your concerns? |
@eregon I am currently busy working on another large refactoring project, before I can circle back around and work on chruby. I have not yet heard of other people having this issue besides you or other truffleruby developers. I am just curious, if this is such a critical issue, why can't truffleruby just workaround the problem? Currently, I do not plan on optionally not setting |
For instance:
TruffleRuby already spent significant amount of effort to workaround this chruby bug. What workaround are you thinking of? I don't think truffleruby can workaround chruby setting the GEM_HOME incorrectly. |
That would be nice. The defaults needs to change though, because the current GEM_HOME/GEM_PATH set by chruby are incorrect for all dev Rubies, and all non-CRuby. In other words, it only works for CRuby releases, in the case they are always built with the same flags (e.g., --enable-shared) and arch for a given release version on the same machine. It also fails for CRuby releases on platforms with multiple archs as said in #422 (comment) and postmodern/ruby-install#413 (comment). |
I can verify that in my work on the YJIT team, and especially for speed.yjit.org, we have difficulties when shared dirs contain built native extensions. We handle this by deleting all gems in all shared directories on every build, as well as all built Ruby dirs we'll be using for that build. In general, my experience is that Rubygems/Bundler/etc deal poorly with trying to match up specific built native extensions to specific Rubies. So for benchmarking we use a Big Hammer to handle the situation: we delete everything, so there is clearly nothing stale or inappropriately shared. This problem isn't unique to chruby, though we do have it when using chruby. We're a hard case - we build a lot of prerelease Rubies that all have the same version string, so RUBY_VERSION checking does nothing for us. We're prone to get crashes, slowdowns and other problems very regularly if we leave built gems sitting around. So we basically treat shared-across-multiple-Rubies gem dirs as a bug, and delete their contents when there's reason to care. To preempt the same question: we do indeed work around the problem, by deleting everything. We need a fresh gem install of all native extensions for every build regardless, so saving old copies wouldn't do us any good. If we wanted shorter runs that didn't take multiple hours, or to reuse the same prerelease Ruby for multiple runs, we'd work around it by fiddling with dirs like GEM_HOME every time we changed versions. But if we need to manually manage our gem-related env vars every time we switch Rubies, chruby becomes a much less valuable tool. |
?? – I'm no truffleruby developer :) Just a developer doing things with Ruby. I've been a devote and happy chruby user for 10 years (yes, since start almost), but sadly, I no longer recommend friends and co-workers to use the released version of chruby. I now recommend people using eregon's branch. It would be great to change that. |
As a compromise and to get the changes released faster, I am thinking of adding a separate As per @dentarg's use case of wanting to switch between aarm64 and x86-64 on Apple Silicon, I could also add a Testing the same ruby version with different configurations or switching between aarch64 and x86-64 on specific hardware are niche use-cases vs. your more common Ruby app development. Providing opt-in solutions seems like a good compromise. Depending on whether these opt-in solutions become popular, they might become the default behavior in 1.0.0. |
I have to disagree that multiple architechtures are niche use cases. there are searches for it all over the web since apple silicone and rosetta have become main staple development machines. it has become a necessity even for many |
I often invoke a ruby command from another ruby for benchmark reasons, which results in pointing to a wrong In addition, I have the same problem as eregon; I develop ruby itself. I often have multiple installations of the same ruby version with different build flags. When build flags are different, I want them to not share the same extensions. I want to unset All in all, if you contribute to or benchmark a ruby implementation and install that under a writable directory, you shouldn't set |
By the way, I was using master branch of chruby, which is why I didn't notice 1.0.0 branch has #419. It does address the latter concern in my comment, but the former concern remains. So it'd be nice to have a way to keep |
TBH I'm really annoyed about this, I spent a large amount of time to try to fix this in a way that pleases @postmodern in chruby, spent time to discuss the proper solution in RubyGems (where the general agreement has become to use the default gem home unless it's not writable, exactly the same behavior I proposed for chruby in #431), but my PR is just hidden on a branch and not the best approach (which is to not set GEM_HOME) and chruby feels very much unmaintained. I think it's time I hard fork chruby and create a more sensible and actually maintained and sound Ruby switcher. The fact that chruby keeps an incorrect GEM_HOME for years without doing anything for its users seems unbelievable (also tracked as #451). The issue has been known for 4 years now. |
BTW, this ABI check which now exists in TruffleRuby and CRuby has caused various issues and complications. Was it not for chruby and this long-time bug we would probably not need this ABI check. So while that's not chruby's direct doing, it's partly a consequence of not fixing this bug. |
@eregon like we have discussed on multiple occasions, changing the path of the I would have accepted #451, however I am very hesitant about adding additional bifurcating logic. I could envision scenarios where you are debugging an issue for a use and you need to determine if the gems are being installed into the correct location, so you then have to determine if the ruby's gem directory is writable or not in order to determine if Since I am now considering a different approach to handling Example Code# potentially defined in a `gems.sh` or `gem_home.sh` file
function chruby_gems_set()
{
export GEM_HOME="$HOME/.gem/$RUBY_ENGINE/$RUBY_VERSION" # could be extracted into another function in case people want to configure the `GEM_HOME` template string
export GEM_PATH="$GEM_HOME${GEM_ROOT:+:$GEM_ROOT}${GEM_PATH:+:$GEM_PATH}"
export PATH="$GEM_HOME/bin:$PATH"
}
# potentially defined in a `gems.sh` or `gem_home.sh` file
function chruby_post_hook() { chruby_set_gem_home }
function chruby_set()
{
# add the $ruby/bin directory to PATH and query the ruby's information
# ...
chruby_post_hook
} Sorry for not working on the 1.0.0 branch. I have been extremely busy over the last four-six years, with both commercial work (2014-2020) and other Open Source work (2020-2023). I will start working on 1.0.0 again; I just added relisting of rubies directories. |
FYI: #487 is now merged to 0.4.0 branch. |
I would like a way to tell chruby to not set
$GEM_*
variables, as this is much safer (i.e., does not mix gems of different Ruby implementations) when e.g., developing TruffleRuby and executing two different Rubies without achruby
in between (see #410 (comment)).Currently I'm doing this by using a branch on my chruby fork, removing the code that sets
GEM_HOME
, but that's obviously not very convenient or maintainable, and I can't easily advise other TruffleRuby developers to do the same. I'd much rather this was possible in chruby itself.Actually, there is already a way to do this, by running everything as
root
, but that's obviously not very safe for my use-case.So I'm thinking to just extend the check
if (( UID != 0 )); then
to something likeif (( UID != 0 )) && [ "$CHRUBY_SET_GEM_HOME" != "false" ]; then
.We could also automatically just detect if
$RUBY_ROOT
is under$HOME
and not set$GEM_*
vars in that case, but @postmodern had some concerns about that in #410 (comment):@postmodern @havenwood What do you think?
I would like to have this available in chruby 1.0.0, I'm happy to make a PR.
The text was updated successfully, but these errors were encountered: