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更好)。