Skip to content

Ignore warnings with spec different platforms#8508

Merged
hsbt merged 2 commits intomasterfrom
ignore-spec-different-platfroms
Apr 2, 2026
Merged

Ignore warnings with spec different platforms#8508
hsbt merged 2 commits intomasterfrom
ignore-spec-different-platfroms

Conversation

@hsbt
Copy link
Copy Markdown
Member

@hsbt hsbt commented Feb 19, 2025

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

I'm working to provide shared GEM_HOME for all of Ruby versions and platforms.

If I used CRuby and jruby-launcher gem with that environment, RubyGems warns the following:

Source locally installed gems is ignoring #<Bundler::StubSpecification name=jruby-launcher version=1.1.19 platform=java> because it is missing extensions

In another case, I use JRuby and run gem -v. RubyGems warns all of C extension gem:

Ignoring RedCloth-4.3.4 because its extensions are not built. Try: gem pristine RedCloth --version 4.3.4
Ignoring RedCloth-4.3.3 because its extensions are not built. Try: gem pristine RedCloth --version 4.3.3
Ignoring RedCloth-4.3.2 because its extensions are not built. Try: gem pristine RedCloth --version 4.3.2
Ignoring aliyun-sdk-0.8.0 because its extensions are not built. Try: gem pristine aliyun-sdk --version 0.8.0
Ignoring amatch-0.4.1 because its extensions are not built. Try: gem pristine amatch --version 0.4.1
...

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

I skip to warn with these cases.

TODO

write test code and consider to another cases.

Make sure the following tasks are checked

@deivid-rodriguez
Copy link
Copy Markdown
Contributor

This sounds like #3520. A plan for making this work was sketched at #7372, just never implemented.

@hsbt hsbt force-pushed the ignore-spec-different-platfroms branch 4 times, most recently from c316ba9 to c5b7fb4 Compare February 20, 2025 07:33
@hsbt hsbt marked this pull request as ready for review February 20, 2025 08:16
@hsbt
Copy link
Copy Markdown
Member Author

hsbt commented Feb 20, 2025

/cc @headius

@deivid-rodriguez
Copy link
Copy Markdown
Contributor

For what it's worth, I don't think this is the right fix because it will hide all instances of this warning in JRuby, not just the ones that are actually false positives. I'd prefer that we work on a proper solution.

@hsbt
Copy link
Copy Markdown
Member Author

hsbt commented Feb 20, 2025

I don't imagine missing_extension? is true with JRuby platform. Do you have example for that?

@deivid-rodriguez
Copy link
Copy Markdown
Contributor

If a extension builds specific artifacts only under JRuby, but does not build those artifacts when installed under a different implementation, then if you switch to JRuby, you can't use the installation as is, but the artifacts will need to be built for JRuby, right?

For example, will jruby-launcher extension work on JRuby if installed under non-jruby?

warn "Source #{source} is ignoring #{self} because it is missing extensions"
# If we share GEM_HOME for all of Ruby platform, the platform specific gem always warn that specification.
# ex `jruby-launcher` and CRuby
if platform == Gem::Platform::RUBY && RUBY_ENGINE != "jruby"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this only limited to jruby?

@headius
Copy link
Copy Markdown
Contributor

headius commented Apr 9, 2025

Sorry I missed this for a while. Answers to some questions:

I don't think this is the right fix because it will hide all instances of this warning in JRuby

In general, extensions built for one configuration of JRuby (JRuby version plus Java version) will work on any other configuration. We do not expose a version-specific C API, so there's nothing to recompile, and Java-based extensions are shipped in a pre-built form. Unless an extension is using Java version-specific APIs (I don't know of any that do this), we do not need separate builds for each configuration.

For example, will jruby-launcher extension work on JRuby if installed under non-jruby?

jruby-launcher is a "-java" platform gem, so I don't expect CRuby users will ever install it. But even if they did, it just builds a plain C-based executable that has no dependencies on a specific JRuby or JVM version.

Why is this only limited to jruby?

Basically, this extension warning makes no sense for JRuby, because:

  • Gems that contain Java extensions should ship them pre-compiled. Changing JRuby or Java version should have no effect on these.
  • Gems that actually build something when installed in JRuby don't depend on any version-specific API like they do in CRuby. Usually, they produce a standalone dll or executable that will work across JRuby+Java configurations.
  • Gems that generate a stub makefile (and build nothing) obviously don't need this check at all.

Basically, gems with native code installed on JRuby should work on just about any supported configuration of JRuby + Java. The warning is (almost always?) useless for us.

I got sick of seeing these warnings again today and was about to monkey-patch RubyGems to stop producing this warning, but this PR would probably be a better option.

(Edit: "exceptions" => "extensions")

@headius
Copy link
Copy Markdown
Contributor

headius commented Apr 9, 2025

The jruby-launcher gem actually exposes another problem with this warning: it does not actually create an extension for the missing_extension? check to find. Instead, it just builds an executable that it installs in $JRUBY_HOME/bin/jruby:

[] tmp $ gem install jruby-launcher
Fetching jruby-launcher-2.0.0-java.gem
Building native extensions. This could take a while...
Successfully installed jruby-launcher-2.0.0-java
Parsing documentation for jruby-launcher-2.0.0-java
Installing ri documentation for jruby-launcher-2.0.0-java
Done installing documentation for jruby-launcher after 1 seconds
1 gem installed
[] tmp $ bundle                    
Source locally installed gems is ignoring #<Bundler::StubSpecification name=jruby-launcher version=2.0.0.pre2 platform=java> because it is missing extensions
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

So there's basically no way to avoid this warning when using bundler and the jruby-launcher gem.

@headius
Copy link
Copy Markdown
Contributor

headius commented Apr 9, 2025

So there's basically no way to avoid this warning when using bundler and the jruby-launcher gem.

Oops, I did not notice it was complaining about the "2.0.0.pre2" version of the jruby-launcher gem, so that was a red herring. But it is still a problem when switching Java versions, even though the installed executable works just fine:

[] tmp $ jruby -v                  
jruby 10.0.0.0-SNAPSHOT (3.4.2) 2025-04-09 e2909f9baf OpenJDK 64-Bit Server VM 21.0.5+11-LTS on 21.0.5+11-LTS +indy +jit [arm64-darwin]
[] tmp $ gem install jruby-launcher
Building native extensions. This could take a while...
Successfully installed jruby-launcher-2.0.0-java
Parsing documentation for jruby-launcher-2.0.0-java
Done installing documentation for jruby-launcher after 0 seconds
1 gem installed
[] tmp $ bundle   
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
[] tmp $ pickjdk 24
/Library/Java/JavaVirtualMachines/jdk-24.jdk/Contents/Home
[] tmp $ bundle
Fetching gem metadata from https://rubygems.org/.
Source rubygems repository https://rubygems.org/ or installed locally is ignoring #<Bundler::StubSpecification name=resolv version=0.6.0 platform=ruby> because it is missing extensions
Source rubygems repository https://rubygems.org/ or installed locally is ignoring #<Bundler::StubSpecification name=jruby-launcher version=2.0.0 platform=java> because it is missing extensions
Source rubygems repository https://rubygems.org/ or installed locally is ignoring #<Bundler::StubSpecification name=bindex version=0.8.1 platform=ruby> because it is missing extensions
Resolving dependencies...
Installing resolv 0.6.0 with native extensions
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

The main problem is when switching Java version, since that version gets baked into the extension dir and used for the missing check.

@hsbt hsbt force-pushed the ignore-spec-different-platfroms branch 4 times, most recently from 743b51b to ea0266e Compare June 12, 2025 08:59
@hsbt hsbt force-pushed the ignore-spec-different-platfroms branch from ea0266e to 8cca385 Compare June 27, 2025 04:51
@hsbt hsbt changed the title Ignore spec different platfroms Ignore warnings with spec different platfroms Jan 26, 2026
@hsbt hsbt force-pushed the ignore-spec-different-platfroms branch from 7148b2e to 90e7e04 Compare April 1, 2026 08:40
Copilot AI review requested due to automatic review settings April 1, 2026 08:40
@hsbt
Copy link
Copy Markdown
Member Author

hsbt commented Apr 1, 2026

I simplified this by having missing_extensions? always return false on JRuby. The check is unnecessary because Java extensions are shipped pre-compiled and don't need to be rebuilt across JRuby or Java versions.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to reduce noisy “missing extensions” warnings when using a shared GEM_HOME across multiple Ruby engines/platforms (e.g., CRuby + JRuby), especially when gems for other platforms are present.

Changes:

  • Special-cases JRuby by forcing missing_extensions? to return false in RubyGems Specification/StubSpecification and Bundler StubSpecification.
  • Updates RubyGems and Bundler test expectations to avoid stderr warnings on JRuby.
  • Adjusts several tests to branch on RUBY_ENGINE == "jruby".

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
lib/rubygems/specification.rb Alters missing_extensions? logic to return false on JRuby.
lib/rubygems/stub_specification.rb Alters stub missing_extensions? logic to return false on JRuby.
bundler/lib/bundler/stub_specification.rb Alters Bundler stub missing_extensions? logic to return false on JRuby.
test/rubygems/test_gem.rb Updates warning expectations for Gem.try_activate on JRuby.
test/rubygems/test_gem_stub_specification.rb Updates warning expectations and changes what is asserted on JRuby.
test/rubygems/test_gem_specification.rb Updates warning expectations and missing-extensions assertions on JRuby.
spec/bundler/stub_specification_spec.rb Updates Bundler stub specs expectations (but currently introduces a syntax error).
Comments suppressed due to low confidence (1)

bundler/lib/bundler/stub_specification.rb:60

  • On JRuby, forcing missing_extensions? to false means ignored? will also be false, so Bundler will include gems whose extensions were never built for the current platform/engine (and may later fail at runtime). To address the reported warning spam (including the CRuby+java-platform case), keep missing_extensions? semantics and gate the warning in ignored? on platform compatibility (similar to RubyGems' BasicSpecification#contains_requirable_file?), rather than disabling missing-extension detection entirely on JRuby.
    def missing_extensions?
      return false if RUBY_ENGINE == "jruby"
      return false if default_gem?
      return false if extensions.empty?
      return false if File.exist? gem_build_complete_path
      return false if manually_installed?


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# probably want to build_extensions

def missing_extensions?
return false if RUBY_ENGINE == "jruby"
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing_extensions? returning false unconditionally on JRuby changes behavior beyond silencing warnings: specs with unbuilt extensions will no longer be marked ignored, so they can be selected for activation/resolution even though their native bits are unavailable for the current platform/ABI (and commands like gem pristine --only-missing-extensions will stop working). Instead of short-circuiting missing_extensions? by engine, keep the missing-extension detection intact and suppress the warning in the caller(s) when the spec is for a different platform (or when running on non-CRuby engines).

Suggested change
return false if RUBY_ENGINE == "jruby"

Copilot uses AI. Check for mistakes.
end

def missing_extensions?
return false if RUBY_ENGINE == "jruby"
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JRuby early return in missing_extensions? prevents Gem::StubSpecification#ignored? from filtering out specs whose extensions are not built for the current platform, which can lead to incompatible gems being considered activatable under a shared GEM_HOME. This method should continue to report missing extensions based on gem_build_complete_path; if the goal is to avoid noisy output, adjust the warning site(s) instead (e.g., only warn when Gem::Platform.local === platform).

Suggested change
return false if RUBY_ENGINE == "jruby"

Copilot uses AI. Check for mistakes.
end

it "returns true if not manually_installed?" do
it "returns #{RUBY_ENGINE == "jruby" ? "false" : "true"} if not manually_installed?" do
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example description string is a syntax error because it uses unescaped double quotes inside a double-quoted string interpolation (RUBY_ENGINE == "jruby" ? ...). Use single quotes inside the interpolation, or build the description string without nested quotes.

Suggested change
it "returns #{RUBY_ENGINE == "jruby" ? "false" : "true"} if not manually_installed?" do
it "returns #{RUBY_ENGINE == 'jruby' ? 'false' : 'true'} if not manually_installed?" do

Copilot uses AI. Check for mistakes.
Comment on lines 69 to +75
stub_with_extension do |stub|
_, err = capture_output do
refute stub.contains_requirable_file? "nonexistent"
if RUBY_ENGINE == "jruby"
refute stub.ignored?
else
refute stub.contains_requirable_file? "nonexistent"
end
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JRuby branch stops exercising contains_requirable_file? entirely (it only checks ignored?), which weakens coverage of the behavior this test is named after. Prefer asserting refute stub.contains_requirable_file?("nonexistent") on all engines, and only vary the stderr expectation (empty vs warning) to verify the warning-suppression behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +1581 to +1585
if RUBY_ENGINE == "jruby"
refute @ext.ignored?
else
refute @ext.contains_requirable_file? "nonexistent"
end
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the stub-spec test, the JRuby branch no longer tests contains_requirable_file? and therefore doesn't validate the warning/no-warning behavior at the call site. Consider keeping the contains_requirable_file? assertion for JRuby as well, and only adjust the stderr expectation.

Suggested change
if RUBY_ENGINE == "jruby"
refute @ext.ignored?
else
refute @ext.contains_requirable_file? "nonexistent"
end
refute @ext.contains_requirable_file? "nonexistent"

Copilot uses AI. Check for mistakes.
Comment thread test/rubygems/test_gem.rb
Comment on lines +1307 to +1314
if RUBY_ENGINE == "jruby"
assert_equal "", err
else
expected = "Ignoring ext-1 because its extensions are not built. " \
"Try: gem pristine ext --version 1\n"

assert_equal expected, err
assert_equal expected, err
end
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test now expects no warning on JRuby, but the implementation change achieves that by disabling missing-extension detection entirely on JRuby (which can allow incompatible specs into activation). Once warning suppression is implemented at the warning site, update this test to verify that missing extensions are still detected/ignored while stderr remains quiet, instead of changing missing_extensions? semantics by engine.

Copilot uses AI. Check for mistakes.
Comment on lines +148 to +152
if RUBY_ENGINE == "jruby"
refute stub.missing_extensions?
else
assert stub.missing_extensions?
end
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These assertions now make missing_extensions? engine-dependent, but missing_extensions? is also used for correctness (filtering/pristine --only-missing-extensions), not just warnings. If the intent is only to silence warnings under cross-platform shared GEM_HOME, keep missing_extensions? reporting true when the current platform's gem.build_complete is absent and suppress the warning output separately.

Suggested change
if RUBY_ENGINE == "jruby"
refute stub.missing_extensions?
else
assert stub.missing_extensions?
end
assert stub.missing_extensions?

Copilot uses AI. Check for mistakes.
Comment on lines +4018 to +4022
if RUBY_ENGINE == "jruby"
refute @ext.missing_extensions?
else
assert @ext.missing_extensions?
end
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making missing_extensions? return false on JRuby changes core behavior and this test now codifies that change. If the desired behavior is “still ignore specs missing extensions, but don’t warn when those specs are effectively for another platform/engine”, adjust the warning logic and keep missing_extensions? consistent across engines; then this test should continue to expect @ext.missing_extensions? to be true before build_extensions.

Suggested change
if RUBY_ENGINE == "jruby"
refute @ext.missing_extensions?
else
assert @ext.missing_extensions?
end
assert @ext.missing_extensions?

Copilot uses AI. Check for mistakes.
@hsbt hsbt force-pushed the ignore-spec-different-platfroms branch 2 times, most recently from dd38baa to 6d73df9 Compare April 1, 2026 09:00
JRuby does not require extension rebuilds when switching JRuby or Java
versions because Java extensions are shipped pre-compiled and JRuby does
not expose a version-specific C API. This means missing_extensions?
returning true on JRuby is almost always a false positive and the
suggested `gem pristine` is not actionable.

Return false early from missing_extensions? on JRuby so that all
downstream warnings and ignored-spec filtering are suppressed at the
source rather than patching each warning site individually.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@hsbt hsbt force-pushed the ignore-spec-different-platfroms branch from 6d73df9 to 9fedee5 Compare April 2, 2026 01:35
When no gems have missing extensions (e.g. on JRuby where
missing_extensions? always returns false), display an informational
message instead of raising Gem::Exception.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@hsbt hsbt force-pushed the ignore-spec-different-platfroms branch from 9fedee5 to 738d2db Compare April 2, 2026 01:41
@hsbt hsbt merged commit 83ea8b8 into master Apr 2, 2026
97 checks passed
@hsbt hsbt deleted the ignore-spec-different-platfroms branch April 2, 2026 02:52
hsbt added a commit that referenced this pull request Apr 7, 2026
Ignore warnings with spec different platfroms

(cherry picked from commit 83ea8b8)
@hsbt hsbt changed the title Ignore warnings with spec different platfroms Ignore warnings with spec different platforms Apr 7, 2026
hsbt added a commit that referenced this pull request Apr 7, 2026
Ignore warnings with spec different platfroms

(cherry picked from commit 83ea8b8)
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.

5 participants