2012-11-23 6 views
6

Ich möchte ein Juwel machen, und wenn jemand anderes versucht, es mit MRI zu verwenden, wird es C-Code verwenden, und wenn sie es von JRuby verwenden, wird es Java-Code verwenden.Wie mache ich ein Juwel, das sowohl auf MRI als auch auf JRuby abzielt?

Die Nokogiri- und Puma-Edelsteine ​​machen das, und ich habe ihren Code angeschaut, aber ich habe nicht gesehen, wie sie es geschafft haben.

+0

Siehe auch http://stackoverflow.com/questions/3642085/make-bundler-use-different-gems-for-different-platforms – knut

+0

Das ist nicht, worüber ich spreche. Ich möchte ein Juwel machen, und wenn jemand anderes versucht, es mit MRI zu verwenden, wird es C-Code verwenden, und wenn es von JRuby verwendet wird, wird es Java-Code verwenden. Die Nokogiri- und Puma-Edelsteine ​​tun das, und ich habe ihren Code angeschaut, aber ich habe nicht gesehen, wie sie es möglich machten. – jshen

+0

Der einfachste Weg wäre, den Edelstein in Ruby zu schreiben, so dass man ihn auf 'jRuby' laufen lässt "MRI" oder irgendeine Implementierung. Es wird gut laufen. Sie haben nicht angegeben, welche externen Abhängigkeiten für Ihr Juwel gelten. – nikhil

Antwort

6

Dies wird durch Cross-Compiling der Edelstein für die verschiedenen Plattformen Sie Targeting, mit rvm (oder andere ähnliche Tools zum Wechsel zwischen Rubinen) und rake-compiler getan.

Die Datei gemspec muss die Dateien angeben, die für jede Plattform benötigt werden; dies durch Überprüfen der Plattform erfolgt die Perle wird zusammengestellt mit:

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 

Im Rakefile nach rake-compiler Installation, ist das Muster in der Regel die folgenden:

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 

Aber Sie können spezifische tun müssen Aufgaben für die verschiedenen Plattformen.

Mit MRI kompilieren Sie dann mit rake native gem; mit JRuby, rake java gem - hier ist ein Tool wie rvm praktisch. Du erhältst schließlich verschiedene Edelstein-Dateien für dein Juwel, eine pro Plattform, die du dann als dein Juwel veröffentlichen kannst.

Siehe rake-compiler documentation, um weitere Informationen oder andere Projekte überprüfen, die die gleiche wie redcloth oder pg_array_parser tun (ich finde sie für diese bessere Beispiele als nokogiri sind).