Nat! bio photo

Nat!

Senior Mull

Twitter Github Twitch

Building true universal binaries - Intel and PPC - with Xcode 4 and gcc4.0

This entry is plagiarizing Meckis fine entry on StackOverflow, but doing it a little differently.

First I needed to install some Xcode3 stuff from the original distribution on my pristine Lion VM. I grabbed what I needed from my Snow Leopard DVD, which contained Xcode 3.2. There is a folder called Optional Installs, which contains a hidden folder Packages. I needed files contained in the following packages:

DeveloperTools.pkg // for one lousy PlugIn
DeveloperToolsCLI.pkg // assembler and linker
gcc4.0.pkg // the GCC 4.0 compiler
MacOSX10.4.Universal.pkg // the 10.4u SDK

I installed them in that order into a folder /Xcode3, I already had Xcode4 installed. These four packages do not overwrite anything outside of the destination folder, so the installation order doesn't matter if you install it like this.

cd /Volumes/Mac\ OS\ X\ Install/Optional\ Installs.localized/Packages
open DeveloperTools.pkg
open DeveloperToolsCLI.pkg
open gcc4.0.pkg
open MacOSX10.4.Universal.pkg

I have my Xcode4 installed in /Xcode4, because I am pretty sure there will be an Xcode5 in the future and I easily confuse. With this little shell script, running under sudo, I now do the necessary linking and patching. You can't copy paste these lines directly into a shell, it needs to run as a shell script.

#!/bin/sh
#
# coded by Nat!   Mulle kybernetiK
#
# mostly ripped off from Mecki
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4
#

XCODE3=${1:-/Xcode3}
shift
XCODE4=${1:-/Xcode4}
shift

cd "$XCODE4/SDKs"
ln -s "$XCODE3/SDKs/MacOSX10.4u.sdk"

#
# this is the only thing we need from DeveloperTools.pkg (!)
#
cd "$XCODE4/Library/Xcode/PrivatePlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins"
ln -s "$XCODE3/Library/Xcode/Plug-ins/GCC 4.0.xcplugin"

#
# get the 4.0 stuff
#
cd "$XCODE4/usr/bin"
for SRC_FILE in $XCODE3/usr/bin/*4.0*; do ln -s "$SRC_FILE" ; done

#
# this is different from what Mecki on StackOverflow does
#
# install the old assembler _and_ the old linker
# for both Intel and PPC
#
cd "$XCODE4/usr/libexec/gcc"
ln -s "$XCODE3/usr/libexec/gcc/powerpc-apple-darwin10"
ln -s "$XCODE3/usr/libexec/gcc/i686-apple-darwin10"

#
# (this actually changes stuff in Xcode3, but doesn't break it)
#
cd "$XCODE4/usr/libexec/gcc/powerpc-apple-darwin10/4.0.1/"
if [ ! -e as.old ]
then
        mv as as.old
        mv ld ld.old
fi
ln -s "$XCODE3/usr/bin/as"
ln -s "$XCODE3/usr/bin/ld"

cd "$XCODE4/usr/libexec/gcc/i686-apple-darwin10/4.0.1/"
if [ ! -e as.old ]
then
        mv as as.old
        mv ld ld.old
fi
ln -s "$XCODE3/usr/bin/as"
ln -s "$XCODE3/usr/bin/ld"


#
# now make it nicey, nicey and patch Xcode to show Universal build options
#
cd "$XCODE4/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications"
if [ ! -e MacOSX\ Architectures-apple.xcspec ]
then
   cp MacOSX\ Architectures.xcspec MacOSX\ Architectures-mulle.xcspec
   mv MacOSX\ Architectures.xcspec MacOSX\ Architectures-apple.xcspec
fi

ln -s MacOSX\ Architectures-mulle.xcspec MacOSX\ Architectures.xcspec

# you (or at least I) can't copy paste this into a shell so this is the
# reason this is done as shell script

cat <<EOF | patch -N MacOSX\ Architectures-mulle.xcspec
--- MacOSX Architectures-apple.xcspec   2011-07-22 01:01:18.000000000 +0200
+++ MacOSX Architectures-mulle.xcspec   2011-07-22 00:57:54.000000000 +0200
@@ -21,7 +21,20 @@
        },
        {
                Type = Architecture;
-               Identifier = Universal64bit;
+               Identifier = Universal;
+               Name = "32-bit Universal";
+               Description = "32-bit Mac OS X universal architectures";
+               ListInEnum = YES;
+               SortNumber = 7;
+               RealArchitectures = (
+                       i386,
+                       ppc,
+               );
+               ArchitectureSetting = "ARCHS_UNIVERSAL_32_BIT";
+       },
+       {
+               Type = Architecture;
+               Identifier = Standard64bit;
                Name = "64-bit Intel";
                Description = "64-bit Mac OS X architectures";
                ListInEnum = YES;
@@ -33,7 +46,7 @@
        },
        {
                Type = Architecture;
-               Identifier = "Universal32_64_Bit";
+               Identifier = "Standard32_64_Bit";
                Name = "Standard (32/64-bit Intel)";
                Description = "32- and 64-bit Mac OS X architectures";
                ListInEnum = YES;
@@ -46,6 +59,20 @@
        },
        {
                Type = Architecture;
+               Identifier = "Universal32_64_Bit";
+               Name = "Universal (32/64-bit)";
+               Description = "32- and 64-bit Mac OS X universal architectures";
+               ListInEnum = YES;
+               SortNumber = 8;
+               RealArchitectures = (
+                       "x86_64",
+                       i386,
+                       ppc,
+               );
+               ArchitectureSetting = "ARCHS_UNIVERSAL_32_64_BIT";
+       },
+       {
+               Type = Architecture;
                Identifier = Native;
                Name = "Native Architecture of Build Machine";
                Description = "Native 32- or 64-bit architecture of build machine";
@@ -73,4 +100,42 @@
                ListInEnum = NO;
                SortNumber = 106;
        },
+       {
+               Type = Architecture;
+               Identifier = ppc;
+               Name = "Minimal (32-bit PowerPC only)";
+               Description = "32-bit PowerPC";
+               "PerArchBuildSettingName" = PowerPC;
+               ByteOrder = big;
+               ListInEnum = No;
+               SortNumber = 201;
+       },
+       {
+               Type = Architecture;
+               Identifier = ppc7400;
+               Name = "PowerPC G4";
+               Description = "32-bit PowerPC for G4 processor";
+               ByteOrder = big;
+               ListInEnum = NO;
+               SortNumber = 202;
+       },
+       {
+               Type = Architecture;
+               Identifier = ppc970;
+               Name = "PowerPC G5 32-bit";
+               Description = "32-bit PowerPC for G5 processor";
+               ByteOrder = big;
+               ListInEnum = NO;
+               SortNumber = 203;
+       },
+       {
+               Type = Architecture;
+               Identifier = ppc64;
+               Name = "PowerPC 64-bit";
+               Description = "64-bit PowerPC";
+               "PerArchBuildSettingName" = "PowerPC 64-bit";
+               ByteOrder = big;
+               ListInEnum = NO;
+               SortNumber = 204;
+       }
 )
EOF

In the end it looks like this in Xcode4, notice the different wording in Architectures. Because I am using additional identifiers, there may be backwards incompatibilities.

Xcode4 universal