I'm currently wring a Cocoa application which needs to execute some (console) applications which are optimized for 32 and 64 bit. Because of this I would like to detect what CPU architecture the application is running on so I can start the correct console application.

So in short: how do I detect if the application is running on a 64 bit OS?

Edit: I know about the Mach-O fat binaries, that was not my question. I need to know this so I can start another non bundled (console) application. One that is optimized for x86 and one for x64.

Even when you do not have the source, you can combine two binaries you already have. Remember, fat binaries work for non-bundled console binaries! Just do what cgkanchi suggested, lipo -create -arch i386 bin32 -arch x86_64 bin64 -output bin_universal.
–
YujiJan 1 '10 at 18:57

EDIT: D'oh! I didn't realise you'd need runtime checking... Going through the output of sysctl -A, two variables look potentially useful. Try parsing the output of sysctl hw.optional.x86_64 and sysctl hw.cpu64bit_capable . I don't have a 32-bit Mac around to test this, but both these are set to 1 in Snow Leopard on a Core2Duo Mac.

That one does not work. If your executable is compiled with 32 bit it delivers NSBundleExecutableArchitectureI386 no matter what the OS is.
–
Andreas LöwOct 19 '12 at 14:14

Of course, that's how it works. It tells you which architecture your application is running on. x86_64 CPU can emulate and run an app in i386. If your binary is compiled in i386 only, it will run in i386. If it's universal, it will usually run in x86_64 on x86_64 CPU, unless you've changed kernel options to run in i386 or if you run your app via arch -32 ... for example. If you want to know CPU architecture regardless of the running app's architecture, read hw.machine via sysctl as answered by bleater for example.
–
Mirek RusinApr 10 '14 at 13:57

You don't have to detect it manually to achieve that effect. One Mach-O executable file can contain both binaries for 32 bit and 64 bit intel machines, and the kernel runs the most appropriate ones automatically. If you're using XCode, there's a setting in the project inspector where you can set the architectures (ppc, i386, x86_64) you want to have in a single universal binary.

Also, remember that on OS X, running a 64-bit kernel (with Snow Leopard) and being able to run a 64-bit user land app are two orthogonal concepts. If you have a machine with 64 bit cpu, you can run a user-land program in a 64-bit mode even when the kernel is running in the 32 bit mode (with Leopard or Snow Leopard), as long as all of the libraries you link with are available with 64 bit. So it's not that useful to check if the OS is 64-bit capable.

I thought I was clear about this. I try to explain better. I want to call a NON FAT binary. One is optimized for x86 and one for x64. I did not create the binaries and do not have the source. To choose the best optimized non-fat binary I need to know what cpu I run on.
–
Ger TeunisJan 1 '10 at 18:01

@Ger Teunis: The accepted answer is also compile time (the sizeof part) and it just doesn't matter. If someone runs your 32 bit binary despite the fact that you provide both a 64 and a 32 bit one, there is really little point in not considering the world to be 32-bit even if it happens to be a 64-bit machine.
–
FredrikJan 1 '10 at 18:58

That is correct, but they provided the lipo solution which works fine. I agree the original question isn't answered but lipo solved my problems.
–
Ger TeunisJan 1 '10 at 19:30

Usually, you shouldn't need to be able to check at runtime whether you're on 64 or 32 bits. If your host application (that's what I'd call the app that launches the 64 or 32 bit tools) is a fat binary, the compile-time check is enough. Since it will get compiled twice (once for the 32-bit part of the fat binary, once for the 64-bit part), and the right one will be launched by the system, you'll compile in the right launch code by just writing sth. like

If the user somehow explicitly launches your app in 32 bits on a 64 bit Mac, trust them that they know what they're doing. It's an edge case anyway, and why break things for power users out of a wrong sense of perfection. You may even be happy yourself if you discover a 64-bit-only bug if you can tell users the workaround is launching as 32 bits.

You only need a real runtime check if your app itself is only 32 bits (e.g. Carbon GUI with command-line helper). In that case, host_processor_info or sysctl or similar are probably your only route if for some weird reason you can't just lipo the two executables together.