MacOS X uses fat files.
A fat bundle contains data for different architectures. Here are some examples:
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:03 AM]# file *
Terminal: Mach-O fat file with 2 architectures
Terminal (for architecture i386): Mach-O executable i386
Terminal (for architecture ppc): Mach-O executable ppc
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:03 AM]#
or even:
stany@gilva:/System/Library/Frameworks/Accelerate.framework/Versions/A[02:07 AM]$ file Accelerate
Accelerate: Mach-O fat file with 3 architectures
Accelerate (for architecture i386): Mach-O dynamically linked shared library i386
Accelerate (for architecture ppc): Mach-O dynamically linked shared library ppc
Accelerate (for architecture ppc64): Mach-O 64-bit dynamically linked shared library ppc64
stany@gilva:/System/Library/Frameworks/Accelerate.framework/Versions/A[02:07 AM]$
In order to operate on fat bundles Apple provides a utility called lipo.
If you are in a situation where you are limited by processor architecture – for example, if you never expect to use internal hard drive of your iBook in firewire target mode to boot up an i386 system – it is possible to remove the extra “fat” from fat binaries, to save some disk space.
Here is an example:
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:09 AM]# mv Terminal Terminal.bak
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:10 AM]# ls
Terminal.bak
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:10 AM]#lipo Terminal.bak -remove i386 -output Terminal
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:10 AM]# ls -la
total 2296
drwxrwxr-x 4 root admin 136 Sep 6 02:10 .
drwxrwxr-x 7 root admin 238 Aug 31 00:07 ..
-rwxr-xr-x 1 root admin 386472 Sep 6 02:10 Terminal
-rwxrwxr-x 1 root admin 783784 May 14 22:22 Terminal.bak
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:10 AM]# file *
Terminal: Mach-O fat file with 1 architecture
Terminal (for architecture ppc): Mach-O executable ppc
Terminal.bak: Mach-O fat file with 2 architectures
Terminal.bak (for architecture i386): Mach-O executable i386
Terminal.bak (for architecture ppc): Mach-O executable ppc
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:10 AM]#
A quick test confirms that Terminal.app continues to run as before, however to make sure that everything is kosher I would probably want to correct permissions on the new binary to match what it was on the original.
Disk space saving will not be big, as an average .app consists of many other objects besides the executable itself, so this is probably not a very big issue. If one tries to remove a non-existing architecture from a binary, lipo will complain:
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:18 AM]#
lipo Terminal.bak -remove ppc64 -output Terminal
lipo: -remove ppc64 specified but fat file: Terminal.bak does not contain that architecture
root@gilva:/Applications/Utilities/Terminal.app/Contents/MacOS[02:19 AM]#
Another interesting option to lipo is -detailed_info:
stany@gilva:~[02:22 AM]$ lipo -detailed_info /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
Fat header in: /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
fat_magic 0xcafebabe
nfat_arch 3
architecture i386
cputype CPU_TYPE_I386
cpusubtype CPU_SUBTYPE_I386_ALL
offset 4096
size 8488
align 2^12 (4096)
architecture ppc
cputype CPU_TYPE_POWERPC
cpusubtype CPU_SUBTYPE_POWERPC_ALL
offset 16384
size 8564
align 2^12 (4096)
architecture ppc64
cputype CPU_TYPE_POWERPC64
cpusubtype CPU_SUBTYPE_POWERPC_ALL
offset 28672
size 8488
align 2^12 (4096)
stany@gilva:~[02:22 AM]$
writing a script that processes the output of:
find . -type f -perm -55 -exec file {} ; | grep i386 | sed 's/.for arch.*$//g'
while stripping out the arch, AND not screwing up the system is left as an excercise for the reader. 😛