简体   繁体   中英

How do I make a gem that targets both MRI and JRuby?

I want to make a gem, and when someone else tries to use it with MRI it will use C code, and when they use it from JRuby it will use Java code.

The nokogiri and puma gems do this, and I've glanced at their code, but didn't see how they were making it happen.

This is done by cross-compiling the gem for the different platforms you are targeting, using rvm (or other similar tools to switch between rubies) and rake-compiler .

The gemspec file must specify the files needed for each platform; this is done by checking the platform the gem is being compiled with:

Gem::Specification.new do |gem|
# . . .

  if RUBY_PLATFORM =~ /java/
    # package jars
    gem.files += ['lib/*.jar']
    # . . . 
  else
    # package C stuff
    gem.files += Dir['ext/**/*.c']
    # . . . 
    gem.extensions = Dir['ext/**/extconf.rb']
  end
end

In the Rakefile , after installing rake-compiler , the pattern is usually the following:

spec = Gem::Specification.load('hello_world.gemspec')

if RUBY_PLATFORM =~ /java/
  require 'rake/javaextensiontask'
  Rake::JavaExtensionTask.new('hello_world', spec)
else
  require 'rake/extensiontask'
  Rake::ExtensionTask.new('hello_world', spec)
end

But you may need to do specific tasks for the different platforms.

With MRI, you then compile with rake native gem ; with JRuby, rake java gem – this is where a tool like rvm gets handy. You finally end up with different gem files for your gem, one per platform, that you can then release as your gem.

See rake-compiler documentation for more details, or check out other projects that do the same, such as redcloth or pg_array_parser (I find they are better examples than nokogiri for this).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM