2012-01-20 6 views
18

私は、宝石のインストール時に条件付きで依存関係を設定する必要がある宝石に取り組んでいます。私はいくつかの掘り下げを行ったルビーの宝石を構築し、依存関係を条件付きで指定する

と私はこの必要性で一人ではないようだ。

Rubygems: How do I add platform-specific dependency?

これは、長いスレッド

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

である私が宝石に依存関係を追加するために見ることができる唯一の方法は、中に宝石:: Specifictionブロック内add_dependencyメソッドを使用することです。 gemspecファイル

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 

ネット上で見つかったすべてのドキュメントとスレッドに基づいて、トンあなたは

  • Linux上の宝石をインストールした場合、その後、RB-inotifyのは、依存関係および自動インストール
  • だろうマック - RB-fseventがインストールされる
  • のWindows - RB-fchangeがインストールされます

しかし、それはそうではないようです。ブロック内のif文は、gemがビルドされてパッケージ化された時点で評価されます。したがって、 Linux上でgemをビルドしてパッケージ化すると、rb-inotifyが依存関係Macとして追加され、次にrb-fsevent、Windows-rb-fchangeとして追加されます。

解決策がまだ必要な場合は、私はrubygemsコードで掘り下げました。次のようなことが起こるのは広範な話です。

  • ビルドあなたの宝石のためのすべてのコード:foo.gem
  • はfoo.gemspecファイル
  • ビルド、パッケージを作成し、そのようなrubygems.org
  • として宝石サーバーに宝石をリリース皆さんに知らせてください。
  • gem install foo
  • foo.gemファイルがダウンロード、展開、インストールされています。すべての依存関係もインストールされます。
  • すべてを設定する必要があります。宝石を使用して缶詰めできます。

宝石が構築され、解放されたときにfoo.gemspecファイルがロードされ、宝石::仕様ブロックが評価され、YAMLに変換され、 metadata.gzとして圧縮、およびfoo.gemに含まれているようです。ルビコードはdata.tar.gzに圧縮され、同様にインクルードされます。 gemがローカルの開発者マシンにインストールされると、 YAMLはmetadata.gzから抽出され、Gem :: Specificationブロックに変換されますが、元のブロックには戻されません。

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:

代わりに、次のようなものが表示されます。しかし、私はプロセスの鳥瞰図を持っていますが、単一の宝石を構築し、OSターゲットの範囲に対する依存関係を条件付きで指定するという私の望みは変わりません。

ターゲットOSごとに複数の.gemspecファイルを作成する以外の方法がある人は...私はすべて耳にします!

+0

私の答えを見てくださいhttp://stackoverflow.com/a/10249133/309514、それはうまく動作します。 – Fotios

答えて

1

私はこれを自分自身をやったことがないが、プラットフォーム固有のバージョンで利用可能ないくつかの宝石があります:http://rubygems.org/gems/libv8/versions

私はそれだけで命名のことだ理解して何から、あなたのプラットフォームのオプションを設定することで設定することができますgemspec。ドックを見てください:http://guides.rubygems.org/specification-reference/#platform=

0

私もこれを調べ、設計上可能でない結論に達しました。すべてのプラットフォームで単一のメガネを持つことは、宝石がダウンロードされてインストールされるまでプラットフォームがサポートされているかどうかを知らないという問題を引き起こします。 Gemは、プラットフォームに応じてインストールする正しい方法が何であるかを判断するのに十分スマートでなければなりません。プラットフォームがまったくサポートされていない場合、宝石は恐ろしいことに失敗し、ワームの大きな缶を開けます。同じ理由で削除された宝石がインストールされた後、宝石を正しくインストールするための魔法もなく、コールバックを使用します。 mkmfを使用してこれをハッキングした人もいますが、より良い解決策として、プラットフォームあたりの宝石の磨耗経路に従うことをお勧めします。

これに基づいて、rubyとjruby用の宝石を作成するプロジェクトでは、私は手動で各宝石を作成してRubyGemにアップロードする必要があります。 Jewelerを使用すると、これはGemfileを指定するのと同じくらい簡単ですが、私はgemをパッケージ化するたびにgemの仕様を再構築する必要があります。 2つのプラットフォームしかサポートしていない場合はかなり簡単ですが、構築プロセスはまっすぐであるため、複数のプラットフォームの宝石をサポートするために自動化できます。

1

私は過去にこの問題を偶然見つけました。私が見つけることができる唯一の回避策は、依存関係をインストールするためのRakeタスクを作成することでした。もちろん、その段階では、ユーザーが受け取ったエラーメッセージに基づいて、自分が見つけていない宝石を自分自身で把握できるようにすることができます。私の場合、いくつかのプラットフォーム依存の依存関係がインストールされていたので、これはオプションではありませんでした。

Rakefile:

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

インストーラ:

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 

そして、ユーザは、適切な依存関係をインストール得るためにrake installを使用することができます。

条件依存インストール(プラットフォームに基づいているだけでなく、ユーザーの入力に基づいているなど)は、RubyGemsには酷評されています。将来的に導入されることを祈りましょう!

関連する問題