I'm trying to write a Ruby extension, and I've been successfully compiling my nmatrix.so
shared object file all day. But then, suddenly, it starts producing nmatrix.bundle
instead, without any .so
file at all.
It's not giving me any linker errors, so I can't imagine why this would be. I also didn't change anything in my Makefile
or extconf.rb
. I've been consistently using Ruby 1.9.3p0 through rvm.
I've tried doing a git stash save
with my work for the day and compiling something I know should work without linker errors (something that produced a .so) earlier. Unfortunately, that too produces a .bundle
file.
Clearly I have done something -- perhaps installed something inadvertently -- which has changed some critical GCC setting. This is totally possible, as I spent most of the day trying to get LAPACK and ATLAS to build, and also installed homebrew at some point.
I have discovered that there is a work-around. I change these two lines:
DLLIB = $(TARGET).bundle
# ...
LDSHARED = $(CC) -dynamic -bundle
to
DLLIB = $(TARGET).so
# ...
LDSHARED = $(CC) -dynamic
And then the library compiles and loads correctly. However, I haven't the faintest what I changed in extconf.rb
(or elsewhere) which would have caused it to auto-generate this Makefile with .bundle
files instead of .so
.
The question is: how exactly did I cause this, and what do I do to restore it?
The C extensions RubyGems Guide has an overview of the building process.
The critical lines in your extconf.rb
file are near the ends:
require "mkmf"
# ...
create_makefile("nmatrix")
This builds the Makefile
for you. The Makefile
is built using configuration values stored in the RbConfig::CONFIG[]
array; the configuration value you're most interested in is RbConfig::CONFIG['DLEXT']
:
$ ruby -e "require 'rbconfig'; puts RbConfig::CONFIG['DLEXT'];"
so
To easily see the entire configuration, look for the rbconfig.rb
file; mine is located in /usr/lib/ruby/1.8/x86_64-linux/rbconfig.rb
, and I'll include the first few lines here:
# 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"
...
So, some version of your rbconfig.rb
file has been built when another version of Ruby was built that suggested that dynamically linked extensions should have a different extension. This might be a feature of rvm
(which I still need to learn more about) or this might be a difference between Apple-supplied Ruby vs self-compiled Ruby. You can see in the comment header of the file that you could easily make the change in rbconfig.rb
yourself -- but it will be blown away the next time you rebuild or install a differently-built Ruby.
(Incidentally, I thought the extension was .dylib
, but it's been a while since I've used OS X, too.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With