summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Dalessio <mike.dalessio@gmail.com>2022-12-15 21:01:04 +0000
committerGitHub <noreply@github.com>2022-12-16 06:01:04 +0900
commit66740bbe2e7867bbcb2f4e73b5e85277c4a21f9f (patch)
tree91158b44f7237275d93d540b8853faa678d8b0ad
parent8c907ac32f87bf16da6e84105fb4d6bf257e6bbd (diff)
downloadrake-compiler-66740bbe2e7867bbcb2f4e73b5e85277c4a21f9f.tar.gz
Add support for RubyGems 3.3.21 or later (#209)
Since Rubygems 3.3.21, the Gem::Platform name always contains the library version for gnu platforms. So where the rake-compiler config entries previously were: ```yaml --- rbconfig-x86_64-linux-gnu-2.7.0: "/usr/local/rake-compiler/ruby/x86_64-redhat-linux/ruby-2.7.0/lib/ruby/2.7.0/x86_64-linux-gnu/rbconfig.rb" rbconfig-x86_64-linux-2.7.0: "/usr/local/rake-compiler/ruby/x86_64-redhat-linux/ruby-2.7.0/lib/ruby/2.7.0/x86_64-linux-gnu/rbconfig.rb" ``` with later versions of rubygems, it is only ```yaml --- rbconfig-x86_64-linux-gnu-2.7.0: "/usr/local/rake-compiler/ruby/x86_64-redhat-linux/ruby-2.7.0/lib/ruby/2.7.0/x86_64-linux-gnu/rbconfig.rb" ``` This means that the current way of finding a matching runtime, by doing a string comparison on the config keys, is no longer appropriate. This is causing failing builds downstream in `rake-compiler-dock`. This PR: - extracts a new CompilerConfig class to encapsulate the logic - uses `Gem::Platform#=~` to tell if the gem platform matches the runtime platform
-rw-r--r--lib/rake/baseextensiontask.rb2
-rw-r--r--lib/rake/compiler_config.rb38
-rw-r--r--lib/rake/extensiontask.rb12
-rw-r--r--spec/lib/rake/compiler_config_spec.rb54
-rw-r--r--spec/lib/rake/extensiontask_spec.rb59
5 files changed, 137 insertions, 28 deletions
diff --git a/lib/rake/baseextensiontask.rb b/lib/rake/baseextensiontask.rb
index cf32147..063a555 100644
--- a/lib/rake/baseextensiontask.rb
+++ b/lib/rake/baseextensiontask.rb
@@ -5,6 +5,8 @@ require 'rbconfig'
require 'pathname'
+require_relative "compiler_config"
+
module Rake
class BaseExtensionTask < TaskLib
diff --git a/lib/rake/compiler_config.rb b/lib/rake/compiler_config.rb
new file mode 100644
index 0000000..e9832dc
--- /dev/null
+++ b/lib/rake/compiler_config.rb
@@ -0,0 +1,38 @@
+module Rake
+ class CompilerConfig
+ def initialize(config_path)
+ require "yaml"
+ @config = YAML.load_file(config_path)
+ end
+
+ def find(ruby_version, gem_platform)
+ gem_platform = Gem::Platform.new(gem_platform)
+
+ @config.each do |config_name, config_location|
+ # There are two variations we might find in the rake-compiler config.yml
+ #
+ # 1. config_name: rbconfig-x86_64-linux-3.0.0
+ # runtime_platform_name: x86_64-linux
+ # runtime_version: 3.0.0
+ #
+ # 2. config_name: rbconfig-x86_64-linux-gnu-3.0.0
+ # runtime_platform_name: x86_64-linux-gnu
+ # runtime_version: 3.0.0
+ #
+ # With rubygems < 3.3.21, both variations will be present (two entries pointing at the same
+ # installation).
+ #
+ # With rubygems >= 3.3.21, only the second variation will be present.
+ runtime_platform_name = config_name.split("-")[1..-2].join("-")
+ runtime_version = config_name.split("-").last
+ runtime_platform = Gem::Platform.new(runtime_platform_name)
+
+ if (ruby_version == runtime_version) && (gem_platform =~ runtime_platform)
+ return config_location
+ end
+ end
+
+ nil
+ end
+ end
+end
diff --git a/lib/rake/extensiontask.rb b/lib/rake/extensiontask.rb
index 7c69741..0f48520 100644
--- a/lib/rake/extensiontask.rb
+++ b/lib/rake/extensiontask.rb
@@ -393,8 +393,11 @@ Java extension should be preferred.
return
end
- require "yaml"
- config_file = YAML.load_file(config_path)
+ rbconfig_file = Rake::CompilerConfig.new(config_path).find(ruby_ver, for_platform)
+ unless rbconfig_file
+ warn "no configuration section for specified version of Ruby (rbconfig-#{for_platform}-#{ruby_ver})"
+ return
+ end
# tmp_path
tmp_path = "#{@tmp_dir}/#{for_platform}/#{@name}/#{ruby_ver}"
@@ -405,11 +408,6 @@ Java extension should be preferred.
# lib_binary_path
lib_binary_path = "#{lib_path}/#{File.basename(binary(for_platform))}"
- unless rbconfig_file = config_file["rbconfig-#{for_platform}-#{ruby_ver}"] then
- warn "no configuration section for specified version of Ruby (rbconfig-#{for_platform}-#{ruby_ver})"
- return
- end
-
# mkmf
mkmf_file = File.expand_path(File.join(File.dirname(rbconfig_file), '..', 'mkmf.rb'))
diff --git a/spec/lib/rake/compiler_config_spec.rb b/spec/lib/rake/compiler_config_spec.rb
new file mode 100644
index 0000000..22b1f7f
--- /dev/null
+++ b/spec/lib/rake/compiler_config_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
+
+require 'rake/extensiontask'
+require 'rbconfig'
+require 'tempfile'
+
+describe Rake::CompilerConfig do
+ def config_file(contents)
+ Tempfile.new.tap do |tf|
+ tf.write(contents)
+ tf.close
+ end
+ end
+
+ it "returns the matching config for exact platform match" do
+ cc = Rake::CompilerConfig.new(config_file(<<~CONFIG))
+ ---
+ rbconfig-x86_64-linux-3.0.0: "/path/to/aaa/rbconfig.rb"
+ rbconfig-x86_64-darwin-3.1.0: "/path/to/bbb/rbconfig.rb"
+ rbconfig-x86_64-linux-3.1.0: "/path/to/ccc/rbconfig.rb"
+ CONFIG
+
+ expect(cc.find("3.0.0", "x86_64-linux")).to eq("/path/to/aaa/rbconfig.rb")
+ expect(cc.find("3.1.0", "x86_64-darwin")).to eq("/path/to/bbb/rbconfig.rb")
+ expect(cc.find("3.1.0", "x86_64-linux")).to eq("/path/to/ccc/rbconfig.rb")
+
+ expect(cc.find("2.7.0", "x86_64-linux")).to be_nil
+ expect(cc.find("3.1.0", "arm64-linux")).to be_nil
+ end
+
+ it "returns the matching config for inexact platform match" do
+ cc = Rake::CompilerConfig.new(config_file(<<~CONFIG))
+ ---
+ rbconfig-x86_64-linux-gnu-3.0.0: "/path/to/aaa/rbconfig.rb"
+ rbconfig-x86_64-linux-musl-3.1.0: "/path/to/bbb/rbconfig.rb"
+ CONFIG
+
+ expect(cc.find("3.0.0", "x86_64-linux")).to eq("/path/to/aaa/rbconfig.rb")
+ expect(cc.find("3.1.0", "x86_64-linux")).to eq("/path/to/bbb/rbconfig.rb")
+ end
+
+ it "does not match the other way around" do
+ if Gem::Version.new(Gem::VERSION) < Gem::Version.new("3.3.21")
+ skip "rubygems 3.3.21+ only"
+ end
+
+ cc = Rake::CompilerConfig.new(config_file(<<~CONFIG))
+ ---
+ rbconfig-x86_64-linux-3.1.0: "/path/to/bbb/rbconfig.rb"
+ CONFIG
+
+ expect(cc.find("3.1.0", "x86_64-linux-musl")).to be_nil
+ end
+end
diff --git a/spec/lib/rake/extensiontask_spec.rb b/spec/lib/rake/extensiontask_spec.rb
index a7eb5e3..1c4c9bb 100644
--- a/spec/lib/rake/extensiontask_spec.rb
+++ b/spec/lib/rake/extensiontask_spec.rb
@@ -381,9 +381,10 @@ describe Rake::ExtensionTask do
end
it 'should warn if no section of config file defines running version of ruby' do
- config = Hash.new
- expect(config).to receive(:[]).with("rbconfig-#{@platform}-#{@ruby_ver}").and_return(nil)
- allow(YAML).to receive(:load_file).and_return(config)
+ allow_any_instance_of(Rake::CompilerConfig).to(
+ receive(:find).with(@ruby_ver, @platform).and_return(nil)
+ )
+
out, err = capture_output do
Rake::ExtensionTask.new('extension_one') do |ext|
ext.cross_compile = true
@@ -403,9 +404,9 @@ describe Rake::ExtensionTask do
end
it 'should generate additional rake tasks if files are added when cross compiling' do
- config = Hash.new
- allow(config).to receive(:[]).and_return('/rubies/1.9.1/rbconfig.rb')
- allow(YAML).to receive(:load_file).and_return(config)
+ allow_any_instance_of(Rake::CompilerConfig).to(
+ receive(:find).and_return("/rubies/1.9.1/rbconfig.rb")
+ )
# Use a real spec instead of a mock because define_native_tasks dups and
# calls methods on Gem::Specification, which is more than mock can do.
@@ -433,9 +434,11 @@ describe Rake::ExtensionTask do
end
it 'should allow usage of RUBY_CC_VERSION to indicate a different version of ruby' do
- config = Hash.new
- expect(config).to receive(:[]).with("rbconfig-i386-mingw32-1.9.1").and_return('/rubies/1.9.1/rbconfig.rb')
- allow(YAML).to receive(:load_file).and_return(config)
+ allow_any_instance_of(Rake::CompilerConfig).to(
+ receive(:find)
+ .with("1.9.1", "i386-mingw32")
+ .and_return("/rubies/1.9.1/rbconfig.rb")
+ )
ENV['RUBY_CC_VERSION'] = '1.9.1'
Rake::ExtensionTask.new('extension_one') do |ext|
@@ -444,10 +447,16 @@ describe Rake::ExtensionTask do
end
it 'should allow multiple versions be supplied to RUBY_CC_VERSION' do
- config = Hash.new
- expect(config).to receive(:[]).once.with("rbconfig-i386-mingw32-1.8.6").and_return('/rubies/1.8.6/rbconfig.rb')
- expect(config).to receive(:[]).once.with("rbconfig-i386-mingw32-1.9.1").and_return('/rubies/1.9.1/rbconfig.rb')
- allow(YAML).to receive(:load_file).and_return(config)
+ allow_any_instance_of(Rake::CompilerConfig).to(
+ receive(:find)
+ .with("1.8.6", "i386-mingw32")
+ .and_return("/rubies/1.8.6/rbconfig.rb")
+ )
+ allow_any_instance_of(Rake::CompilerConfig).to(
+ receive(:find)
+ .with("1.9.1", "i386-mingw32")
+ .and_return("/rubies/1.9.1/rbconfig.rb")
+ )
ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
Rake::ExtensionTask.new('extension_one') do |ext|
@@ -459,18 +468,19 @@ describe Rake::ExtensionTask do
platforms = ["x86-mingw32", "x64-mingw32"]
ruby_cc_versions = ["1.8.6", "2.1.10", "2.2.6", "2.3.3", "2.10.1", "2.11.0"]
ENV["RUBY_CC_VERSION"] = ruby_cc_versions.join(":")
- config = Hash.new
+
ruby_cc_versions.each do |ruby_cc_version|
platforms.each do |platform|
unless platform == "x64-mingw32" && ruby_cc_version == "2.11.0"
rbconf = "/rubies/#{ruby_cc_version}/rbconfig.rb"
end
- allow(config).to receive(:[]).
- with("rbconfig-#{platform}-#{ruby_cc_version}").
- and_return(rbconf)
+ allow_any_instance_of(Rake::CompilerConfig).to(
+ receive(:find)
+ .with(ruby_cc_version, platform)
+ .and_return(rbconf)
+ )
end
end
- allow(YAML).to receive(:load_file).and_return(config)
allow(Gem).to receive_message_chain(:configuration, :verbose=).and_return(true)
@@ -515,9 +525,16 @@ describe Rake::ExtensionTask do
context "(cross compile for multiple versions)" do
before :each do
- config = Hash.new
- allow(config).to receive(:[]).and_return('/rubies/1.8.6/rbconfig.rb', '/rubies/1.9.1/rbconfig.rb')
- allow(YAML).to receive(:load_file).and_return(config)
+ allow_any_instance_of(Rake::CompilerConfig).to(
+ receive(:find)
+ .with("1.8.6", "universal-unknown")
+ .and_return("/rubies/1.8.6/rbconfig.rb")
+ )
+ allow_any_instance_of(Rake::CompilerConfig).to(
+ receive(:find)
+ .with("1.9.1", "universal-unknown")
+ .and_return("/rubies/1.9.1/rbconfig.rb")
+ )
ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
@ext = Rake::ExtensionTask.new('extension_one') do |ext|