【问题标题】:How did I cause gcc to produce a .bundle instead of a .so?我是如何让 gcc 生成 .bundle 而不是 .so 的?
【发布时间】:2012-02-08 08:38:24
【问题描述】:

我正在尝试编写一个 Ruby 扩展,并且我整天都在成功编译我的 nmatrix.so 共享对象文件。但是,突然之间,它开始生成nmatrix.bundle,而根本没有任何.so 文件。

它没有给我任何链接器错误,所以我无法想象为什么会这样。我也没有更改my Makefile or extconf.rb 中的任何内容。我一直在通过 rvm 使用 Ruby 1.9.3p0。

我已经尝试用我今天的工作做一个git stash save 并编译一些我知道应该在没有链接器错误的情况下工作(产生一个.so 的东西)。不幸的是,这也会产生一个.bundle 文件。

很明显,我做了一些事情——也许是无意中安装了一些东西——这改变了一些关键的 GCC 设置。这是完全可能的,因为我花了一天的大部分时间尝试构建 LAPACK 和 ATLAS,并且在某个时候还安装了自制软件。

我发现有一种解决方法。我改变了这两行:

DLLIB = $(TARGET).bundle
# ...
LDSHARED = $(CC) -dynamic -bundle

DLLIB = $(TARGET).so
# ...
LDSHARED = $(CC) -dynamic

然后库编译并正确加载。但是,我在extconf.rb(或其他地方)中所做的更改并没有最微弱,这会导致它使用.bundle 文件而不是.so 自动生成这个Makefile。

问题是:我究竟是如何造成这种情况的,我该怎么做才能恢复它?

【问题讨论】:

  • 你能附上你的Makefile吗?
  • 完成。 Makefile 是使用rvm ruby extconf.rb 自动生成的,所以我也包含了extconf.rb

标签: c ruby macos gcc shared-libraries


【解决方案1】:

C extensions RubyGems Guide 提供了构建过程的概述。

extconf.rb 文件中的关键行接近结尾:

require "mkmf"
# ...
create_makefile("nmatrix")

这将为您构建MakefileMakefile 是使用存储在 RbConfig::CONFIG[] 数组中的配置值构建的;你最感兴趣的配置值是RbConfig::CONFIG['DLEXT']

$ ruby -e "require 'rbconfig'; puts RbConfig::CONFIG['DLEXT'];"
so

要轻松查看整个配置,请查找rbconfig.rb 文件;我的位于/usr/lib/ruby/1.8/x86_64-linux/rbconfig.rb,我将在此处包括前几行:

# This file was created by mkconfig.rb when ruby was built.  Any
# changes made to this file will be lost the next time ruby is built.

module Config
  RUBY_VERSION == "1.8.7" or
    raise "ruby lib version (1.8.7) doesn't match executable version (#{RUBY_VERSION})"

  TOPDIR = File.dirname(__FILE__).chomp!("/lib/ruby/1.8/x86_64-linux")
  DESTDIR = '' unless defined? DESTDIR
  CONFIG = {}
  CONFIG["DESTDIR"] = DESTDIR
  CONFIG["INSTALL"] = '/usr/bin/install -c'
  CONFIG["EXEEXT"] = ""
  CONFIG["prefix"] = (TOPDIR || DESTDIR + "/usr")
  ...
  CONFIG["DLEXT"] = "so"
  CONFIG["LDSHARED"] = "$(CC) -shared"
  CONFIG["CCDLFLAGS"] = " -fPIC"
  ...

因此,当构建另一个版本的 Ruby 时,您的 rbconfig.rb 文件的某个版本已经构建,该版本建议动态链接的扩展应该具有不同的扩展。这可能是 rvm 的一个特性(我仍然需要了解更多),或者这可能是 Apple 提供的 Ruby 与自编译 Ruby 之间的区别。您可以在文件的注释标题中看到,您可以轻松地自己在rbconfig.rb 中进行更改——但是当您下次重建或安装不同构建的 Ruby 时,它会被吹走。

(顺便说一句,我以为扩展名是.dylib,但我也有一段时间没有使用OS X了。)

【讨论】:

  • 你摇滚!下次我读MBA时会试试这个。非常感谢。
  • 好的,现在编译可以工作了——但rake compile 仍然失败,显然是在复制操作上:rake aborted! No such file or directory - tmp/x86_64-darwin11.2.0/nmatrix/1.9.3/nmatrix.bundle 我已经更改了rbconfig.rb,所以我不确定在哪里看.
【解决方案2】:

问题似乎来自于使用 LLVM gcc,它在 Xcode 4.2 中表现不佳。

我安装了常规的 gcc,所以我重新安装了 Ruby,如下所示:

export CC=/usr/bin/gcc-4.2
rvm install 1.9.3

大多数方向似乎都说改用rvm install 1.9.3 --enable-shared,但那个额外的标志似乎是问题的根源。

无论如何,我现在似乎可以加载.bundle 文件了。

【讨论】:

  • 如果您的答案解决了问题,请不要忘记将您的答案标记为“已接受”。
猜你喜欢
  • 1970-01-01
  • 2014-03-17
  • 2021-05-16
  • 2011-10-29
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
相关资源
最近更新 更多