построить рубиновый гем и условно указать зависимости - PullRequest
19 голосов
/ 20 января 2012

Я работаю над гемом, который должен установить зависимости условно при установке гема.Я немного покопался в

и похоже, что я не одинок в этом.

Rubygems: Как добавить зависимость для конкретной платформы?

это длинная тема

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

Единственный способ увидеть, как добавить зависимости кgem должен использовать метод add_dependency в блоке Gem :: Specifiction в файле .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

Основываясь на всех документах и ​​потоках, которые я нашел в сети, я ожидал бы, что если вы установитеgem в

  • Linux, тогда rb-inotify будет зависимостью и будет автоматически установлен
  • Mac - будет установлен rb-fsevent
  • Windows - rb-Будет установлен fchange

Однако, похоже, дело не в этом.Операторы if в блоке оцениваются во время сборки и упаковки гема.Поэтому, если вы собираете и упаковываете гем в Linux, то rb-inotify добавляется как зависимость, Mac, затем rb-fsevent, Windows - rb-fchange.

Все еще нужно решение, я выкопалгде-то в коде rubygems, и кажется, что ниже описывается, что происходит.

  • соберите весь свой код для своего гема: foo.gem
  • создайте foo.gemspecфайл
  • собрать, упаковать и выпустить gem на такой гем-сервер, как rubygems.org
  • , чтобы все знали,
  • разработчики устанавливают его локально с помощью: gem install foo
  • Файл foo.gem загружен, распакован и установлен.все зависимости также установлены.
  • все должно быть установлено, и мы можем использовать этот гем.

Кажется, что когда гем собран и выпущен, файл foo.gemspecзагружен, и блок Gem :: Specification оценивается и преобразуется в YAML, сжимается как metadata.gz и включается в foo.gem.Рубиновый код сжимается в data.tar.gz и также включается.Когда гем установлен на локальном компьютере разработчика, 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

Хорошо.Таким образом, я имею представление о процессе с высоты птичьего полета, однако это не меняет моего желания создать один гем и условно определять зависимости для целого ряда целей ОС.несколько файлов .gemspec для каждой целевой ОС ... У меня все уши !!

Ответы [ 3 ]

1 голос
/ 16 марта 2012

Я также сталкивался с этой проблемой в прошлом.Единственный обходной путь, который я смог найти, - это создать задачу 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.Будем надеяться, что это будет реализовано в будущем!

1 голос
/ 20 января 2012

Я никогда не делал этого сам, но есть некоторые драгоценные камни, которые доступны в версиях для конкретной платформы: http://rubygems.org/gems/libv8/versions

из того, что я понимаю, это просто вещь именования, которую можно настроить, установив опцию платформы вашей gemspec. взгляните на документ: http://guides.rubygems.org/specification-reference/#platform=

0 голосов
/ 16 марта 2012

Я тоже изучил это и пришел к выводу, что это невозможно по замыслу. Наличие единого «мега-драгоценного камня» для всех платформ приводит к проблеме незнания, поддерживается ли платформа до тех пор, пока драгоценный камень не будет загружен и установлен. Gem должен быть достаточно умен, чтобы определить, какой правильный способ установки зависит от платформы. Если платформа вообще не поддерживается, драгоценный камень может ужасно потерпеть неудачу, открывая большую банку с червями. После установки драгоценного камня, который был удален по той же причине, использовался обратный вызов, не было волшебства, чтобы заставить камень правильно установить. Некоторые люди взломали это, используя mkmf, но я рекомендую следовать по изношенному пути драгоценного камня на платформу как лучшее решение.

Исходя из этого, в проекте, который создает гем для ruby ​​и jruby, я должен вручную создать каждый гем и загрузить его в RubyGem. Используя Jeweler это так же просто, как указать Gemfile , но мне приходится перестраивать спецификацию гема каждый раз, когда я упаковываю гем. Довольно тривиально при поддержке только 2 платформ, но процесс сборки достаточно прост, чтобы его можно было автоматизировать для поддержки нескольких платформ.

...