Я создаю файл с драгоценными камнями Ruby, который имеет различные исполняемые требования сторонних разработчиков (некоторые рубиновые инструменты, которые камень будет использовать через системные вызовы).Как читать спецификации gem-файла из extconf.rb?
Перечень требований задаются с помощью gemspec списка информативного requirements
, и я была поставлена задачей создания набора вверх, где этот список требования проверяются во время установки - по существу преобразования requirements
списка от того, информативного, чтобы быть авторитетным.
Мой первоначальный подход заключается в использовании extensions
, как в шаблоне extconf.rb
, для запуска некоторого рубинового кода во время установки, который будет проверять список требований и не выполнить установку, если эти требования не выполняются.
Так что мой текущая реализация использует ext/Rakefile
, который читает gemspec файл, используя жестко запрограммированный путь, разбирает список requirements
, используя пользовательский (но прямо-вперед и простой) синтаксис и запустить несколько простых тестов на требуемых исполняемых файлов.
Я бы очень хотел отказать в зависимости от знания пути к файлу gemspec, поэтому я могу повторно использовать код модульным способом для других проектов.
Для завершения (и в надежде, что это будет полезно для кого-то), вот мой код, в котором используется режим «Rakefile» Gem::Ext::Builder
, чтобы запустить какой-то произвольный код.
require 'rubygems'
require 'mkmf'
def verify_requirement(reqspec)
exe, version_spec, version_regex = reqspec.split(/\s*,\s*/,3)
exe = $1 if exe =~ /\[([^\]]+)\]/ # support human readable alias for executable name
abort "Missing required executable #{exe}!" unless find_executable(exe)
return unless version_speC# no version is specified, so executable existing is good enough
version = %x|#{exe} --version 2>&1|.chomp
version = %x|#{exe} -version 2>&1|.chomp unless $?.success?
abort "Error checking for version of #{exe}: (#{$?.exitstatus}) #{version}" unless $?.success?
if version_regex
abort "Version test '#{version_regex}' failed to match '#{version}'!" unless version =~ /#{version_regex}/m
abort "Version test '#{version_regex}' failed to generate a version number!" unless $1
version = $1
end
abort "Failed to locate a valid version number for #{exe}, found '#{version}'" unless version =~ /^[0-9\.]+/
abort "Insufficient version '#{version}' for #{exe} - requires #{version_spec}" unless Gem::Dependency.new(exe, version_spec).match? exe, version
end
task :default do
gemspec = File.absolute_path('../my.gemspec')
Gem::Specification::load(gemspec).requirements.each do |req|
verify_requirement(req)
end
end
Этот код требует, чтобы requirements
использует любой из этих синтаксисов:
exe-file[, <semantic-version-spec>[, <version-garabbing-regex>]]
alias '[' exe-file ']'[, <semantic-version-spec>[, <version-garabbing-regex>]]
Например:
spec.requirements << 'sox'
spec.requirements << 'ffmpeg, >= 2.5, ffmpeg version ([\d\.]+)'
spec.requirements << 'ImageMagick [convert], >= 6.7.5, ImageMagick ([\d\.]+)'