From 26e68b7df4206693e11ebc2a36c40e850b8c2544 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 13 Jul 2023 09:37:43 -0700 Subject: [PATCH] Add support for building precompiled gems Running `rake gem:native` will attempt to cross-compile gems for the following platforms: - aarch64-linux - arm64-darwin - x86_64-darwin - x86_64-linux `rake gem:` also will compile one specific platform. For example: `rake gem:arm64-darwin`. --- Rakefile | 63 +++++++++++++++++++++++++++++++++++++++++++++++++---- lib/re2.rb | 8 ++++++- re2.gemspec | 3 ++- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/Rakefile b/Rakefile index d32bbf3..89280b7 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,8 @@ +# frozen_string_literal: true + require 'rake/extensiontask' require 'rspec/core/rake_task' +require 'rake_compiler_dock' CLEAN.include FileList['**/*{.o,.so,.dylib,.bundle}'], FileList['**/extconf.h'], @@ -14,17 +17,65 @@ CLOBBER.add("ports/*").exclude(%r{ports/archives$}) RE2_GEM_SPEC = Gem::Specification.load('re2.gemspec') -Rake::ExtensionTask.new('re2') - Gem::PackageTask.new(RE2_GEM_SPEC) do |p| p.need_zip = false p.need_tar = false end +CROSS_RUBY_VERSIONS = %w[3.2.0 3.1.0 3.0.0 2.7.0].join(':') +CROSS_RUBY_PLATFORMS = %w[ + aarch64-linux + arm64-darwin + x86_64-darwin + x86_64-linux +].freeze + +ENV['RUBY_CC_VERSION'] = CROSS_RUBY_VERSIONS + +Rake::ExtensionTask.new('re2', RE2_GEM_SPEC) do |e| + e.cross_compile = true + e.cross_config_options << '--enable-cross-build' + e.config_options << '--disable-system-libraries' + e.cross_platform = CROSS_RUBY_PLATFORMS + e.cross_compiling do |spec| + spec.files.reject! { |path| File.fnmatch?('ports/*', path) } + spec.dependencies.reject! { |dep| dep.name == 'mini_portile2' } + end +end + RSpec::Core::RakeTask.new(:spec) -def gem_build_path - File.join 'pkg', RE2_GEM_SPEC.full_name +namespace 'gem' do + def gem_builder(platform) + # use Task#invoke because the pkg/*gem task is defined at runtime + Rake::Task["native:#{platform}"].invoke + Rake::Task["pkg/#{RE2_GEM_SPEC.full_name}-#{Gem::Platform.new(platform)}.gem"].invoke + end + + CROSS_RUBY_PLATFORMS.each do |platform| + # The Linux x86 image (ghcr.io/rake-compiler/rake-compiler-dock-image:1.3.0-mri-x86_64-linux) + # is based on CentOS 7 and has two versions of cmake installed: + # a 2.8 version in /usr/bin and a 3.25 in /usr/local/bin. The latter is needed by abseil. + cmake = platform == 'x86_64-linux' ? '/usr/local/bin/cmake' : 'cmake' + desc "build native gem for #{platform} platform" + task platform do + RakeCompilerDock.sh <<~SCRIPT, platform: platform, verbose: true + gem install bundler --no-document && + bundle && + CMAKE=#{cmake} bundle exec rake gem:#{platform}:builder MAKE='nice make -j`nproc`' + SCRIPT + end + + namespace platform do + desc "build native gem for #{platform} platform (guest container)" + task 'builder' do + gem_builder(platform) + end + end + end + + desc 'build all native gems' + task 'native' => CROSS_RUBY_PLATFORMS end def add_file_to_gem(relative_source_path) @@ -38,6 +89,10 @@ def add_file_to_gem(relative_source_path) RE2_GEM_SPEC.files << relative_source_path end +def gem_build_path + File.join 'pkg', RE2_GEM_SPEC.full_name +end + def add_vendored_libraries dependencies = YAML.load_file(File.join(File.dirname(__FILE__), 'dependencies.yml')) abseil_archive = File.join('ports', 'archives', "#{dependencies['abseil']['version']}.tar.gz") diff --git a/lib/re2.rb b/lib/re2.rb index 5870b47..9c903ff 100644 --- a/lib/re2.rb +++ b/lib/re2.rb @@ -3,5 +3,11 @@ # # Copyright (c) 2010-2014, Paul Mucur (http://mudge.name) # Released under the BSD Licence, please see LICENSE.txt -require "re2.so" +begin + ::RUBY_VERSION =~ /(\d+\.\d+)/ + require_relative "#{Regexp.last_match(1)}/re2.so" +rescue LoadError + require 're2.so' +end + require "re2/scanner" diff --git a/re2.gemspec b/re2.gemspec index 355dd63..873ce5e 100644 --- a/re2.gemspec +++ b/re2.gemspec @@ -27,7 +27,8 @@ Gem::Specification.new do |s| "spec/re2/set_spec.rb", "spec/re2/scanner_spec.rb" ] - s.add_development_dependency("rake-compiler", "~> 0.9") + s.add_development_dependency "rake-compiler", "~> 1.2.1" + s.add_development_dependency "rake-compiler-dock", "~> 1.3.0" s.add_development_dependency("rspec", "~> 3.2") s.add_runtime_dependency("mini_portile2", "~> 2.8.2") # keep version in sync with extconf.rb end