How do programs support i386 and ppc at the same time? - macos

I would like to know how you can support i386 and ppc architectures for programs at /bin.
I run for instance
bin $ file amber
I get
amber: setgid Mach-O universal binary with 2 architectures
amber (for architecture i386): Mach-O executable i386
amber (for architecture ppc): Mach-O executable ppc
How do programs support i386 and ppc in the source code?
In other words, which components can you remove, for instance, in /bin/amber if you remove the support of ppc -architecture?

It's called a Universal binary. In short, the executable contains both types of executable code. Apple has a published document describing how developers should build their applications to run on either platform.
The executable lipo can be used to remove either version of the executable from the file. If you want your executables to contain only one version, you can use lipo to achieve this.
Be aware that there is more than just ppc and i386, although these are the "safest" architectures to choose for a Universal binary. Read the manpage for arch; there you can see that a modern OSX binary is likely to contain any of ppc, ppc64, i386 or x86_64. There are many more listed, but they exist there for completeness.

It's called a fat binary.
There's a copy of the native code for both architectures in the binary. The binary format and the operating system have to support it, so it can know where to look in the file for the correct code.

Related

Compiling 32-bit OS X binaries on a 64-bit environment

What is involved in compiling 32-bit Intel OS X binaries on a 64-bit command-line environment? Is it as simple as adding a -m32 flag? I'm not using Xcode, but could use it to install libraries that gcc could use, if needed. Thanks for your advice.
If you're compiling on a Macintosh computer using Apple's implementation of GCC, one of the extra options you can pass along is the "-arch" parameter.
The man page says this:
-arch arch
Compile for the specified target architecture arch.
The allowable values are i386, x86_64, ppc and ppc64.
Multiple options work, and direct the compiler to produce "universal"
binaries including object code for each architecture specified with -arch.
This option only works if assembler and libraries are available
for each architecture specified. (APPLE ONLY)

Can I build both 32-bit and 64-bit architectures of a library on Mac OS?

I need to build a library (Ipopt) on Mac OS X and use it from two different programs (Python & Matlab). However, one program is 32-bit and the other is 64-bit. Do I have to build two separate libraries of the two architectures then set the path accordingly for each program? Or can I build both architectures in the same library file(s) and the program will select the correct architecture to load? If I can, then how?
Thanks!
You can build both architectures and combine them into a single binary. The tool to do this is lipo.
For example, if you had built libpopt as a 32 bit library and placed it in lib/, and built it again as a 64 bit library and placed that in lib64/, then the command to combine these two could be:
lipo lib/libpopt.a lib64/libpopt.a -create -output libUniversal/libpopt.a
For more information, see the lipo man page (here, or through man lipo).

How do i remove the ppc section in growl framework?

Now i add growl notification support into my app ,when i submitted it to mac app store with organizer,it says that
"
Unsupported Architecture - Application executables may support either or both of the Intel architectures:
i386 (32-bit)
x86_64 (64-bit)
"
Finally i find that its issue by growl library, so i need to remove the ppc section in growl,so,how to?
Please help..
Use the lipo command line utility, which strips architectures off fat binaries (what an appropriate name). First, check which architectures there are in your Growl framework:
$ lipo -info path/to/Growl.framework/Growl
Architectures in the fat file: Growl are: x86_64 i386 ppc
In this case, we simply have ppc, but there are about 10 variants (of which I've met 3). To avoid any surprise, you should run this command any time you want to strip architectures from a file instead of just jumping to the removal part. (If you're curious, man 3 arch has the exhaustive list of possible architectures for fat binaries on Mac OS.)
Then, remove the ppc achitecture:
$ lipo -remove ppc path/to/Growl.framework/Growl -output GrowlIntel
Find the real Growl binary (should be under Versions somewhere) and replace it with GrowlIntel.
You can also use "ditto". I submitted my last Mac app with frameworks included that are stripped off ppc support using the two below commands. No rejections from Apple.
$ ditto -rsrc --arch i386 --arch x86_64 Growl-WithInstaller Growl-WithInstaller_noppc
$ lipo -info Growl-WithInstaller_noppc

OSX linking non-universal (i386) w/ universal .dylib

Is this legal? I'm getting an error "Can't find <lib>.framework/Versions/4/<lib>" from the linker. In this case, <lib> is 'QtGui' that has been built as an i386 framework (not universal), but another (third party) lib I'm linking to (that uses QtGui) is universal.
I'm thinking everything has to be built universal or not...
You can link a non-universal framework (say i386 only) with a universal framework (say with i386 and x86_64) to make an i386 binary.
Of course you can't make an x86_64 binary in this case.
Note that if your Mac has a 64 bit CPU, the linker defaults to mae an x86_64 binary. So the linker will complain if any of your library does not have the x86_64 part. If you want to create an i386 binary, you need to specify that explicitly on the command line.
Roger.
Turns out my issue actually stems from bad embedded paths in the external libraries that have to be reset (which I didn't think would affect links, but it does).
The universal build issue was a suspected culprit, but no.
Thanks,
rickb

Mac OSX 10.6 compiler: a puzzling experience with 32 vs 64 bit

I have trouble understanding the gcc compiler provided by OSX 10.6 snow leopard, mainly because of my lack of experience with 64 bits environments.
$ cat >foo.c
main() {}
$ gcc foo.c -o foo
$ file foo
foo: Mach-O 64-bit executable x86_64
$ lipo -detailed_info foo
input file foo is not a fat file
Non-fat file: foo is architecture: x86_64
However, my architecture is seen as an intel i386 type (I have one of the latest Intel Core2 duo MacBook)
$ arch
i386
and the compiler targets i686-apple-darwin10
$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5646)
Of course, if I compile 32 bits I get a 32 bit executable.
$ gcc -m32 foo.c -o foo
$ file foo
foo: Mach-O executable i386
but I don't get the big picture. The default setup for the compiler is to produce x86_64 executables, even if I have arch saying I have a 32 bit machine (why? Core2 is 64); even if (I guess) I am running a 32 bit kernel; even if I have a compiler targeting the i686-apple-darwin platform. Why? How can they run ? Should I compile 64 or 32 ?
This question is due to my attempt to compile gcc 4.2.3 on the mac, but I am having a bunch of issues with gmp, mpfr and libiberty getting (in some cases) compiled for x86_64. Should I compile everything x86_64 ? If so, what's the target (not i686-apple-darwin10 I guess)?
Thanks for the help
The default compiler on Snow Leopard is gcc4.2, and its default architecture is x86_64. The typical way to build Mac software is to build multiple architectures in separate passes, then use lipo to combine the results. (lipo only compiles single-arch files into a multiple-arch file, or strips archs out of a multi-arch file. It has no utility on single-arch files, as you discovered.)
The bitness of the compiler has nothing to do with anything. You can build 32-bit binaries with a 64-bit compiler, and vice versa. (What you think is the "target" of the compiler is actually its executable, which is different.)
The bitness of the kernel has nothing to do with anything. You can build and run 64-bit binaries when booted on a 32-bit kernel, and vice versa.
What matters is when you link, whether you have the appropriate architectures for linking. You can't link 32-bit builds against 64-bit binaries or vice versa. So the important thing is to see what the architectures of your link libraries are, make sure they're coherent, then build your binary of the same architecture so you can link against the libraries you have.
i686-apple-darwin10.0.0 contains an x86_64 folder which is not understood by most versions of autotools. In other words, I'd say that the gcc compiler is unfortunately nothing short of a joke on Snow Leopard. Why you would bundle 32-bit and 64-bit libraries into i686-apple-darwin10.0.0 is beyond me.
$ ls /usr/lib/gcc
i686-apple-darwin10 powerpc-apple-darwin10
You need to change all your autotools configure files to handle looking in *86-darwin directories and then looking for 64-bit libraries I'd imagine.
As with your system, my mac mini says its i386 even though its obviously using a 64-bit platform, again another mistake since its distributed with 64-bit hardware.
$arch
i386
Apple toolchains support multiple architectures. If you want to create a fat binary that contains x86 and x86_64 code, then you have to pass the parameters -arch i386 -arch x86_64 to gcc. The compiler will compile your code twice for both platforms in one go.
Adding -arch i386 -arch x86_64 to CFLAGS may allow you to compile gmp, mpfr, and whatnot for multiple archs in one go. Building libusb that way worked for me.
This answer is wrong, but see comments below
The real question is... how did you get a 32-bit version of OSX? I wasn't aware that Snow Leopard had a 32-bit version, as all of Apple's Intel chips are Core 2 or Xeon, which support the x86_64 architecture.
Oh, and Snow Leopard only works on Intel chips.
Edit: Apparently Snow Leopard starts in 32-bit mode.

Resources