Sunday, March 13, 2011

Compiling the mysql-python bindings as a Universal binary

For a project I needed a copy of the mysql-python bindings that would run on every version of MacOS back to 10.5.0. But the compiled versions I could find of both the latest MySQL and the bindings were mostly for 10.6, and were either i386 or x86_64. So besides needing two versions (or to glue them together), that still left 10.5 computers, especially 10.5 ppc computers out in the cold.

All of the instructions that I could find to make Universal Binaries for both MySQL and the python bindings were written before MySQL switched to cmake, or did not cover making Universal Binaries. Since this took my a little while, I would like to have this documented for myself. So here is my documentation, available for general perusal.

To lead off, I am going to recommend that you do all of this on a partition that you don't care about, as following these instructions will install the MySQL binaries, but will not do any of the setup needed to get MySQL up and running (creating databases and users, etc...). So I would install the target OS on a volume that can be erased after you have what you need.

You will need:

  • a volume with the minimum OS you want to support on it, preferably one you can mess up
  • the XCode tools installed on that volume (or at least gcc)
  • the following downloads: MySQL source code (5.5.9), cmake (2.8.4), and MySQL-Python(1.2.3)

I should note the places this process could be improved:

  • we don't need to compile or install the MySQL server
  • there is probably a way of getting the MySQL-Python bindings to compile from the compiled version of MySQL, rather than the installed version
  • it would be better to have a staticly compiled version of the bindings that did not need the libmysqlclient.16.dylib file in the same folder (or installed)
  • figure out how to use the sdk properly in the MySQL-Python compile so you could do this from latter versions of the OS targeting older versions

  1. Download and install (or make and install) cmake.
  2. Download and uncompress the latest versions of MySQL-Python and MySQL server, specifically the "Generic Linux" tar archive.
  3. In the terminal create a temprary folder and use cmake to configure the compile of mysql:
    mkdir /tmp/buildTemp
    cd /tmp/buildTemp
    cmake "-DCMAKE_OSX_ARCHITECTURES=ppc;i386;x86_64 -DCMAKE_OSX_SYSROOT=/Developer/SDKs/MacOSX10.5.sdk" /path/to/mysql/source
  4. Compile, and then install MySQL (this gets both the client and server, the latter we don't need):
    sudo make install
  5. Confirm that MySQL was built with the right architectures:
    file /usr/local/mysql/lib/libmysqlclient.16.dylib
  6. Open the "site.cfg" file in the MySQL-Python source folder in your text editor of choice, and un-comment the "mysql_config" line and change it to point at where it at where it defaults to on MacOS X:
  7. Compile MySQL-Python:
    cd /path/to/mysql-python/source/
    export ARCHFLAGS="-arch ppc -arch i386 -arch x86_64"
    python build
  8. Verify that is built as a Universal Binary:
    file build/lib.macosx-10.5-i386-2.5/
  9. Copy libmysqlclient.16.dylib in with the rest of the built files to create a library that is portable (note the exact path can differ):
    cp /usr/local/mysql/lib/libmysqlclient.16.dylib build/lib.macosx-10.5-i386-2.5/
  10. Verify that the client works as expected
    cd build/lib.macosx-10.5-i386-2.5
    >>> import MySQLdb
    >>> connection = MySQLdb.connect(host='', user='db_user', db='db_name', password='db_password')
    >>> cursor = connection.cursor()
    >>> cursor.execute('select * from `my_table`)
    >>> cursor.fetchone()

You will now have a folder (lib.macosx-10.5-i386-2.5) containing everything you need to import into your project in order to get MySQL working with your Python code. You should be able to copy this folder onto a freshly-installed system with no additional installs and be able to make a connection to a MySQL database running on some computer.