Thursday, February 26, 2009

Failed attempt to use Mac OS X Leopard stock installation of Ruby on Rails.

Stock installation of RoR, if updated to Rails 2.2.2 fails because it breaks MySQL functionality. Using gem install mysql fails because the stock Ruby interpreter packaged with Xcode 3.0 is only 32 bit and the stock version of MySQL and its libraries for building mysql clients are 64 bit. Link to Chris Cruft's blog about MySQL gem problems

Faced the same error messages as in the blog above, and followed basically the same steps. Below is the initial error message when trying to install the mysql gem.

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb install mysql
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... no
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***


I tried both options indicated at the end of Chris Cruft's blog post, and the successful solution that ended up being the least amount of work was installing a 4-way fat universal binary for the MySQL.

The first option I attempted was to make a new installation of Ruby 1.8.7-p72 by compiling from source. Used /usr/local for new installation environment to avoid conflicts with stock installation. Added a ".profile" file in the shell users's home directory so that the $PATH environment variable would be set to PATH=/usr/local/bin:/bin:/usr/sbin:/sbin:/usr/bin:/usr/X11/bin
upon login. I followed most of these instructions to compile Ruby for Mac OS X Leopard

When I got to the step of installing the MySQL C binding gem for Rails; I still had the same problem as when attempting to install it for the out-of-the-box Ruby 1.8.6 stack.
Entering this in the terminal

sudo env ARCHFLAGS="-arch i386" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config

just didn't work and gave the following errors when using -V option with gem install.

ld: warning in /usr/local/mysql/lib/libmysqlclient.dylib, file is not of required architecture
ld: warning in /usr/local/mysql/lib/libmygcc.a, file is not of required architecture


Errno::ENOENT (No such file or directory - /tmp/mysql.sock):
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/vendor/mysql.rb:107:in `initialize'
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/vendor/mysql.rb:107:in `new'
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/vendor/mysql.rb:107:in `real_connect'
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/connection_adapters/mysql_adapter.rb:527:in `connect'
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/connection_adapters/mysql_adapter.rb:186:in `initialize'
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/connection_adapters/mysql_adapter.rb:85:in `new'
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/connection_adapters/mysql_adapter.rb:85:in `mysql_connection'


It then occurred to me that my colleague had recently built a new PHP environment and needed the MySQL client libraries and headers.

The following are the notes my colleague wrote for the PHP build.

More or less followed instructions from: http://www.unibia.com/unibianet/node/32?page=0,0
found a few difficulties along the way, and did not install my own apache to replace the apple one.

Started out building in intel 32 bit mode, but the apache was compiled in 64 bit and couldn't use it so had to restart the process - see lines 29-36 below.


First of all, we need to download the MySQL client libraries and headers from Apple's website since they are not included with Mac OS X Server 10.5. The following instructions are taken directly off of Apple's knowledge base article located at http://support.apple.com/kb/TA25017?viewlocale=en_US.

To install:

Download the file from: http://www.opensource.apple.com/darwinsource/other/MySQL-43.binaries.tar.gz
If the download doesn't automatically produce a folder on your desktop, double-click it to unzip it to a folder named "MySQL-43.binaries" which has a file named "MySQL-43.root.tar.gz" in it (as well as the readme file). Note: Do not double-click/unzip the "MySQL-43.root.tar.gz" file that is within the folder.
Open Terminal.
Type cd (but do not press Return).
Drag the "MySQL-43.binaries" folder from your desktop to the Terminal window to populate the cd path, then press Return.
Execute this command:

sudo tar -xzvf MySQL-43.root.tar.gz -C /
Make sure you complete this step, you can not build PHP with MySQL support without these libraries and headers.

Lets go to a terminal and switch to the root user and create ourselves a work folder to keep everything in. Execute the following commands in your terminal window:

sudo -s
cd ~
mkdir work
cd work


set some environment variables for the compilers:

# MACOSX_DEPLOYMENT_TARGET=10.5
# CFLAGS="-arch x86_64 -g -Os -pipe -no-cpp-precomp"
# CCFLAGS="-arch x86_64 -g -Os -pipe"
# CXXFLAGS="-arch x86_64 -g -Os -pipe"
# LDFLAGS="-arch x86_64 -bind_at_load"
# export CFLAGS CXXFLAGS LDFLAGS CCFLAGS MACOSX_DEPLOYMENT_TARGET


PHP GD depends on the libjpeg library, so lets install this at /usr/local/libjpeg. Download and extract as shown.

wget http://www.ijg.org/files/jpegsrc.v6b.tar.gz
tar xfvz jpegsrc.v6b.tar.gz
cd jpeg-6b/
The configure script will throw an error unless you copy some configuration hints from the libtool library to the libjpeg source files directory. The libtool library is already included in OS X. Execute the following commands to obtain those files.

cp /usr/share/libtool/config.sub .
cp /usr/share/libtool/config.guess .
Configure and make, notice how we specify the install directory with PREFIX. You must compile libjpeg with the shared option, thus we use the "--enable-shared" flag.

./configure --prefix=/usr/local/libjpeg --enable-shared
make
Since this is such an old library, it won't automatically create the destination directories, you must do that manually before attempting to install.

mkdir -p /usr/local/libjpeg/include
mkdir -p /usr/local/libjpeg/bin
mkdir -p /usr/local/libjpeg/lib
mkdir -p /usr/local/libjpeg/man/man1
Now you can install and return to the work folder

make install
cd ..



Build and Install FreeType2
Some features of the GD library won't be enabled unless you have freetype2 installed. Download, extract, configure, build, and install to "/usr/local/freetype2" as shown.

wget http://savannah.inetbridge.net/freetype/freetype-2.3.8.tar.gz
tar xfvz freetype-2.3.8.tar.gz
cd freetype-2.3.8
./configure --prefix=/usr/local/freetype2
make
make install
cd ..



Build and Install GD
Download, extract, configure, build, and install libgd to "/usr/local/gd" as shown. Notice how we tell libgd where to find libjpeg and freetype2.

wget http://www.libgd.org/releases/gd-2.0.35.tar.gz
tar xfvz gd-2.0.35.tar.gz
cd gd-2.0.35
./configure --prefix=/usr/local/gd --with-jpeg=/usr/local/libjpeg --with-freetype=/usr/local/freetype2
make
make install
cd ..



Build and Install libmcrypt
Lots of PHP application want mcrypt (phpMyAdmin for example), so lets go ahead and get the mcrypt library setup. PHP recommends that you specify the following flags, "--disable-posix-threads" and "--enable-dynamic-loading".

Download, extract, configure, build, and install to "/usr/local/mcrypt" as shown.

wget http://voxel.dl.sourceforge.net/sourceforge/mcrypt/libmcrypt-2.5.8.tar.gz
tar xfvz libmcrypt-2.5.8.tar.gz
cd libmcrypt-2.5.8
./configure --prefix=/usr/local/mcrypt --disable-posix-threads --enable-dynamic-loading
make
make install
cd ..

Actually this one gave me grief, so I found I had to add --disable-dependency-tracking to the .configure command to get past the error of you can only compile for one architecture at a time. This took several tries and was not entirely a satisfying resounding "you got it right" result.



Build and Install PHP
It's time to build PHP. There are tons of configure options available, I have selected the most used. You may take a look at all available options by using the "--help" flag when you run the configure script. Keep in mind however, that some options may require additional dependencies not discussed here.

Download and Extract the latest PHP source code

wget http://us.php.net/get/php-5.2.8.tar.gz/from/this/mirror
tar xfvz php-5.2.8.tar.gz
cd php-5.2.8
Along with the desired features we want PHP to have, we must tell it where to find libgd, mcrypt, Apache, MySQL Client, libjpeg, and freetype2. Additionally, we must tell PHP where to find some of the Apple built in libraries. Thus we have a long and complex configure command as shown.

./configure --prefix=/usr/local/php5 --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql=/usr --with-mysql-sock=/var/mysql --with-mysqli=/usr/bin/mysql_config --with-zlib-dir=/usr --with-iodbc=/usr --with-curl=/usr --with-xsl=/usr --with-jpeg-dir=/usr/local/libjpeg --with-gd=/usr/local/gd --with-freetype-dir=/usr/local/freetype2 --with-mcrypt=/usr/local/mcrypt --enable-cli --enable-exif --enable-ftp --enable-mbstring --enable-mbregex --enable-sockets --with-openssl --with-xmlrpc --with-pear
Once PHP's make file is configured, lets build and install

make
make install
PHP will automatically modify the httpd.conf file in your Apache installation, but it won't add the application type. We'll take care of that part later.

once again I modified the .configure command a little: this is what I ended up with:
./configure --prefix=/usr/local/php5 --with-apxs2=/usr/sbin/apxs --with-openssl=/usr --with-zlib=/usr --with-zlib-dir=/usr --with-iodbc=/usr --with-gd=/usr/local/gd --with-ldap --with-xmlrpc --enable-exif --enable-soap --enable-sqlite-utf8 --enable-cli --enable-wddx --enable-ftp --enable-sockets --with-bz2=/usr --enable-zip --enable-pcntl --enable-shmop --enable-sysvsem --enable-sysvshm --enable-sysvmsg --enable-memory-limit --enable-mbstring --enable-mbregex --enable-sockets --enable-bcmath --enable-calendar --enable-memcache --with-kerberos=/usr --with-imap-ssl=/usr --with-libxml-dir=shared,/usr/ --with-xsl=shared,/usr --with-curl=shared,/usr --with-jpeg-dir=/usr/local/libjpeg --enable-gd-native-ttf --with-freetype-dir=/usr/local/freetype2 --with-mysql=shared,/usr/local/mysql --with-mysql-sock=/var/mysql --with-mysqli=shared,/usr/bin/mysql_config --with-mcrypt=shared,/usr/local/mcrypt --with-pear

the imap support flag was causing errors so I had to drop imap support for now.



edited the php.ini - put the working version in: /usr/local/php5/lib/php.ini

copied some mysql libraries, because it was looking for them in the wrong place. the copies are in /usr/local/php5/lib/mysql - the originals were in /usr/local/mysql and still are there.


I noticed in my colleague's configure for PHP 5, he pointed to the mysql_config at /usr/bin and not the one located in /usr/local/mysql. Also, I investigated the MySQL-43.binaries.tar.gz he downloaded. The instructions he followed meant that mysql binaries located in /usr/bin were replaced.

By executing /usr/bin/mysqlbug and /usr/local/mysql/bin/mysqlbug I was able to determine the configuration options of these mysql libraries and compare them. I discovered that the MySQL binaries in /usr/bin were from the mysql-5.0.45 (Source distribution) release and the binaries in /usr/local/mysql/bin were from the mysql-5.0.77 (MySQL Community Server (GPL)) release.

/usr/bin contained 4-way fat universal mysql binaries compiled with
CFLAGS=-O3 -fno-omit-frame-pointer -arch ppc -arch ppc64 -arch i386 -arch x86_64 -pipe
and the binaries in /usr/local/mysql/bin were just for 64-bit Intels compiled with
CFLAGS=-g -Os -arch x86_64 -fno-common

Ultimately, the solution was to use the fat mysql-5.0.45 release and the command to install the MySQL C binding was
gem install mysql -- --with-mysql-config=/usr/bin/mysql_config
This worked for both the stock Ruby on Rails stack and the /usr/local Ruby on Rails build.
blog comments powered by Disqus