Как я заставил gcc создать .bundle вместо .so? - PullRequest
6 голосов
/ 12 января 2012

Я пытаюсь написать расширение для Ruby, и я успешно компилирую свой общий объектный файл nmatrix.so весь день. Но затем, внезапно, он начинает производить nmatrix.bundle вместо этого, без какого-либо файла .so.

Это не дает мне никаких ошибок компоновщика, поэтому я не могу себе представить, почему это так. Я также ничего не изменил в моем Makefile или extconf.rb. Я последовательно использую Ruby 1.9.3p0 через rvm.

Я пытался сделать git stash save с моей работой на день и скомпилировать что-то, что, как я знаю, должно работать без ошибок компоновщика (что-то, что привело к .so) ранее. К сожалению, это тоже создает файл .bundle.

Очевидно, что я что-то сделал - возможно, что-то случайно установил - что изменило некоторые критические настройки GCC. Это вполне возможно, поскольку я провел большую часть дня, пытаясь собрать LAPACK и ATLAS, а также в какой-то момент установил homebrew.

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

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

до

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

И тогда библиотека компилируется и загружается правильно. Однако у меня нет ни малейшего изменения, которое я изменил в extconf.rb (или где-либо еще), что заставило бы его автоматически сгенерировать этот Makefile с файлами .bundle вместо .so.

Вопрос: как именно я это вызвал и что мне делать, чтобы восстановить его?

Ответы [ 2 ]

3 голосов
/ 14 января 2012

Руководство по RubyGems для расширений C содержит обзор процесса сборки.

Критические строки в файле extconf.rb близки к концу:

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

Это строит Makefile для вас.Makefile построен с использованием значений конфигурации, хранящихся в массиве 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"
  ...

Итак, некоторая версия вашего rbconfig.rb файла была создана, когда была собрана другая версия Ruby, в которой предлагалосьчто динамически связанные расширения должны иметь другое расширение.Это может быть особенностью rvm (о которой мне еще нужно узнать больше), или это может быть разница между Ruby, поставляемым Apple, и Ruby, скомпилированным самим собой.В заголовке комментария к файлу видно, что вы можете легко внести изменения в rbconfig.rb самостоятельно, но оно будет сорвано в следующий раз, когда вы пересоберите или установите другой Ruby.

(Между прочим, я думал, что расширение было .dylib, но с тех пор я тоже использовал OS X.)

2 голосов
/ 06 февраля 2012

Кажется, что проблема возникает из-за использования gcc LLVM, который не очень хорошо работает с 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 файлов.

...