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

Fix regression when installing native extensions on universal rubies #7077

Merged
merged 2 commits into from
Nov 8, 2023

Conversation

hanyang-tony
Copy link
Contributor

@hanyang-tony hanyang-tony commented Oct 19, 2023

Since #6945 the extension dir changed to Gem::BasicSpecification's implementation, we didn't hook that in rubygems_ext.rb. So for universal rubies, we ended up using the universal platform name when installing, but arch replaced platform name when checking. This lead to native extensions can never be correctly installed on universal rubies.

Hook Gem::BasicSpecifications so the behavior is consistent on installing and checking.

What was the end-user or developer problem that led to this PR?

For universal rubies, the change from #6945 to def gem_build_complete_path is incorrect. Previously, extension_dir is invoked on the Bundler::StubSpecification, which is a child class of Specification. After the change to stub.gem_build_complete_path, @Stub is actually an instance of Gem::StubSpecification, thus gem_build_complete_path is from Gem::BasicSpecification.

The problem arise when in bundler, we replace the 'universal' part of Gem::Platform with the arch. But we still use the universal name for Gem::Specification, this is defined in 'rubygems_ext.rb'. Now the stub is using extension_dir defined in Gem::BasicSpecification, so the 'universal' part ended up being swapped by arch.

So, we install native extensions to 'extensions/universal-darwin-22/', but finding them in 'extensions/x86_64-darwin-22/'. Leading to native extension gems can never be installed on universal ruby.

What is your fix for the problem, implemented in this PR?

Hook Gem::BasicSpecifications so the behavior is consistent on installing and checking.

Make sure the following tasks are checked

@welcome
Copy link

welcome bot commented Oct 19, 2023

Thanks for opening a pull request and helping make RubyGems and Bundler better! Someone from the RubyGems team will take a look at your pull request shortly and leave any feedback. Please make sure that your pull request has tests for any changes or added functionality.

We use GitHub Actions to test and make sure your change works functionally and uses acceptable conventions, you can review the current progress of GitHub Actions in the PR status window below.

If you have any questions or concerns that you wish to ask, feel free to leave a comment in this PR or join our #rubygems or #bundler channel on Slack.

For more information about contributing to the RubyGems project feel free to review our CONTRIBUTING guide

@segiddins
Copy link
Member

Looks good, mind adding a spec for the scenario that this addresses?

@hanyang-tony
Copy link
Contributor Author

hanyang-tony commented Oct 20, 2023

I realized we can avoid code duplication by changing class Specification to class BasicSpecification, since the former is a subclass of the latter. Also added a spec to test if StubSpecification's extensions_dir equals Specifications.

@hanyang-tony
Copy link
Contributor Author

Looks good, mind adding a spec for the scenario that this addresses?

Done :)

@deivid-rodriguez
Copy link
Member

@hanyang-tony I tried reverting the fix here, and the spec still passes. Can you have a look?

@hanyang-tony
Copy link
Contributor Author

@hanyang-tony I tried reverting the fix here, and the spec still passes. Can you have a look?

Sorry, I was testing the wrong method. I've fixed it now. Due to the nature of how the Gem::StubSpecification::StubLine is loaded, I have to include a separate gemspec file instead of inline it in spec test. Please check it out.

@deivid-rodriguez
Copy link
Member

Maybe I'm crazy but the new spec is still passing without this fix?

@hanyang-tony
Copy link
Contributor Author

Maybe I'm crazy but the new spec is still passing without this fix?

This is a fix for 'universal ruby', Gem::Platform.local.cpu should be 'universal'. Other versions of ruby don't have this issue.

@deivid-rodriguez
Copy link
Member

deivid-rodriguez commented Oct 31, 2023

Ideally we'd find a way to test this in our CI, to avoid regressions, even if by mocking the platform somehow. Let's ship the bug fix though for now.

Since rubygems#6945 the extension dir changed to Gem::BasicSpecification's implementation, we didn't hook that in rubygems_ext.rb. So for universal rubies, we ended up using the universal platform name when installing, but arch replaced platform name when checking. This lead to native extensions can never be correctly installed on universal rubies.

Hook Gem::BasicSpecifications so the behavior is consistent on installing and checking.
@hanyang-tony
Copy link
Contributor Author

Ideally we'd find a way to test this in our CI, to avoid regressions, even if by mocking the platform somehow. Let's ship the bug fix though for now.

It's possible to hook Platform.local into universal ruby in this spec. Or add a workflow that hook it first then run the specs.

@hanyang-tony
Copy link
Contributor Author

I've fixed the linting error, can we re-run the actions?

@hanyang-tony
Copy link
Contributor Author

Can we re-run the failed test? Seems like it was not caused by the changes in this PR.

@deivid-rodriguez deivid-rodriguez changed the title Ensure we are using the same extension dir Fix regression when installing native extensions on universal rubies Nov 8, 2023
@deivid-rodriguez
Copy link
Member

Ok, let's ship this as is.

It's possible to hook Platform.local into universal ruby in this spec. Or add a workflow that hook it first then run the specs.

Would happily accept such a test to cover this 👍.

@deivid-rodriguez deivid-rodriguez merged commit d79c609 into rubygems:master Nov 8, 2023
92 checks passed
deivid-rodriguez added a commit that referenced this pull request Nov 8, 2023
Fix regression when installing native extensions on universal rubies

(cherry picked from commit d79c609)
deivid-rodriguez added a commit that referenced this pull request Nov 8, 2023
Fix regression when installing native extensions on universal rubies

(cherry picked from commit d79c609)
deivid-rodriguez added a commit that referenced this pull request Nov 8, 2023
Fix regression when installing native extensions on universal rubies

(cherry picked from commit d79c609)
deivid-rodriguez added a commit that referenced this pull request Nov 8, 2023
Fix regression when installing native extensions on universal rubies

(cherry picked from commit d79c609)
@Bo98
Copy link
Contributor

Bo98 commented Nov 11, 2023

It's possible to hook Platform.local into universal ruby in this spec

You could take inspiration from 11229b1 which uses simulate_platform and simulate_ruby_platform.

@hanyang-tony
Copy link
Contributor Author

It's possible to hook Platform.local into universal ruby in this spec

You could take inspiration from 11229b1 which uses simulate_platform and simulate_ruby_platform.

I tried to use simulate_ruby_platform, but it doesn't work in this case. Because the RUBY_PLATFORM isn't used directly by this spec, it's the hook in rubygems_ext.rb that make use of it. The hook only run once, before the spec is run, so change the platform in spec doesn't do anything.

@Bo98
Copy link
Contributor

Bo98 commented Nov 15, 2023

Yeah it's designed to work when running a Bundle process (install_gemfile) rather than direct method calls. So if the problem can be translated to a real world steps to reproduce then we could test that. Was the problem revealed from doing a bundle exec after an install? The existing tests only tested the install.

@hanyang-tony
Copy link
Contributor Author

The regression caused bundler to search gem extension in a different directory than the one which it was installed. The existing tests could work if the tested gem has native extension.

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

Successfully merging this pull request may close these issues.

None yet

4 participants