How to fix mach-o, but wrong architecture on OSX Snow Leopard for Ruby Gems Bundle Files

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.

prompt$ file /usr/local/bin/ruby
/usr/local/bin/ruby: Mach-O executable i386


$ file /bin/ls
/bin/ls: Mach-O universal binary with 2 architectures
/bin/ls (for architecture x86_64): Mach-O 64-bit executable x86_64
/bin/ls (for architecture i386): Mach-O executable i386

In the case of RedCloth, removed the 64-bit bundle;
$ sudo /bin/rm /usr/local/lib/ruby/site_ruby/1.8/i686-darwin9.5.0/redcloth_scan.bundle

$ cd /usr/local/lib/ruby/gems/1.8/gems/RedCloth-4.2.2/ext/redcloth_scan/

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.