iains / gcc-darwin-arm64

GCC master branch for Darwin with experimental support for Arm64. Currently GCC-15.0.0 [September 2024]
GNU General Public License v2.0
268 stars 33 forks source link

Cross-compiler can’t link #87

Closed simonjwright closed 2 years ago

simonjwright commented 2 years ago

I've been building GCC-with-Ada cross-compilers to arm-eabi for some time now, so thought that x86_64->aarch64 (macOS) wouldn't be that bad - forgetting the time it took to work out reliable scripts!

Running with darwin 21.4.0, command line tools 13.3.0.

So far I've found most help from @fxcoudert's issue #34, and my current script for the cross-compiler is

$GCC_SRC/configure                          \
    --prefix=$XPREFIX                       \
    --program-prefix=                       \
    --without-libiconv-prefix               \
    --disable-libmudflap                    \
    --disable-libstdcxx-pch                 \
    --disable-libsanitizer                  \
    --disable-libcc1                        \
    --disable-libcilkrts                    \
    --disable-multilib                      \
    --disable-nls                           \
    --enable-languages=c,c++,ada            \
    --target=$ARM                           \
    --build=$X86                            \
    --without-isl                           \
    --with-sysroot=$CLU                     \
    --with-build-config=no                  \
    --disable-bootstrap                     \
    AR_FOR_TARGET=/usr/bin/ar               \
    AS_FOR_TARGET=/usr/bin/as               \
    DSYMUTIL_FOR_TARGET=/usr/bin/dsymutil   \
    LD_FOR_TARGET=/usr/bin/ld               \
    LIPO_FOR_TARGET=/usr/bin/lipo           \
    NM_FOR_TARGET=/usr/bin/nm               \
    OBJDUMP_FOR_TARGET=/usr/bin/objdump     \
    OTOOL_FOR_TARGET=/usr/bin/otool         \
    RANLIB_FOR_TARGET=/usr/bin/ranlib       \
    STRIP_FOR_TARGET=/usr/bin/strip

make -w -j7

make -w -j7 install

where --program-prefix= successfully means that tools are named gcc rather than aarch64-apple-darwin21-gcc. Must of the other switches are the ones I'd use for a normal build; $CLU is actually xcrun --show-sdk-path.

This compiles C, C++ and Ada source code successfully. Unfortunately, there's a problem with linking:

temeraire:tmp simon$ aarch64-apple-darwin-cross-6/bin/gcc hello.c
...
 /Users/simon/tmp/aarch64-apple-darwin-cross-6/libexec/gcc/aarch64-apple-darwin21/12.0.1/collect2 -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/ -dynamic -arch arm64 -macosx_version_min 12.0 -o a.out -L/Users/simon/tmp/aarch64-apple-darwin-cross-6/lib/gcc/aarch64-apple-darwin21/12.0.1 -L/Users/simon/tmp/aarch64-apple-darwin-cross-6/lib/gcc/aarch64-apple-darwin21/12.0.1/../../../../aarch64-apple-darwin21/lib /var/folders/ch/k_zwspdx3qsfbt1_x21zld6m0000gn/T//ccHy48l9.o -lemutls_w -lgcc -lSystem -lgcc -no_compact_unwind -rpath @loader_path -rpath /Users/simon/tmp/aarch64-apple-darwin-cross-6/lib/gcc/aarch64-apple-darwin21/12.0.1 -rpath /Users/simon/tmp/aarch64-apple-darwin-cross-6/lib/gcc/aarch64-apple-darwin21/12.0.1/../../../../aarch64-apple-darwin21/lib
collect2: fatal error: cannot find 'ld'
compilation terminated.

which is odd, considering I configured with LD_FOR_TARGET=/usr/bin/ld, and I also said AS_FOR_TARGET=/usr/bin/as and as was called with no trouble.

The cure I found was to put this symlink on the PATH:

aarch64-apple-darwin21-ld -> /Library/Developer/CommandLineTools/usr/bin/ld

(linking to /usr/bin/ld didn't work).

I also found that bin/gcc-ar said

$ aarch64-apple-darwin-cross-6/bin/gcc-ar
aarch64-apple-darwin-cross-6/bin/gcc-ar: Cannot find binary 'aarch64-apple-darwin21-ar'

and similarly -nm, -ranlib.

Looking at the source of collect2, it seems only to search for ld, so where aarch64-apple-darwin21-ld comes from isn't obvious.

Clearly I could do the symlink trick above to get to the stage of building the native aarch64 compiler, but I can't help feeling I've missed something. Help!

iains commented 2 years ago

I build a cross (and a native cross) at least once a week (after rebasing).

However, I use the "standard" GCC method (AFAIK using the same compiler is required for a reliable Ada build).

  1. bootstrap native into --prefix=/where/we/want/it --build=x86_64-apple-darwinMM ... --with-sysroot=...
  2. add /where/we/want/it/aarch64-apple-darwinNN/bin/{with symlinks to the tools ar, as, ld, lipo, lib tool, otool, objdump,strip, stings, ran lib}
  3. configure with --prefix=/where/we/want/it --target=aarch64-apple-darwinNN --build=x86_64-apple-darwinMM --with-sysroot=...

which works fine (and the resulting compiler works); I do not find it necessary to disable lots of the libraries etc.

I suspect you can drop most of the options you have and just use --with-as=/usr/bin/as --with-ld=/usr/bin/ld --with-dsymutil=/usr/bin/dsymutil

(unless you use the trick with the aarch64-apple-darwinNN/bin) the top level configure wants to see tools named aarch64-apple-darwinNN-xxxx.

When you look at the output of the top level configure you should see paths to valid tools in the last section.

iains commented 2 years ago

I do not know of a solution (other than either providing a symlink for aarch64-apple-darwinNN-xxxx or the parallel directory) for the references in gcc-ar, gcc-as, gcc-ranlib.

simonjwright commented 2 years ago

I got a successful cross-build with the script as above with the addition of --with-as=/usr/bin/as --with-ld=/usr/bin/ld --with-dsymutil=/usr/bin/dsymutil and --with-ranlib=/usr/bin/ranlib.

I find that if you symlink

aarch64-apple-darwin21-ranlib -> /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/../../usr/bin/ranlib

then aarch64-apple-darwin21-ranlib thinks it is libtool with, of course, a quite different argument set and, specifically, a requirement to supply -o.

Thanks for the help!

iains commented 2 years ago

I find that if you symlink

aarch64-apple-darwin21-ranlib -> /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/../../usr/bin/ranlib

then aarch64-apple-darwin21-ranlib thinks it is libtool with, of course, a quite different argument set and, specifically, a requirement to supply -o.

This is a long-standing issue with cctools ranlib (it is actually an alias for libtool - but libtool only looks at the first 6 characters of the filename to determine if it has been invoked as 'ranlib' ... I fixed this in my Xtools/cctools stuff (by looking at the trailing 6 chars).

The alternative is to put a small shell script as the tool like so (assuming that the real ranlib is in the same directory (I am sure you can amend the idea to suit whatever layout you have):

xxxxx-apple-darwinNN-ranlib:
#!/bin/sh
exec $(dirname ${0})/ranlib ${@}
exit 1
simonjwright commented 2 years ago

Actually, I found that having built the cross-compiler as above, I didn't need to define the symlinks for the native aarch64 to build - but I did define

        --with-as=/usr/bin/as                                                \
        --with-ld=/usr/bin/ld                                                \
        --with-ranlib=/usr/bin/ranlib                                        \
        --with-dsymutil=/usr/bin/dsymutil                                    \

just in case (I freely admit to fumbling in the dark at this point).

I did run the compiler against ACATS 4.1Y, with very minor differences from the x86_64 results - are you interested? I could post in this issue (it will end up in a blog in due course anyway)

iains commented 2 years ago

Actually, I found that having built the cross-compiler as above, I didn't need to define the symlinks for the native aarch64 to build - but I did define

        --with-as=/usr/bin/as                                                \
        --with-ld=/usr/bin/ld                                                \
        --with-ranlib=/usr/bin/ranlib                                        \
        --with-dsymutil=/usr/bin/dsymutil                                    \

I don't think --with-ranlib= does anything, and you are just seeing default behaviour (which is it finds the first one in $PATH - which is most-of-the-time OK on macOS if the host version is close to the target one .. but breaks, for example, when trying to do a cross from newer x86_64 => old powerpc).

I did run the compiler against ACATS 4.1Y, with very minor differences from the x86_64 results - are you interested? I could post in this issue (it will end up in a blog in due course anyway)

I do test Ada on all the platform versions I test... The GCC acats version [I don't know if that is the same version you are testing] results are in here (+ the GCC gnat testsuite) https://github.com/iains/gcc-darwin-arm64/issues/30#issuecomment-1072997727

similar?

simonjwright commented 2 years ago

The ACATS tests in GCC are based on version 2.6. There are some timing adjustments, and all the B-tests (tests to check that the compiler detects errors as it should) are omitted.

ACATS 2 is for Ada 95, ACATS 3 is for Ada 2005, and ACATS 4 is for Ada 2012. I expect the version for Ada 2022 will be 5.

The ACATS suite I maintain on Github is 4.1, currently release Y.

A comparison of test results on x86_64 and aarch64 follows.

x86_64

On gcc version 12.0.1 20220311:

        === acats Summary ===
# of expected passes        2537
# of unexpected failures    9
# of expected failures      1489
# of unresolved testcases   11
# of unsupported tests      124
*** FAILURES: c250002 c324006 c415001 cxd1003 cxd1004 cxd1005 cxd2006 cxd3001 cxd3002

Failures only in x86_64:

aarch64

On gcc version 12.0.1 20220312:

        === acats Summary ===
# of expected passes        2535
# of unexpected failures    11
# of expected failures      1489
# of unresolved testcases   11
# of unsupported tests      124
*** FAILURES: c324006 c415001 cb1010a cb1010d cxd1003 cxd1004 cxd1005 cxd2006 cxd3001 cxd3002 cxd8002

Failures only in aarch64:

Common failures: