Building an LLVM cross-compiler

Yes, for such a full from-scratch setup, the procedure is a bit fiddly to get right, and exactly how to do it is very dependent on how configurable the lower level components of your target platform are for such bootstrap setups.

I regularly build my toolchain that targets mingw, in exactly this way. First I build the compiler, then I install the target "libc"'s headers, then build the mingw equivalent of the libc.

Here, the "libc" consists of import libraries (that are generated from symbol listings using llvm-dlltool) and static libraries, so libclang_rt isn't needed yet. (The autoconf scripts for these bits define AC_NO_EXECUTABLES, which avoids bailing out due to the compiler not being able to link an executable.)

After this step, I build the compiler-rt builtins, and this is configured with -DCMAKE_C_COMPILER_WORKS=1 to (iirc) make it not bail out even though the toolchain still can't link anything. After building the compiler-rt builtins, and installing them, the toolchain finally is complete enough to link a working C program.

After this stage, higher level runtimes like libc++ can be built on top, followed by other compiler-rt libraries.

See https://github.com/mstorsjo/llvm-mingw for the full set of scripts I use to build my setup; built-all.sh is the toplevel script you can start following if you want to dig in.

// Martin

Hello Martin,

Martin Storsjö wrote:

1. Get the sources (llvm, lld, compiler-rt, libunwind, libcxx...).
2. Build an LLVM cross-compiler toolchain using native distribution's
compiler (i.e. build an x86_64 clang executable that targets aarch64).
3. Cross-compile libc and other libraries/dependencies to run the
userland.
4. Cross-compile the userland.

Yes, for such a full from-scratch setup, the procedure is a bit fiddly
to get right, and exactly how to do it is very dependent on how
configurable the lower level components of your target platform are
for such bootstrap setups.

I regularly build my toolchain that targets mingw, in exactly this way.
First I build the compiler, then I install the target "libc"'s headers,
then build the mingw equivalent of the libc.
After this stage, higher level runtimes like libc++ can be built on top,
followed by other compiler-rt libraries.
See https://github.com/mstorsjo/llvm-mingw for the full set of scripts I
use to build my setup; built-all.sh is the toplevel script you can star
following if you want to dig in.

I like this. I hope you don't mind if I borrow some of these ideas to
play with. C_COMPILER_WORKS is something I've never heard of.

Thank you!

Hi everyone,

Just a quick update. Here's what worked for me here*:
1. Get the sources.
2. Build clang, llvm, lld.
3. Install libc headers to a sysroot.
4. Build compiler-rt builtins and crt with the freshly-built clang.
One need to set C_COMPILER_WORKS to skip the checks.
5. Build libc.a/libc.so

Now the freshly-built clang can compile a "Hello, World" program.

@Martin Storsjö
@Chris Bieneman
Thanks for the hints!

* - instead of previously supposed
  1. Get the sources (llvm, lld, compiler-rt, libunwind, libcxx...).
  2. Build an LLVM cross-compiler toolchain using native distribution's
  compiler (i.e. build an x86_64 clang executable that targets aarch64).
  3. Cross-compile libc and other libraries/dependencies to run the
  userland.
  4. Cross-compile the userland.

Hello!

From: llvm-dev <llvm-dev-bounces@lists.llvm.org> On Behalf Of Cág via
llvm-dev
Sent: Tuesday, November 10, 2020 8:49 AM
To: llvm-dev@lists.llvm.org
Subject: Re: [llvm-dev] Building an LLVM cross-compiler

Hi everyone,

Just a quick update. Here's what worked for me here*:
1. Get the sources.
2. Build clang, llvm, lld.
3. Install libc headers to a sysroot.
4. Build compiler-rt builtins and crt with the freshly-built clang.
One need to set C_COMPILER_WORKS to skip the checks.
5. Build libc.a/libc.so

Now the freshly-built clang can compile a "Hello, World" program.

Can this recipe be documented somewhere in the building-llvm pages?
It's clearly not an obvious procedure.
Thanks,
--paulr