我想创建一个gem,当其他人尝试将它与MRI一起使用时,它将使用C代码,当他们从JRuby使用它时,它将使用Java代码。
nokogiri和puma gems这样做,我已经看了他们的代码,但没看到他们是如何实现它的。
答案 0 :(得分:6)
这是通过使用rvm(或其他类似工具在红宝石之间切换)和rake-compiler交叉编译您要定位的不同平台的gem来完成的。
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
在安装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
但您可能需要为不同平台执行特定任务。
使用MRI,然后使用rake native gem
进行编译;使用JRuby,rake java gem
- 这就是像rvm这样的工具变得方便的地方。你终于得到了宝石的不同宝石文件,每个平台一个,然后你可以作为你的宝石发布。
有关详细信息,请参阅rake-compiler documentation,或查看执行相同操作的其他项目,例如redcloth或pg_array_parser(我发现它们比nokogiri更好的例子)。< / p>