我正在创建一个Ruby C扩展,我想为其创建预打包的二进制包,因为编译需要大量的依赖项。我是Ruby的新手,但似乎gem
不想创建特定于平台的软件包,因此常见的方法是使用rake-compiler gem,然后执行rake native
。我可以得到它来编译扩展,但是失败并显示错误
NoMethodError: undefined method `split' for nil:NilClass
使用--trace运行表明错误出在rake-compiler-1.0.7 / lib / rake / extensiontask.rb:515:
def ruby_api_version(ruby_version)
ruby_version.split(".")[0, 2].join(".")
end
这是因为ruby_version为nil。它是通过define_native_tasks()中的rake-compiler-1.0.7 / lib / rake / extensiontask.rb:262调用的:
ruby_versions = @ruby_versions_per_platform[platf] || []
sorted_ruby_versions = ruby_versions.sort_by do |ruby_version|
ruby_version.split(".").collect(&:to_i)
end
spec.required_ruby_version = [
">= #{ruby_api_version(sorted_ruby_versions.first)}",
"< #{ruby_api_version(sorted_ruby_versions.last).succ}.dev"
]
@ruby_versions_per_platform
在构造函数中设置为{}
,但是没有代码行对其进行设置。因此,sorted_ruby_versions
为空,.first
和.last
为零,这导致ruby_api_version
的参数为零。
查看项目中的git blame,发现这些行已有2年历史了,并且是变更集https://github.com/rake-compiler/rake-compiler/commit/0dc23504cb03ed2fb3c506e1bb58af48d3851d1e的结果。但是,ruby_versions_per_platform
从未分配给构造函数之外,这意味着ruby_api_version
将始终以nil调用,并且总是失败。那么这怎么能工作两年呢?
更重要的是,我要怎么做才能使rake native
正常工作?
我正在使用macOS 10.12.6,安装了MacPorts的Ruby 2.3.7p456(由port select --set ruby ruby26
选择),rake-compiler 1.0.7和rake-12.3.2。
Rakefile:
require "rake/extensiontask"
gemspec = Gem::Specification::load("mygem.gemspec")
Gem::PackageTask.new(gemspec) do |pkg|
end
Rake::ExtensionTask.new("mygem", gemspec) do |ext|
end
mygem.gemspec
Gem::Specification.new do |s|
s.name = "mygem"
s.version = "1.0.0rc1"
s.authors = [ "John Doe" ]
s.summary = "Awesome library"
s.description = "Awesome library because, reasons"
s.licenses = [ 'MIT' ]
s.email = "johndoe@null.com"
s.homepage = "http://www.null.com"
s.extensions = %w[ext/mygem/extconf.rb]
s.files = FileList['lib/**/*.rb', 'ext/**/*.{rb,c,h}']
s.platform = Gem::Platform::RUBY
s.required_ruby_version = '>= 1.8'
end
我的项目布局是
Rakefile
mygem.gemspec
ext/
mygem/
extconf.rb
mygem.c (generated with SWIG 3.0)
lib/
mygem.rb