MacOSX: Trimming fat from Mach-O fat files

MacOS X uses fat files.

A fat bundle contains data for different architectures. Here are some examples:

root@gilva:/Applications/Utilities/[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/[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/[02:09 AM]# mv Terminal Terminal.bak 
root@gilva:/Applications/Utilities/[02:10 AM]# ls
root@gilva:/Applications/Utilities/[02:10 AM]#lipo Terminal.bak -remove i386 -output Terminal
root@gilva:/Applications/Utilities/[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/[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/[02:10 AM]#

A quick test confirms that 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/[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/[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
    offset 16384
    size 8564
    align 2^12 (4096)
architecture ppc64
    cputype CPU_TYPE_POWERPC64
    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. 😛

One thought to “MacOSX: Trimming fat from Mach-O fat files”

Comments are closed.