multiarch / crossbuild

:earth_africa: multiarch cross compiling environments

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for Apple M1 arm64/aarch64 chips

Willena opened this issue · comments

I've been using this docker container to cross-compile some libraries for Mac OS for quite a long time. It works great !
After a quick look to the content of the container, it seems that it contains some of the things needed to build for aarch64 / Apple M1 processor.
Adding a new CROSS_TRIPLE case and setting -arch arm64 with an arm64 compatible GCC could do the work.

I don't know how difficult it would be to implement this new processor. Correct me if I'm wrong.

cc @moul @junaruga @aimxhaisse @lafin @QuentinPerez

Hello! Has there been any progress on this?

Sorry I do not know any progress.

@Willena Could you try to open a pull request?

I suspect that currently only clang compiles to Apple Silicon, requiring Xcode 12.2 on Mac.

gcc has a suspended ticket for its support, but there is a work-in-progress implementation here.

The upstream crossbuild project has added code for M1 ARM (64) support.

tpoechtrager/osxcross@261de10

The only issue is that to target arm64e ( M1 chips if I'm correct ) we still need to build the llvm-compiler from scratch (not very difficult, but requires a lot of computing resources and it is a quite long process).
I'm not very familiar with arm architecture, but if arm64 is compatible with arm64e then this becomes much easier.

Confirmed, building the Apple Clang compiler is able to generate arm64[e] toolchains for osxcross. This is documented in the osxcross README.

https://github.com/tpoechtrager/osxcross#what-is-the-goal-of-osxcross

Example compilation of Apple Clang on Ubuntu:

https://github.com/mcandre/apple-clang/blob/master/Dockerfile

My use case was to build a universal2 binary on x86_64. I was able to get it working by doing the following:

I can make a PR if you want, but I don't know where that original SDK came from (dropbox?). Perhaps we can add a copy step to the Dockerfile. Also it may become necessary to do more creative tagging as mentioned in #48 as to support more diverse sets of build environments:

  • stretch-catalina
  • stretch-bigsur, stretch
  • stretch-monterrey, stretch this is not a supported combination for reasons mentioned above
  • bullseye-catalina, catalina
  • bullseye-bigsur, bigsur
  • bullseye-monterrey, monterrey, bullseye, latest

@yuzawa-san I believe the newer cmake can typically be installed via python, eg. apt-get install -y python3-pip; python3 -m pip install cmake which may remove the need to upgrade distribution for this?

I'm trying to make this work without cmake, as our current build chain uses make, i need to pass the path to the cross-compiler (i suppose clang from what i read above).

Anyone managed to do that ?

I can compile our library, and it seems to be recognized as arm64, but when i try to use it the process crash without much information. I'm probably doing something wrong.

Turns out it was a signature problem, as M1 macs always check the signature. You need at least the adhoc signature for a binary to run.

@gotson that all sounds quite promising, nice job figuring out the couple of extra steps!

So are you able to build a binary using a docker built from your fork/commit referenced above?

That ad-hoc signing, can that be done with the tools in the docker too?

@andrewleech yes so far it works, i still need to do a couple of checks to make sure everything is fine before merging this to the master branch.

We are building a dynamic library for multiple platforms, and after some digging i found out a few things:

  • when building on a M1 mac with gcc -arch arm64 or clang, there is an adhoc signature. If you strip the binary, the signature is still there (probably some Apple magic).
  • when building using crossbuild with clang, the adhoc signature is also there. However, when you strip there is a warning /usr/osxcross/bin/aarch64-apple-darwin20.4-strip: warning: changes being made to the file will invalidate the code signature in: /tmp/libsqlitejdbc.jnilib, and the signature is removed.
  • when you run a binary that is not signed (adhoc signature is fine) on a M1 mac, Gatekeeper will send a SIGKILL straight away.
  • On a Mac you can use the codesign binary to verify a signature: codesign --verify libsqlitejdbc.jnilib
  • You can also use it to add an adhoc signature: codesign --sign - libsqlitejdbc.jnilib

While checking the issues for M1 mac in the osxcross repo, i stumbled upon this: tpoechtrager/osxcross#355 (comment)

Given codesign is not available on Linux, i created my own Docker image with rcodesign (source). That way i can sign Mac binaries from Docker.

I use a fork of crossbuild following the super helpful comments of @yuzawa-san above.

It seems another tool (sigtool) could be automatically called by osxcross, but i didn't manage to get that working.

Thanks for those details! I can see from the osxcross issues some more details about sigtool:

Currently only supports embedded ad-hoc signatures for universal and thin 64-bit Mach-O files.

I'm guessing I could also just skip strip for a basic open-source executable :-D

I'm guessing I could also just skip strip for a basic open-source executable :-D

Not an option for us, we ship the library in the jar, and every kb counts! Stripping saves around 100-200kb.

Note that rcodesign doesn't have those limitations from what i checked, so you could even use it to sign with your AppleID, and it can also notarize your app.

any update on this?