MacOS broken build between versions

Well this is fun; MacOS binaries built on MacOS 10.8 don’t necessarily run on 10.7. I tried copying some homebrew binaries between machines and got the useless error message “Illegal Instruction: 4”.

Turns out this is working as intended; by default clang is happy to build binaries that only work on the current OS, not older versions. Good discussion here. The fix is to build with -mmacosx-version-min=10.5 (or however far back you need to go). Homebrew doesn’t build with this flag, I imagine because their idea is you recompile code on every machine. That gets tedious with multiple macs on a slow network.

Breaking binary compatibility is a stupid thing.

 

3 thoughts on “MacOS broken build between versions

  1. huh. agreed it’s stupid…but out of curiosity, why copy binaries as opposed to brew install?

  2. On OS X, Apple strongly supports backward compatibility of executables (something that runs on 10.7 will run on 10.8) but does not guarantee forward compatibility. One big reason for that is that Apple strongly discourages static linking and doesn’t make static libs available for most OS X APIs. For backward compatibility newer OS X releases generally provide multiple versions of libs whose ABIs have changed from release to release. If you build on the latest release, by default, you’ll link to the latest versions which may not be available on older releases. However, the Apple compiler chain provided by Xcode does make it easy to build for the previous release by using the supplied SDK and macosx-version-min or the MACOSX_DEPLOYMENT_TARGET env variable. You can also install multiple versions of Xcode and use SDKs and compilers from even earlier releases to build universal executables that include architectures no longer supported on current releases, say if you want to release an app that will work on all Macs that run OS X 10.5 through 10.8. The Xcode IDE usually makes it easier to set and change these settings. Outside of the IDE, with well-behaved application autoconf-based Makefiles, it usually isn’t too difficult to have them do backward compatible, universal builds, often just by adding additional options to CFLAGS et al. There is some non-obsolete information in this old tech note: http://developer.apple.com/legacy/mac/library/#technotes/tn2064/_index.html. BTW, MacPorts provides global configuration options to set deployment targets and build archs just for this kind of use case. Homebrew has historically not attempted to support multiple releases.

  3. Thanks for the answers! I’m trying to copy Homebrew binaries because I have three computers I’m trying to keep updated. Homebrew’s package management is not a success and “brew upgrade” often fails me with dependency errors. I find I’m often wiping the whole directory and starting over.

    And Ned, thanks for the history on compatibility. I can argue either side of what the default should be, but Apple’s choice is at odds with most of Unix history. I don’t think Homebrew has any easy way to override the compiler flags, but I wonder if I could set HOMEBREW_CC to something and make it work.

    I should try MacPorts some day; most people say it’s too bulky, but I’m beginning to think ignoring most of what Apple calls Unix is a feature, not a bug. My real wish is that Fink were more popular; Debian’s package management tools are best-in-class.

Comments are closed.