Ran into the annoying mach-o problem for compiled rubygem extensions on a few gems (mainly RedCloth and CSVScan). First pass at Google rendered a few people who had experienced similar problems but no real solutions. Finally broke down and figured out how to fix it.

First, what is the problem; in the land of OSX you have many architectures this includes the old PowerPC world, 32-bit (i386), and 64-bit (x86_64). In the old world everything was always 32-bit and nobody was the wiser, but with Snow Leopard the world changed and suddenly you could run things in 64-bit. So here’s the rub, 64-bit and 32-bit dont play nicely together. They are consider different architectures and even as Apple has done a great job to provide 32-bit emulation when you have a 64-bit app that tries to access a 32-bit library or vs versa things stop working.

The fix is pretty simple, figure out what architecture your primary application is, then re-compile the library to comply. This error pops up usually as a “mach-o, but wrong architecture” error. And this is true across all languages but in this case I will explain how I fixed my rubygems that had incompatible bundle files.

Step 1: Identify which architecture you need. This goes both ways, if you have a 32-bit app with a 64-bit library you need a 32-bit library to run. If you have a 64-bit app with a 32-bit library you need a 64-bit library. Easiest way is to use the “file” command. If you dont mind larger executables you can compile all architectures in, but this wastes space. Below see a few examples.

Now you can edit your Makefile to include the ‘-arch i386’ or ‘-arch x86_64’, once again you can add one or both. For some reason most of the gem builds scripts don’t account for what version of ruby you run and default to 64-bit which is where the problem originates.

Edit your CFLAGS and ldflags or archflag and just add ‘-arch i386’ or ‘-arch x86_64’ to the lines. Run a make clean; make … then go back to the root of your gem and run the ruby setup.rb install. Make sure you dont re-run config as this will overwrite your Makefile changes. This will install your new bundle and you should be ready to go.