5

Can I create a universal binary for Mac OS X that contains two versions of my app, one that is compiled with SSE4.2 and one that compiled with SSE3?

In this case I would the version compiled with SSE4.2 to be loaded automatically for CPU that support SSE4.2.

If no, I would like to get suggestions to run my app on old CPUs that do not support SSE4.2 but utilize SSE4.2 on CPU that support it.

Note that I target to the Mac AppStore, if that matter. I use Clang with Xcode 4.5.

Yoav
  • 5,962
  • 5
  • 39
  • 61
  • All you need to do is: 1) Detect the instruction set. 2) Branch to the version that you want. – Mysticial Sep 23 '12 at 22:08
  • [My answer here shows how to detect the instruction set.](http://stackoverflow.com/a/7495023/922184) The `__cpuid()` intrinsic is specific to MSVC. In GCC you can access it using inline assembly. I'm not sure what you're using though, but there should be a way to access it. – Mysticial Sep 23 '12 at 22:10
  • I prefer not changing the source code files as some of the lines that fail to run on old CPUs come from third party open source projects. – Yoav Sep 23 '12 at 22:59
  • If you can't change the source, then you're probably out of luck unless you 1) find a compiler option that does it. Or 2) build a wrapper. – Mysticial Sep 23 '12 at 23:01
  • That's why I'm looking for making a universal binary with two versions of the app. This would also have benefit that standard operations like ceil and floor would be translate to SSE4.1 instructions on the second version. – Yoav Sep 23 '12 at 23:04

1 Answers1

3

This is not supported by the Mach-O format, which is used by Mac OS X. The format allows binaries for different architectures. There is a subtype field, but there are only values defined for different generations of processors, not their abilities.

There are a couple of ways to work around this. One would be to have both SSE4.2 and code for older processors built into the same binary, using different function names. Your code would determine whether or not SSE4.2 is supported, then call the proper function.

Another option would be to build two libraries, one with SSE4.2 and one without, and ship both of them in your application bundle, but not link to them. When it is first loaded, your code would determine whether or not SSE4.2 is supported and then load the right library.

Using the first method, you don't have to worry about loading a library and connecting all of the functions, but you will always load extra code which does not get executed, and you will have to check a variable before each of those function calls. Using the second method, you can simply call the functions without checking anything every time, but loading the library and connecting all of the functions is more work than simply comparing a variable each time.

ughoavgfhw
  • 39,734
  • 6
  • 101
  • 123