Archive for the ‘Ruby and Rails’ Category

Using ruby-odbc with unixODBC on Snow Leopard

Monday, October 26th, 2009

I am trying to get my development environment up and running on Snow Leopard. I need to be able to connect to an SQL server through Ruby and Rails and that has been working fine on Leopard.

Snow Leopard being x86_64 presents a few problems. One of them was that I needed ruby-odbc to use my installed unixODBC and not iodbc that ships with OSX. (Here is why).

According to this guide it is advisable to use MacPorts to install an entire stack of ruby and everything else. I have a problem with this approach because it complicates things and because I like to use stock stuff whenever possible. Just a matter of taste.

I set out to try to make it work.

When following this post I got everything to work except that ruby-odbc insisted on using iodbc and not unixODBC. After digging around I found out that when making unixODBC it (libodbc.dynlib) becomes x86_64 only.

Jacob-Riffs-MacBook:unixODBC-2.2.14 jacob$ file /usr/local/unixODBC-2.2.14/lib/libodbc.dylib
/usr/local/unixODBC-2.2.14/lib/libodbc.dylib: Mach-O 64-bit dynamically linked shared library x86_64
MacBook:unixODBC-2.2.14 jacob$ file /usr/local/unixODBC-2.2.14/lib/libodbc.dylib
/usr/local/unixODBC-2.2.14/lib/libodbc.dylib: Mach-O 64-bit dynamically linked shared library x86_64

When ruby-odbc’s extconf does it’s run it will try to gcc to both i386 and x86_64 – that will fail for unixODBC but not for iodbc (which is a fat file for both architectures). This is why ruby-odbc will choose iodbc:

"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -I/usr/local/unixODBC-2.2.14/include  -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE  -fno-common  -pipe -fno-common   conftest.c  -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L/usr/local/unixODBC-2.2.14/lib -L. -arch i386 -arch x86_64     -liodbc  -lruby -lodbcinst -liodbc  -lpthread -ldl  "
ld: warning: in /usr/local/unixODBC-2.2.14/lib/libodbcinst.dylib, file is not of required architecture
Undefined symbols for architecture i386:
  "_SQLConfigDataSource", referenced from:
      _t in ccLjoIVs.o
ld: symbol(s) not found for architecture i386

What I ended up doing was to modify the makefile that extconf creates and remove all references to the i386 architecture and changing LIBS from iodbc to odbc. Here is the lines to change:

CFLAGS   =  -fno-common -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE  -fno-common  -pipe -fno-common $(cflags)
ldflags  = -L. -arch x86_64
LDSHARED = cc -arch x86_64 -pipe -bundle -undefined dynamic_lookup
LIBS = $(LIBRUBYARG_SHARED) -lodbcinst -lodbc  -lpthread -ldl

After this just do a make, make install and go! It might not be pretty, but it works.

I wonder if the right thing to do is to compile unixODBC as a fat file for both architectures but I don’t know how to do it.

I hope this helps somebody.