What’s this blog about?

It’s holiday and I’m bored. Since embedded development is one of the things I’ve been learning in my free time (also the one with least progress), I thought I’d write a blog about cross compilers, which is very crucial in embedded development.

In this blog, I’ll be using gcc and the sample target compilation is Allwinner H3 SoC.


Introduction

Have you ever wondered how a code can be compiled to run on different devices? Well, we compile the code using different compilers. For example, if we want to compile a C code to run on an Intel machine, you use a compiler that compiles for x86 Instruction Set Architecture (ISA). If you want the same C code to run on newer MacBooks, you need to use a compiler that compiles for the ARM ISA.

When we want to compile a code for an ISA that is different from that of the machine we’re compiling on (e.g. compiling for armv7-A on an x86 machine), we’re using what’s called cross compiler.


Components of a cross compiler

What makes up a cross compiler? Well, if it’s a GNU toolchain, they are:

Components of cross compiler toolchain. Credits to Bootlin.

Components of cross compiler toolchain. Credits to Bootlin.


Compiler prefix

Usually, a cross compiler will have a prefix tuple to distinguish themselves from native compilers & other cross compilers targeted at different ISAs.

The tuple is a set of dash-separated words consisting of 3 or 4 components:

[architecture]-[vendor]-[OS]-[ABI]-gcc

Here, vendor is optional. So if the tuple only contains 3 components, then vendor is the one getting dropped.


Crosstool-NG

Crosstool-NG is a very useful tool that I use to build cross compilers. After installing it according to this manual, I then run ct-ng menuconfig to tell crosstool-ng what cross compiler I want.

While crosstool-ng can be customized further, for Allwinner H3 (the sample SoC we’re using in this blog), I did the following:

  1. Path: I specify the directory where I want the cross compiler installed.
  2. Architecture: I specify the architecture of the SoC, which is Allwinner H3, so ARM.
  3. Architecture level (CT_ARCH_ARCH): In our example, Allwinner H3 uses ARM Cortex A7 CPU, whose specific ISA is armv7-a. This is the equivalent of tuning a compiler using the --with-arch= flag.
  4. CPU type (CT_ARCH_TUNE): Set this to cortex-a7 since Allwinner H3 uses ARM Cortex A7 CPU. This is the equivalent of tuning a compiler using the -mcpu= flag.

And that’s it. I then run ct-ng build and wait for my cross compiler to be built. Lastly, I append /path/to/cross/compiler/bin to the PATH environment variable.


Conclusion

Although this blog is very simple, I hope that this gives an idea on what a cross compiler is and how to build one.


References