如何编译Ruby扩展

时间:2012-11-22 21:56:00

标签: ruby gem rake rakefile

我在ext / Q / flagvalue.c中有一个简单的扩展名

我的ext / Q / extconfig.rb如下所示:

require 'mkmf'
create_makefile('Q/flagvalue')

Rakefile中的任务设置如下:

Rake::ExtensionTask.new("Q") do |extension|
  extension.lib_dir = 'lib/Q'
end

当我rake build时,我得到以下输出:

mkdir -p tmp/x86_64-linux/Q/1.9.3
cd tmp/x86_64-linux/Q/1.9.3
/usr/local/rvm/rubies/ruby-1.9.3-p286/bin/ruby -I. ../../../../ext/Q/extconf.rb
creating Makefile
cd -
cd tmp/x86_64-linux/Q/1.9.3
make
compiling ../../../../ext/Q/flagvalue.c
linking shared-object Q/flagvalue.so
cd -
install -c tmp/x86_64-linux/Q/1.9.3/Q.so lib/Q/Q.so
rake aborted!
No such file or directory - tmp/x86_64-linux/Q/1.9.3/Q.so

所以看起来编译器编译并链接 flagvalue.so ,安装程序尝试安装不存在的 Q.so ...这个错误来自哪里以及什么我能做些什么吗?

2 个答案:

答案 0 :(得分:1)

Rakefile

中试试这个
Rake::ExtensionTask.new 'flagvalue' do |extension|
  extension.ext_dir = 'ext/Q'
  extension.lib_dir = 'lib/Q'
end

这确实需要一些重复,因为Rake任务不知道你在extconf中指定的目标(即它不知道Q目录),所以你必须再次指定。这也意味着任务在项目中的Q目录下创建的结构中不会有tmp目录,但这可能不是问题。

答案 1 :(得分:0)

好的,经过一些挖掘(以及一些模糊的猜测:-Δ)我找到了解决方案:

我刚刚为我的gemspec(来自Writehack.com)获得了一些代码,就是这样:

s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }

此方法的问题在于您必须在存储库中已经存在just-to compile-binaries。正确的方法是从ext目录中获取* .c文件并将它们重命名为* .so,如下所示:

s.executables   = s.files.grep(%r{^ext/.*c$}).map{ |f| File.basename(f, '.c') + '.so'}
s.bindir        = 'bin'

并且还向Rakefile的ExtensionTask添加了一个bindir,并使其从spec中获取文件:

spec = Gem::Specification.load('Q.gemspec')
spec.executables.each do |f|
  Rake::ExtensionTask.new('Q', spec) do |ext|
    ext.name    = f.gsub(/\.so$/,'')
    ext.tmp_dir = 'tmp'
    ext.lib_dir = 'bin'
  end
end

: - Δ