From 8b55aaa85ca3b5333e6659f0f0b1eabdd0b9491b Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 20 Feb 2024 07:03:11 +0000 Subject: [PATCH] [Feature #20345] Add `--target-rbconfig` option to mkmf Introduce a new mkmf option `--target-rbconfig` to specify the RbConfig file for the deployment target platform. This option is useful for cross-compiling Ruby extensions without faking the global top-level `RbConfig` constant. --- lib/mkmf.rb | 17 +++++++++++++++++ test/mkmf/test_config.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/lib/mkmf.rb b/lib/mkmf.rb index 92af95d423..73459ffeb9 100644 --- a/lib/mkmf.rb +++ b/lib/mkmf.rb @@ -44,6 +44,23 @@ end # correctly compile and link the C extension to Ruby and a third-party # library. module MakeMakefile + + target_rbconfig = nil + ARGV.delete_if do |arg| + opt = arg.delete_prefix("--target-rbconfig=") + unless opt == arg + target_rbconfig = opt + end + end + if target_rbconfig + # Load the RbConfig for the target platform into this module. + # Cross-compiling needs the same version of Ruby. + Kernel.load target_rbconfig, self + else + # The RbConfig for the target platform where the built extension runs. + RbConfig = ::RbConfig + end + #### defer until this module become global-state free. # def self.extended(obj) # obj.init_mkmf diff --git a/test/mkmf/test_config.rb b/test/mkmf/test_config.rb index 7211c61d53..0d2cb3751c 100644 --- a/test/mkmf/test_config.rb +++ b/test/mkmf/test_config.rb @@ -1,5 +1,6 @@ # frozen_string_literal: false require_relative 'base' +require 'tempfile' class TestMkmfConfig < TestMkmf def test_dir_config @@ -27,4 +28,30 @@ class TestMkmfConfig < TestMkmf assert_equal(false, with_config("foo")) end; end + + def test_with_target_rbconfig + Tempfile.create(%w"rbconfig .rb", ".") do |tmp| + tmp.puts <<~'end;' + module RbConfig + CONFIG = {} + MAKEFILE_CONFIG = {} + + def self.fire_update!(key, value); end + def self.expand(val, config = CONFIG); val; end + end; + ::RbConfig::CONFIG.each do |k, v| + tmp.puts " CONFIG[#{k.dump}] = #{v.dump}" + end + ::RbConfig::MAKEFILE_CONFIG.each do |k, v| + tmp.puts " MAKEFILE_CONFIG[#{k.dump}] = #{v.dump}" + end + tmp.puts " CONFIG['testing-only'] = 'ok'" + tmp.puts "end" + tmp.close + assert_separately([], ["--target-rbconfig=#{tmp.path}"], <<-'end;') + assert_equal("ok", MakeMakefile::RbConfig::CONFIG["testing-only"]) + assert_not_equal(::RbConfig, MakeMakefile::RbConfig) + end; + end + end end