Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, PHP, and whatever else I happen to feel like hacking at.

Create universal files on Mac OS X

Jerry Stratton, September 2, 2009

I’ve been getting a new server ready, and as usual the only big issues are architecture issues: 32-bit vs. 64-bit. I had to use 64-bit to set up PHP’s MySQL module, but when I went to install Perl’s MySQL module I had to install the 32-bit version over it. In Mac OS X Leopard, Apache runs as 64-bit, but Perl runs as 32-bit.

So I installed the i386 version. But as soon as I did that, PHP stopped working.

[toggle code]

  • dyld: Library not loaded: /usr/local/mysql/lib/libmysqlclient.15.dylib
  • Referenced from: /usr/lib/php/extensions/no-debug-non-zts-20060613/pdo_mysql.so
  • Reason: no suitable image found. Did find:
    • /usr/local/mysql/lib/libmysqlclient.15.dylib: mach-o, but wrong architecture

Of course, when I switched it back to x86_64, Perl stopped working:

[toggle code]

  • install_driver(mysql) failed: Can't load '/Library/Perl/5.8.8/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle' for module DBD::mysql: dlopen(/Library/Perl/5.8.8/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle, 1): Library not loaded: /usr/local/mysql/lib/libmysqlclient.15.dylib
  • Referenced from: /Library/Perl/5.8.8/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle
  • Reason: no suitable image found. Did find:
    • /usr/local/mysql/lib/libmysqlclient.15.dylib: mach-o, but wrong architecture at /System/Library/Perl/5.8.8/darwin-thread-multi-2level/DynaLoader.pm line 230.
  • at (eval 3) line 3
  • Compilation failed in require at (eval 3) line 3.
  • Perhaps a required shared library or dll isn't installed where expected

This is the problem:

  • Perl comes installed only as 32-bit.
  • Apache runs as 64-bit, which means that the PHP module runs as 64-bit.
  • To get PHP to load MySQL requires installing MySQL as 64-bit.
  • To get Perl to load MySQL requires installing MySQL as 32-bit.
  • There is no combined package install of MySQL for both 32-bit and 64-bit.

The culprit is /usr/local/mysql/lib/libmysqlclient.15.dylib. It is loaded dynamically, so you can’t just install one, get PHP working, then install the other to get Perl working. As soon as you switch to 32-bit, PHP stops working; as soon as you switch to 64-bit, Perl stops working.

Rather than try to compile MySQL to a universal file and worry about that process bringing up its own issues, I thought I’d see if there was an easy way to combine libraries of different architectures into a universal file. There is: lipo.

I extracted the i386 version to a different volume, but you could also extract one, get the libmysqlclient.15.dylib from it, and then extract the other.

  • $lipo -create /Volumes/madness/usr/local/mysql/lib/libmysqlclient.15.dylib /usr/local/mysql/lib/libmysqlclient.15.dylib -output libmysqlclient.15.dylib
  • $file libmysqlclient.15.dylib
  • libmysqlclient.15.dylib: Mach-O universal binary with 2 architectures
  • libmysqlclient.15.dylib (for architecture i386): Mach-O dynamically linked shared library i386
  • libmysqlclient.15.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64

Then, move that file to to /usr/local/mysql/lib and you should be good to go.

Reminder: you can attach DMG files from the command line using hdiutil, and you can install from a package using installer:

  • hdiutil attach FILE.dmg
  • cd /Volumes/FILE
  • sudo installer -verbose -pkg FILE.pkg -target /
  • sudo installer -verbose -pkg FILE.pkg -target /Volumes/madness/

Note that the target of the installer is a volume. You can put any path you want there, but it will use the root of the volume the path is on as its installation point.

  1. <- Automatic images in XHTML
  2. Django cache time ->