2012-01-20 23 views
18

Tôi đang làm việc trên một viên ngọc có nhu cầu thiết lập các phụ thuộc có điều kiện khi đá quý được cài đặt. Tôi đã thực hiện một số việc đào bới xung quanhxây dựng một viên đá quý ruby ​​và có điều kiện xác định phụ thuộc

và có vẻ như tôi không đơn độc trong nhu cầu này.

Rubygems: How do I add platform-specific dependency?

đây là một chủ đề dài

http://www.ruby-forum.com/topic/957999

Cách duy nhất tôi có thể thấy để thêm phụ thuộc vào một viên ngọc là sử dụng phương pháp add_dependency trong một khối Gem :: specifiction trong một. gemspec file

Gem::Specification.new do |s| 

    # ... standard setup stuff 

    # conditionally set dependencies 
    s.add_dependency "rb-inotify", "~> 0.8.8" if RUBY_PLATFORM =~ /linux/i 
    s.add_dependency "rb-fsevent", "~> 0.4.3.1" if RUBY_PLATFORM =~ /darwin/i 
    s.add_dependency "rb-fchange", "~> 0.0.5" if RUBY_PLATFORM =~ /mswin|mingw/i 

end 

Dựa trên tất cả tài liệu và chủ đề tôi tìm thấy trên mạng, tôi đã mong đợi tha t nếu bạn cài đặt các viên ngọc trên

  • Linux, sau đó, rb-inotify sẽ là một sự phụ thuộc và tự động cài đặt
  • Mac - rb-fsevent sẽ được cài đặt
  • Windows - rb-fchange sẽ được cài đặt

Tuy nhiên, có vẻ như không phải như vậy. Các câu lệnh "if" trong khối được đánh giá tại thời điểm đá quý được xây dựng và đóng gói. Do đó, nếu bạn xây dựng và đóng gói gem trên Linux, thì rb-inotify được thêm vào như một phụ thuộc, Mac, sau đó, rb-fsevent, Windows-rb-fchange.

Vẫn còn cần một giải pháp, tôi đào xung quanh trong mã rubygems và có vẻ như sau đây là một stoke rộng của những gì sẽ xảy ra.

  • xây dựng tất cả các mã của bạn cho đá quý của bạn: foo.gem
  • tạo một file foo.gemspec
  • xây dựng, đóng gói, và nhả ngọc đến một máy chủ đá quý như rubygems.org
  • cho mọi người biết
  • nhà phát triển cài đặt cục bộ qua: gem install foo
  • tệp foo.gem được tải xuống, giải nén và cài đặt. tất cả các phụ thuộc cũng được cài đặt.
  • mọi thứ nên được đặt và chúng ta có thể sử dụng đá quý.

Dường như khi đá quý được xây dựng và phát hành các tập tin foo.gemspec được nạp và khối Gem :: Thông số kỹ thuật được đánh giá và chuyển đổi sang YAML, nén như metadata.gz, và bao gồm trong foo.gem . Mã ruby ​​được nén thành data.tar.gz và cũng được bao gồm. Khi gem được cài đặt trên máy phát triển cục bộ, YAML được trích xuất từ ​​metadata.gz và được chuyển đổi trở lại thành khối Gem :: Specification, tuy nhiên nó không được chuyển đổi về khối gốc.

thay vào đó, bạn sẽ thấy một cái gì đó như sau:

Gem::Specification.new do |s| 

    if s.respond_to? :specification_version then 
    s.specification_version = 3 

    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then 
     s.add_runtime_dependency(%q<rb-inotify>, ["~> 0.8.8"]) 
    else 
     s.add_dependency(%q<rb-inotify>, ["~> 0.8.8"]) 
    end 
    else 
    s.add_dependency(%q<rb-inotify>, ["~> 0.8.8"]) 
    end 

end 

Ok.Vì vậy, tôi có một cái nhìn của một con chim của quá trình, tuy nhiên, điều đó không thay đổi mong muốn của tôi để xây dựng một viên ngọc duy nhất và có điều kiện xác định phụ thuộc cho một loạt các mục tiêu hệ điều hành.

Nếu có ai có giải pháp khác ngoài việc tạo nhiều tệp .gemspec cho từng hệ điều hành đích ... Tôi là tất cả tai !!

+0

Nhìn vào câu trả lời của tôi cho http://stackoverflow.com/a/10249133/309514, nó hoạt động tốt. – Fotios

Trả lời

0

Tôi cũng đã xem xét điều này và đã đi đến kết luận không thể thiết kế. Có một 'đá quý lớn' cho tất cả các nền tảng gây ra vấn đề không biết liệu nền tảng có được hỗ trợ cho đến khi đá quý được tải xuống và cài đặt hay không. Một Gem sẽ phải đủ thông minh để xác định cách chính xác để cài đặt tùy thuộc vào nền tảng. Nếu một nền tảng không được hỗ trợ chút nào, đá quý có thể thất bại khủng khiếp, mở một thùng lớn của giun. Có sử dụng để được gọi lại sau khi một đá quý đã được cài đặt đã được gỡ bỏ cho cùng một lý do, không có phép thuật để có được một đá quý để cài đặt một cách chính xác. Một số người đã tấn công xung quanh điều này bằng cách sử dụng mkmf, nhưng tôi đề nghị theo con đường mòn của đá quý trên mỗi nền tảng như là giải pháp tốt hơn.

Dựa trên điều này, trong một dự án xây dựng một viên ngọc cho ruby ​​và jruby, tôi phải tự tạo từng viên đá quý và tải chúng lên RubyGem. Sử dụng Jeweler điều này cũng đơn giản như chỉ định các Gemfile, nhưng tôi phải xây dựng lại đặc tả đá quý mỗi khi tôi đóng gói một viên ngọc. Khá tầm thường khi chỉ hỗ trợ 2 nền tảng, nhưng quá trình xây dựng là đủ về phía trước để có thể tự động cung cấp hỗ trợ nhiều nền tảng đá quý.

1

Tôi cũng đã tình cờ gặp vấn đề này trong quá khứ. Cách giải quyết duy nhất tôi có thể tìm thấy là tạo ra một nhiệm vụ Rake để cài đặt các phụ thuộc. Tất nhiên, ở giai đoạn đó, bạn có thể chỉ muốn để người dùng tự mình tìm ra viên đá quý nào mà anh ta đang thiếu dựa trên thông báo lỗi mà anh ta đang nhận. Trong trường hợp của tôi, có một số phụ thuộc nền tảng được cài đặt, do đó, đó không phải là một lựa chọn.

Rakefile:

task :install do |t| 
    require './lib/library/installer' 
    Library::Installer.install 
end 

Installer:

module Library::Installer 

    require 'rubygems/dependency_installer' 

    def self.install 
    installer = Gem::DependencyInstaller.new 
    dependency = case RUBY_PLATFORM 
     when /darwin/i then ["rb-fsevent", "~> 0.4.3.1"] 
     when /linux/i then ["rb-inotify", "~> 0.8.8"] 
     when /mswin|mingw/i then ["rb-fchange", "~> 0.0.5"] 
    end 
    installer.install(*dependency)   
end 

Sau đó, người dùng có thể sử dụng rake install để get install phụ thuộc thích hợp.

Cài đặt phụ thuộc có điều kiện (không chỉ dựa trên nền tảng, nhưng dựa trên đầu vào của người dùng, ví dụ) bị thiếu tàn nhẫn đối với RubyGems. Hãy hy vọng nó sẽ được triển khai trong tương lai!

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