如何制作针对MRI和JRuby的宝石?

时间:2021-08-19 07:16:20

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.

我想创建一个gem,当其他人试图将它与MRI一起使用时,它将使用C代码,当他们从JRuby使用它时,它将使用Java代码。

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

nokogiri和puma宝石这样做,我已经看了他们的代码,但没看到他们是如何实现它的。

1 个解决方案

#1


6  

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.

这是通过使用rvm(或其他类似工具在红宝石之间切换)和rake-compiler交叉编译您所针对的不同平台的gem来完成的。

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

gemspec文件必须指定每个平台所需的文件;这是通过检查正在编译gem的平台来完成的:

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:

在Rakefile中,安装rake-compiler之后,模式通常如下:

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.

使用MRI,然后使用rake native gem进行编译;使用JRuby,rake java gem - 这就是像rvm这样的工具变得方便的地方。你终于得到了宝石的不同宝石文件,每个平台一个,然后你可以作为你的宝石发布。

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).

有关更多详细信息,请参阅rake-compiler文档,或查看执行相同操作的其他项目,例如redcloth或pg_array_parser(我发现它们比nokogiri更好)。

#1


6  

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.

这是通过使用rvm(或其他类似工具在红宝石之间切换)和rake-compiler交叉编译您所针对的不同平台的gem来完成的。

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

gemspec文件必须指定每个平台所需的文件;这是通过检查正在编译gem的平台来完成的:

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:

在Rakefile中,安装rake-compiler之后,模式通常如下:

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.

使用MRI,然后使用rake native gem进行编译;使用JRuby,rake java gem - 这就是像rvm这样的工具变得方便的地方。你终于得到了宝石的不同宝石文件,每个平台一个,然后你可以作为你的宝石发布。

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).

有关更多详细信息,请参阅rake-compiler文档,或查看执行相同操作的其他项目,例如redcloth或pg_array_parser(我发现它们比nokogiri更好)。