diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b342e8..48e42ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ upgrading. ## [Unreleased] +### Added +- Introduce `--include-shared-dir` to specify additional directory where to + lookup platform-specific shared libraries to bundle in the package. (#34) + ### Fixed - Solve RubyGems 2.6.x changes on exception hierarchy. Thanks to @MSP-Greg (#30) diff --git a/lib/rubygems/commands/compile_command.rb b/lib/rubygems/commands/compile_command.rb index d081045..87b7fc1 100644 --- a/lib/rubygems/commands/compile_command.rb +++ b/lib/rubygems/commands/compile_command.rb @@ -9,6 +9,10 @@ def initialize options[:output] = File.expand_path(value, Dir.pwd) end + add_option "--include-shared-dir DIR", "Additional directory for shared libraries" do |value, options| + options[:include_shared_dir] = value + end + add_option "--prune", "Clean non-existing files during re-packaging" do |value, options| options[:prune] = true end diff --git a/lib/rubygems/compiler.rb b/lib/rubygems/compiler.rb index 93317f5..2db9e74 100644 --- a/lib/rubygems/compiler.rb +++ b/lib/rubygems/compiler.rb @@ -25,6 +25,12 @@ def compile artifacts = collect_artifacts + if shared_dir = options[:include_shared_dir] + shared_libs = collect_shared(shared_dir) + + artifacts.concat shared_libs + end + # build a new gemspec from the original one gemspec = installer.spec.dup @@ -75,6 +81,12 @@ def collect_artifacts Dir.glob("#{target_dir}/{#{lib_dirs}}/**/*.#{dlext}") end + def collect_shared(shared_dir) + libext = platform_shared_ext + + Dir.glob("#{target_dir}/#{shared_dir}/**/*.#{libext}") + end + def info(msg) say msg if Gem.configuration.verbose end @@ -87,6 +99,21 @@ def installer @installer ||= prepare_installer end + def platform_shared_ext + platform = Gem::Platform.local + + case platform.os + when /darwin/ + "dylib" + when /linux|bsd|solaris/ + "so" + when /mingw|mswin|cygwin|msys/ + "dll" + else + "so" + end + end + def prepare_installer # RubyGems 2.5 specifics unpack_options = options.dup.merge(unpack: true) diff --git a/test/rubygems/test_gem_compiler.rb b/test/rubygems/test_gem_compiler.rb index 45e006a..b246f0d 100644 --- a/test/rubygems/test_gem_compiler.rb +++ b/test/rubygems/test_gem_compiler.rb @@ -235,6 +235,78 @@ def test_compile_bundle_artifacts_path_with_spaces end end + def test_compile_bundle_extra_artifacts_linux + util_set_arch "x86_64-linux" + + name = 'a' + + artifact = "shared.so" + old_spec = '' + + gem_file = util_bake_gem(name) { |spec| + old_spec = spec + util_fake_extension spec, name, <<-EOF + require "fileutils" + + FileUtils.touch "#{artifact}" + + File.open 'Rakefile', 'w' do |rf| rf.puts "task :default" end + EOF + } + + compiler = Gem::Compiler.new(gem_file, + :output => @output_dir, :include_shared_dir => "ext") + + output_gem = nil + + use_ui @ui do + output_gem = compiler.compile + end + + assert_path_exists File.join(@output_dir, output_gem) + actual_spec = util_read_spec File.join(@output_dir, output_gem) + + assert_includes actual_spec.files, "ext/#{name}/#{artifact}" + ensure + util_reset_arch + end + + def test_compile_bundle_extra_artifacts_windows + util_set_arch "i386-mingw32" + + name = 'a' + + artifact = "shared.dll" + old_spec = '' + + gem_file = util_bake_gem(name) { |spec| + old_spec = spec + util_fake_extension spec, name, <<-EOF + require "fileutils" + + FileUtils.touch "#{artifact}" + + File.open 'Rakefile', 'w' do |rf| rf.puts "task :default" end + EOF + } + + compiler = Gem::Compiler.new(gem_file, + :output => @output_dir, :include_shared_dir => "ext") + + output_gem = nil + + use_ui @ui do + output_gem = compiler.compile + end + + assert_path_exists File.join(@output_dir, output_gem) + actual_spec = util_read_spec File.join(@output_dir, output_gem) + + assert_includes actual_spec.files, "ext/#{name}/#{artifact}" + ensure + util_reset_arch + end + def test_compile_lock_ruby_abi util_reset_arch