Skip to content
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

Platform comparison mixing libc families #3174

Closed
1 of 5 tasks
fauno opened this issue Mar 13, 2020 · 16 comments · Fixed by #4082 or #5852
Closed
1 of 5 tasks

Platform comparison mixing libc families #3174

fauno opened this issue Mar 13, 2020 · 16 comments · Fixed by #4082 or #5852

Comments

@fauno
Copy link

fauno commented Mar 13, 2020

Hi! After #2918 and #2922, I've extended my own gem repository to contain glibc-linked gems also, and found out that in a machine with glibc, where the platform is x86_64-linux, bundler installs x86_64-linux-musl gems as if they were compatible. I checked again and found out this on rubygems/platform.rb:

  ##
  # Does +other+ match this platform?  Two platforms match if they have the
  # same CPU, or either has a CPU of 'universal', they have the same OS, and
  # they have the same version, or either has no version.
  #
  # Additionally, the platform will match if the local CPU is 'arm' and the
  # other CPU starts with "arm" (for generic ARM family support).

  def ===(other)

The "or either has no version" bit was the one that ends up comparing x86_64-linux to x86_64-linux-musl and finding them equal. I patched the version check to @version == other.version and bundler installed the gem from the correct platform, but I'm wondering if it's ok to submit this patch as a PR since the documentation was so specific about it. Could you clarify? Thanks!

This issue is related to:

  • Network problems
  • Installing a library
  • Publishing a library
  • The command line gem
  • Other

Here are my current environment details:

$ gem env version
3.0.3

I will abide by the code of conduct.

@lloeki
Copy link
Contributor

lloeki commented Nov 23, 2020

I report the same issue.

I produced libv8-node builds for the following platforms, published s such:

  • x86_64-darwin-19
  • x86_64-darwin-20
  • x86_64-linux (IOW glibc-based)
  • x86_64-linux-musl
  • x86_64-solaris-2.11

On the gem production side, just to be able to properly produce the correct x86_64-linux-musl, I had to perform the following hack for ruby versions < 2.7 (I believe this is due to a rubygems change, which turns out to be bundled starting with ruby 2.7):

  def binary_gemspec(platform = Gem::Platform.local, str = RUBY_PLATFORM)
    platform.instance_eval { @version = 'musl' } if str =~ /-musl/ && platform.version.nil?

    gemspec = eval(File.read('libv8-node.gemspec'))
    gemspec.platform = platform
    gemspec
  end

  def binary_gem_name(platform = Gem::Platform.local)
    File.basename(binary_gemspec(platform).cache_file)
  end

On the gem consumption side, gem install libv8-node will install either the -linux one or the -linux-musl one, depending on whatever the order of search results happens to be.

This is a real problem for e.g mini_racer to depend on libv8 and have the distinction made between musl and glibc, and part of why we had to fork it into sq_mini_racer which does not explicitly depends on libv8/libv8-node but has its own search and resolution implementation against the rubygems.org API.

@fauno
Copy link
Author

fauno commented Nov 23, 2020

On the gem production side, just to be able to properly produce the correct x86_64-linux-musl, I had to perform the following hack for ruby versions < 2.7 (I believe this is due to a rubygems change, which turns out to be bundled starting with ruby 2.7):

It's due to a previous patch I submitted that was accepted and bundled with ruby 2.7, that made this one come up

@lloeki
Copy link
Contributor

lloeki commented Nov 23, 2020

Yup, the hack is only necessary for versions of rubygems before your fix, so thanks for that!

@lloeki
Copy link
Contributor

lloeki commented Nov 24, 2020

Regarding the "or either has no version" thing, I think this is e.g for darwin or solaris, so that maybe you can have a gem published as x86_64-darwin or x86_64-solaris and it can be installed regardless of the version, e.g on x86_64-darwin-{17,18,19,20}.

As for linux, while it's possible to build binaries that do run on both glibc and musl, it's fairly involved and requires extreme care (e.g at the very least strict conformance to POSIX and disabling any GNU extension when building it with GCC among other things) which which makes it impractical to assume that linux, nil should match as a wildcard in that case. Also there may be some other libc such as uclibc.

So, pragmatically today, it seems that linux is strictly equal to linux-glibc at large, a fact largely confirmed by Alpine's intentional behaviour of dropping binary gems mentioned by @fauno.

Thus I'm currently attempting a patch, and ultimately a PR, implementing the following:

  • preserve the version nil wildcard for non-linux platforms, just in case
  • ensure linux === linux-glibc and no other
  • ensure linux-foo === linux-foo and no other

lloeki added a commit to lloeki/rubygems that referenced this issue Nov 24, 2020
Attempting to install a gem published as both *-linux and *-linux-musl
results in the incorrect gem being picked up, causing build failures due
to binary incompatibility. This is caused by the `nil` wildcard
swallowing the libc information upon version comparison.

Handle the linux case by performing only non-wildcard equality on the
version and asserting 'gnu' and nil equivalence, while preserving the
current behaviour for other OSes.

Followup to rubygems#2922
Closes rubygems#3174
@lloeki
Copy link
Contributor

lloeki commented Nov 24, 2020

@fauno I opened the PR above, in hopes it would solve this issue, WDYT?

@fauno
Copy link
Author

fauno commented Nov 24, 2020

I messed up something with the patch so I'm editing this comment out :)

@fauno
Copy link
Author

fauno commented Nov 24, 2020

It works! +1

lloeki added a commit to lloeki/rubygems that referenced this issue Feb 18, 2021
Attempting to install a gem published as both *-linux and *-linux-musl
results in the incorrect gem being picked up, causing build failures due
to binary incompatibility. This is caused by the `nil` wildcard
swallowing the libc information upon version comparison.

Handle the linux case by performing only non-wildcard equality on the
version and asserting 'gnu' and nil equivalence, while preserving the
current behaviour for other OSes.

Followup to rubygems#2922
Closes rubygems#3174
lloeki added a commit to lloeki/rubygems that referenced this issue Mar 2, 2021
Attempting to install a gem published as both *-linux and *-linux-musl
results in the incorrect gem being picked up, causing build failures due
to binary incompatibility. This is caused by the `nil` wildcard
swallowing the libc information upon version comparison.

Handle the linux case by performing only non-wildcard equality on the
version and asserting 'gnu' and nil equivalence, while preserving the
current behaviour for other OSes.

Followup to rubygems#2922
Closes rubygems#3174
@lloeki
Copy link
Contributor

lloeki commented Mar 24, 2021

@deivid-rodriguez now that #4082 is reverted, can you reopen this issue for better tracking of what we agreed upon? (I'm going to start tackling this this week)

@fauno
Copy link
Author

fauno commented Mar 24, 2021

Hi! Please let me know if I can help with something :)

lloeki added a commit to lloeki/rubygems that referenced this issue Mar 24, 2021
Attempting to install a gem published as both *-linux and *-linux-musl
results in the incorrect gem being picked up, causing build failures due
to binary incompatibility. This is caused by the `nil` wildcard
swallowing the libc information upon version comparison.

Handle the linux case by performing only non-wildcard equality on the
version and asserting 'gnu' and nil equivalence, while preserving the
current behaviour for other OSes.

Followup to rubygems#2922
Closes rubygems#3174
texpert added a commit to texpert/florsan that referenced this issue Apr 13, 2021
texpert added a commit to texpert/florsan that referenced this issue Apr 13, 2021
texpert added a commit to texpert/florsan that referenced this issue Apr 16, 2021
@lloeki
Copy link
Contributor

lloeki commented Oct 13, 2021

Sorry folks, it's been a bit of a hellhole for me, so just a ping that I have a lot of things to clear up but I'm not forgetting about this.

@fauno
Copy link
Author

fauno commented Oct 18, 2021

Just got notified Alpine 3.15 is going to reenable the musl platform, but not sure which bundler version is going to include: https://gitlab.alpinelinux.org/alpine/aports/-/issues/10808

@lloeki
Copy link
Contributor

lloeki commented Nov 8, 2021

It seems like the Ruby 3.x Docker images (which have a recent rubygems + bundler) behave correctly (or at least more correctly than before).

Got some reasonable backport for people stuck with the official Docker images that have rubygems 3.0 + bundler 1.17 and can't update them due to e.g rails 4.x-5.1 bundler < 2.0 constraint.

https://gist.github.com/lloeki/12dcf61324f64a2fa1e8a8b2109c1f00

@lloeki
Copy link
Contributor

lloeki commented Nov 10, 2021

at least more correctly than before

Well, there are apparently still some situations where recent rubygems+bundler trip up and decide to fetch linux-musl on linux.

I was starting to wonder if this issue was still relevant, but I guess it definitely is.

@eregon
Copy link
Contributor

eregon commented May 3, 2022

Yes, this still happens: #5508
Incorrectly using linux-muslc on glibc systems (the current situation) seems worse than not using -linux gems on Alpine which uses musl (#4434).

Maybe we can do a quick fix that just always prevents -linux-musl to be used on a -linux system? That's always wrong.

@ShepFc3
Copy link

ShepFc3 commented May 26, 2022

I'm experiencing this on the latest ruby alpine image. Are there any workarounds to get this working properly? I've followed all the linked cases and it appears this is still an issue.

CvX added a commit to CvX/licensed that referenced this issue Jul 30, 2022
mini_racer 0.3.1 isn't compatible with more recent macOS versions (in part due to lack of python 2) which made `script/setup` fail with:

```
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/cvx/dev/licensed/test/fixtures/bundler/vendor/gems/ruby/2.7.0/gems/libv8-8.4.255.0/ext/libv8
/Users/cvx/.rubies/ruby-2.7.6/bin/ruby -I /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0 extconf.rb
creating Makefile
/Users/cvx/dev/licensed/test/fixtures/bundler/vendor/gems/ruby/2.7.0/gems/libv8-8.4.255.0/ext/libv8/builder.rb:57:in `setup_python!': libv8 requires python 2 to be installed in order to build, but it is currently
3.9.13 (RuntimeError)
	from /Users/cvx/dev/licensed/test/fixtures/bundler/vendor/gems/ruby/2.7.0/gems/libv8-8.4.255.0/ext/libv8/builder.rb:39:in `build_libv8!'
	from /Users/cvx/dev/licensed/test/fixtures/bundler/vendor/gems/ruby/2.7.0/gems/libv8-8.4.255.0/ext/libv8/location.rb:24:in `install!'
	from extconf.rb:7:in `<main>'

extconf failed, exit code 1

Gem files will remain installed in /Users/cvx/dev/licensed/test/fixtures/bundler/vendor/gems/ruby/2.7.0/gems/libv8-8.4.255.0 for inspection.
Results logged to /Users/cvx/dev/licensed/test/fixtures/bundler/vendor/gems/ruby/2.7.0/extensions/arm64-darwin-21/2.7.0-static/libv8-8.4.255.0/gem_make.out

  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/rubygems/ext/builder.rb:102:in `run'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/rubygems/ext/ext_conf_builder.rb:28:in `build'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/rubygems/ext/builder.rb:171:in `build_extension'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/rubygems/ext/builder.rb:205:in `block in build_extensions'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/rubygems/ext/builder.rb:202:in `each'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/rubygems/ext/builder.rb:202:in `build_extensions'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/rubygems/installer.rb:851:in `build_extensions'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/rubygems_gem_installer.rb:72:in `build_extensions'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/rubygems_gem_installer.rb:28:in `install'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/source/rubygems.rb:207:in `install'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/installer/gem_installer.rb:54:in `install'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/installer/gem_installer.rb:16:in `install_from_spec'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/installer/parallel_installer.rb:186:in `do_install'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/installer/parallel_installer.rb:177:in `block in worker_pool'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/worker.rb:62:in `apply_func'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/worker.rb:57:in `block in process_queue'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/worker.rb:54:in `loop'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/worker.rb:54:in `process_queue'
  /Users/cvx/.rubies/ruby-2.7.6/lib/ruby/site_ruby/2.7.0/bundler/worker.rb:91:in `block (2 levels) in create_threads'

An error occurred while installing libv8 (8.4.255.0), and Bundler cannot continue.

In Gemfile:
  mini_racer was resolved to 0.3.1, which depends on
    libv8
Encountered an error running script/source-setup/bundler.
```

Updating it caused a different problem - a bug in bundler caused it to install both `linux` and `linux-musl` variants in the CI environment. (see: rubyjs/libv8-node#5 and rubygems/rubygems#3174)

This instead replaces `mini_racer` example with `loofah`. That gem depends on `nokogiri` which provides different binary variants, like `libv8`/`libv8-node` did.

But this one builds properly on macOS and does not provide `linux-musl` variant so it should not cause any issues on CI.
@deivid-rodriguez
Copy link
Member

This will be fixed by #5852, sorry it took so long!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants