tpoechtrager / osxcross

Mac OS X cross toolchain for Linux, FreeBSD, OpenBSD and Android (Termux)
GNU General Public License v2.0
2.8k stars 318 forks source link

WIP: feat: add support for GCC targeting darwin arm64 #376

Closed shepherdjerred closed 1 year ago

shepherdjerred commented 1 year ago

I was able to get a working compiler targeting darwin 13.0 arm64. It uses an experimental GCC fork.

It required the following change to cctools.

diff --git a/cctools/ld64/src/ld/PlatformSupport.cpp b/cctools/ld64/src/ld/PlatformSupport.cpp
index 4869542..e081478 100644
--- a/cctools/ld64/src/ld/PlatformSupport.cpp
+++ b/cctools/ld64/src/ld/PlatformSupport.cpp
@@ -105,7 +105,7 @@ void VersionSet::checkObjectCrosslink(const VersionSet& objectPlatforms, const s
                 if (enforce == PlatEnforce::warnInternalErrorExternal) {
                     enforce = (internalSDK ? PlatEnforce::warning : PlatEnforce::error);
                 }
-                if ( platformMismatchesAreWarning && (enforce == PlatEnforce::error) )
+                if ( true && (enforce == PlatEnforce::error) )
                     enforce = PlatEnforce::warning;
                 switch (enforce) {
                     case PlatEnforce::allow:

Note: this results in a ton of warnings from ld. It thinks we're linking to iOS and not macOS. I think this is an issue with GCC. The resulting binaries seem to be fine.

shepherdjerred commented 1 year ago

@tpoechtrager Is there anything I can do to help get this merged in?

tpoechtrager commented 1 year ago

Yes, by extending build_gcc.sh instead of creating a new script to avoid a huge amount of duplicate code.

Symlink build_gcc.sh to build_gcc_arm64.sh. If the script is invoked by the build_gcc_arm64.sh symlink it should build the arm64 gcc.

Btw, I dont get what if [ ! -f README.md ]; then is meant for :)

It would also be neat if you could file a pull request @ cctools with something like this:

if ( (getenv("LD64_ALLOW_PLATFORM_MISMATCH") || platformMismatchesAreWarning) && (enforce == PlatEnforce::error) )

shepherdjerred commented 1 year ago

I'll make those changes!

Btw, I dont get what if [ ! -f README.md ]; then is meant for :)

It was a hack to avoid re-cloning the repo if it is already present. I think I can call one of your helper methods instead.

It would also be neat if you could file a pull request @ cctools with something like this:

I'm going to look further into why gcc is building for iOS rather than macOS. It would be nice to not be spammed with these errors.

shepherdjerred commented 1 year ago

I discovered why that linker error was occurring! It's a very simple fix -- we just need to tell GCC to build for a minimum macOS version. I'm not sure why it defaults to building for an iPhone if that isn't set, but it does.

Anyway, once that's set, it seems to build just fine. I will do a little more work making sure the C standard library works as expected, and then I'll polish this PR up.

@tpoechtrager I'm not sure if it interests you, but I setup another repo that builds these projects using Earthly. It kinda replaces a lot of the utilities scripts you've written -- the builds all run in Docker, and you get some nice things like parallelization and caching for free. And since it's in Docker, everything is containerized which makes the project a little easier to work on IMO. Just thought you might be interested :)

shepherdjerred commented 1 year ago

I'm going to have to put this on pause. Unfortunately, cctools doesn't emit a working arm64 assembler. I would love to get this merged in, but it has taken too much of my time, and I can't spend the required time to get cctools in a working state.

Attempting to run aach64-apple-darwin22-as results in the following:

fatal error: /workspaces/osxcross/target/bin/aarch64-apple-darwin22-as: unknown host architecture (can't determine which assembler to run)

I hacked around this in my working implementation by:

  1. Configuring cctools for arm rather than arm64. Required because cctools does not let us configure for arm64.
  2. Replacing arm with arm64 after configuring. Required so that we actually build for arm64 and not arm.
  3. Linking the resulting arm64 binaries as aarch64. Required so that the binaries match the target triple we're building for.

I've tried other workaround as mentioned in https://github.com/tpoechtrager/cctools-port/issues/6#issuecomment-152952902. I created a script that passed the arguments:

#!/bin/sh
arm64-apple-darwin22-as -target arm-apple-darwin -arch arm64 $@

This results in the following error when building libgcc:

$ make -j
...
configure: error: cannot compute suffix of object files: cannot compile

Digging into the config.log, this was the underlying error:

$ cat /workspaces/osxcross/build/build-gcc-13.0.1/x86_64-pc-linux-gnu/libgcc/config.log 
configure:3839: checking for suffix of object files
configure:3861: /workspaces/osxcross/build/build-gcc-13.0.1/./gcc/xgcc -B/workspaces/osxcross/build/build-gcc-13.0.1/./gcc/ -B/usr/local/x86_64-pc-linux-gnu/bin/ -B/usr/local/x86_64-pc-linux-gnu/lib/ -isystem /usr/local/x86_64-pc-linux-gnu/include -isystem /usr/local/x86_64-pc-linux-gnu/sys-include    -c -g -O2  conftest.c >&5
clang: error: unsupported option '--64'

I was building with the following on Ubuntu Jammy after running tools/get_dependencies.sh, and installing the GCC dependencies listed in the README, plus cmake and flex:

export SDK_VERSION=13.0
export OSX_VERSION_MIN=$SDK_VERSION
export MACOSX_DEPLOYMENT_TARGET=$SDK_VERSION
export PATH=/workspaces/osxcross/target/bin:$PATH
export GCC_VERSION=13.0.1
export TARGET_ARCHITECTURE=aarch64
export OCDEBUG=1
export DARWIN_MIN_LIB_VERSION=13.0

I ran the following commands in build after running build.sh:

rm -r build-gcc-13.0.1
mkdir build-gcc-13.0.1
cd build-gcc-13.0.1

rm /workspaces/osxcross/target/bin/aarch64-apple-darwin22-as
ln -s /workspaces/osxcross/aarch64-apple-darwin22-as /workspaces/osxcross/target/bin/aarch64-apple-darwin22-as 

../gcc-13.0.1/configure \
    --target=$triple \
    --with-sysroot=/workspaces/osxcross/target/SDK/MacOSX13.0.sdk \
    --disable-nls \
    --enable-languages=c,c++,fortran,objc,obj-c++ \
    --without-headers \
    --enable-lto \
    --enable-checking=release \
    --disable-libstdcxx-pch \
    --with-system-zlib \
    --disable-multilib \
    --with-ld=/workspaces/osxcross/target/bin/aarch64-apple-darwin22-ld \
    --with-as=/workspaces/osxcross/target/bin/aarch64-apple-darwin22-as

make -j