Coding

Fun With Apple Multi-Arch Binaries

Apple macOS has for many years supported the ability to have binaries for multiple platforms in one executable. Upon execution the correct binary data is loaded into RAM. This has multiple names such as “Universal”, “fat binary” or “Multi-Architecture Binaries”. These were really useful when Apple was transition from PowerPC to Intel CPUs, a single binary would execute on both platforms. It could be useful in the future if, as many predict, Apple move from Intel to ARM CPUs.

In this post I’ll talk about the m4 script I wrote at HP to use this feature for combined 32bit and 64bit Intel binaries (back when that was relevant).

I was working on a high-performance asynchronous C API to connect to MySQL servers around 2014 which was to be used by HP. As part of this I wanted to make it work on as many platforms as possible. Quite a few people in my division used Apple hardware so I wanted to make it work on that. At the time I had access to both 32bit and 64bit Apple hardware and wanted my binaries to work on both. Hence building this solution.

I was using autotools back then as it is my preferred build system, so after figuring out how to do it I created a script which would build a single library that simultaneously worked for x86 and x86_64 platforms. The script is as follows:

# SYNOPSIS
#
#   AX_UNIVERSAL_BINARY()
#
# DESCRIPTION
#
#   --enable-universal-binary
#
# LICENSE
#
#  Copyright 2014 Hewlett-Packard Development Company, L.P.
#  All rights reserved.
#
# [CUT BSD 3-Clause license, see SPDX-License-Identifier: BSD-3-Clause]

#serial 2

AC_DEFUN([AX_UNIVERSAL_BINARY],
    [AC_ARG_ENABLE([universal-binary],
                   [AC_HELP_STRING([--enable-universal-binary=auto],
                                   [Apple combined x86 & x86_64 binary support])],,
                   [enable_universal_binary=auto])
    have_universal_binary=no
    if test x"enable_universal_binary" != x"no"; then
        AC_CANONICAL_HOST
        AC_MSG_CHECKING([for universal binary support])
        case $host in *-apple-darwin*)
            save_CFLAGS="$CFLAGS"
            save_CXXFLAGS="$CXXFLAGS"
            save_LDFLAGS="$LDFLAGS"
            CFLAGS="$CFLAGS -arch x86_64 -arch i386"
            CXXFLAGS="$CXXFLAGS -arch x86_64 -arch i386"
            LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
            AC_LINK_IFELSE([AC_LANG_SOURCE([int main() {return 0;}])],
                          [have_universal_binary=yes])
            if test x"$have_universal_binary" = x"no"; then
                CFLAGS="$save_CFLAGS"
                CXXFLAGS="$save_CXXFLAGS"
                LDFLAGS="$save_LDFLAGS"
            fi
            ;;
        esac
        AC_MSG_RESULT($have_universal_binary)
    fi
    case "$have_universal_binary:$enable_universal_binary" in
        no:yes) AC_MSG_ERROR([no universal binary support on this host]) ;;
        yes:*)  AC_MSG_WARN([disabling dependency tracking])
                AM_CONDITIONAL([AMDEP],[false])
                AM_CONDITIONAL([am__fastdepCC],[false])
                AMDEPBACKSLASH=
                ;;
    esac])

You can see here that it first looks “Apple Darwin” which is the macOS kernel and the advertised platform. If we don’t have this then we error saying that we cannot do this.

In the compiler we specify multiple archs, in this case x86_64 and i386. The compiler knows what to do with this and we have a very simple test to build to make sure it works.

If we get this far the script disables dependency tracking. I honestly can’t remember why now (it has been 6 years) but I know dependency tracking didn’t work.

Summary

There have been attempts to do this in Linux too using a project called “FatELF“. This doesn’t appear to have taken off but I think it would be very interesting if more work was put into this. Especially with ARM and Intel both becoming major Linux platforms.

LinuxJedi

Share
Published by
LinuxJedi

Recent Posts

Working with the AVR Dx family

In recent years, Microchip has launched a new range of AVR chips. They appear to…

4 days ago

My WordPress Slack ban

A couple of days ago, I got banned from the WordPress community Slack. As this…

5 days ago

Issues I found during WordPress.com to .org migration

Whilst migrating from wordpress.com to an installation of the open source WordPress, I hit some…

1 week ago

Why I moved my blog

Unfortunately, there is a war going on within the WordPress community. To stay as far…

1 week ago

Four new Amiga products for September 2024

Since the June Amiga Expo, I have been developing some new Amiga related products. I…

3 weeks ago

Repairing an Amiga that caught on fire!

Karl at Retro32 likes to challenge me, and this time he had an interesting one.…

1 month ago