2012-11-23 25 views
6

Tôi muốn tạo một viên ngọc và khi người khác cố gắng sử dụng nó với MRI, nó sẽ sử dụng mã C, và khi họ sử dụng nó từ JRuby, nó sẽ sử dụng mã Java.Làm cách nào để tạo một đá quý nhắm mục tiêu cả MRI lẫn JRuby?

Đá quý nokogiri và puma làm điều này, và tôi đã liếc nhìn mã của chúng, nhưng không thấy cách chúng làm cho nó xảy ra.

+0

Xem thêm http://stackoverflow.com/questions/3642085/make-bundler-use-different-gems-for-different-platforms – knut

+0

Đó không phải là những gì tôi đang nói đến. Tôi muốn tạo một viên ngọc, và khi người khác cố gắng sử dụng nó với MRI, nó sẽ sử dụng mã C, và khi họ sử dụng nó từ JRuby, nó sẽ sử dụng mã Java. Các đá quý nokogiri và puma làm điều này, và tôi đã liếc nhìn mã của chúng, nhưng không thấy làm thế nào chúng làm cho nó xảy ra – jshen

+0

Cách đơn giản nhất là viết gem vào ruby, theo cách đó bạn chạy nó trên 'jRuby' , 'MRI' hoặc bất kỳ triển khai nào. Nó sẽ chạy tốt. Bạn đã không chỉ định phụ thuộc bên ngoài cho đá quý của bạn là gì. – nikhil

Trả lời

6

Điều này được thực hiện bằng cách biên dịch chéo đá quý cho các nền tảng khác nhau mà bạn đang nhắm mục tiêu, sử dụng rvm (hoặc các công cụ tương tự khác để chuyển đổi giữa hồng ngọc) và rake-compiler.

Tệp gemspec phải chỉ định các tệp cần thiết cho từng nền tảng; này được thực hiện bằng cách kiểm tra nền tảng này viên ngọc đang được biên soạn với:

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 

Trong Rakefile, sau khi cài đặt rake-compiler, mô hình thường là như sau:

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 

Nhưng bạn có thể cần phải làm cụ thể nhiệm vụ cho các nền tảng khác nhau.

Với MRI, sau đó bạn biên dịch với rake native gem; với JRuby, rake java gem - đây là nơi mà một công cụ như rvm được tiện dụng. Cuối cùng bạn kết thúc với các tệp gem khác nhau cho gem của bạn, một cho mỗi nền tảng, sau đó bạn có thể phát hành như gem của bạn.

Xem rake-compiler documentation để biết thêm chi tiết hoặc xem các dự án khác thực hiện tương tự, chẳng hạn như redcloth hoặc pg_array_parser (Tôi thấy chúng là ví dụ tốt hơn so với nokogiri cho việc này).

Các vấn đề liên quan