Native compiler vs cross compiler

Cross compiling refers to the process of compiling applications to run on a different computer system than the one where the compilation takes place. This contrasts with native compiling, where the compiled application is intended to run on the same system on which it was compiled.

The computer on which compilation takes place is called the host, and the computer where the software is being executed is called the target.

If you run a native compiler on the host, it generates the hello binary, which is intended to run on that host:

gcc hello.c -o hello

A cross compiler also runs on the host, but the binaries it generates are built for a different OS or CPU.

The QNX cross compiler is available for Linux and Windows hosts and generates binaries for the QNX OS running on x86 and ARM CPUs. It comes with the qcc and q++ frontends, and cross compiling a hello.c application for x86_64 architecture can be as simple as native compilation:

qcc hello.c -o hello

The qcc command expects the target architecture (CPU) to be specified with the -V option. You should explicitly call qcc with the -V option, even though x86_64 is the default:

qcc -Vgcc_ntox86_64 hello.c -o hello

C code typically includes system header files and requires linking to libraries (at least the standard C library).

However, when cross compiling, it shouldn't include host-specific headers or link with host libraries Instead, it should use headers and libraries provided for the target system.

Cross compilers usually rely on a so-called sysroot; a directory that contains the necessary files and libraries for the target system (the system on which the compiled code will eventually run).

An equivalent of the sysroot in the QNX SDP is the target folder. Before running qcc or q++, run the following command to set up the environment:

source ~/qnx800/qnxsdp-env.sh

This command sets several environment variables, including QNX_TARGET.

Since qcc is inherently a cross compiler, you don't have to explicitly set the sysroot or provide paths to system files using the -I or -L compiler and linker options.

After compiling a project with a native compiler, the binaries are typically installed in system directories, such as /usr/local/bin on the host. This is problematic when cross compiling. Instead, you want to install the binaries in the sysroot or a staging area.

A staging area is simply a directory that you can use instead of the sysroot to avoid cluttering it with headers and libraries from user projects. The staging area serves a similar purpose to the sysroot, as the compiler can search it for headers from previously cross-compiled projects when there are dependencies.

One advantage of using a staging area is that it consolidates all the generated files, making it easier to copy them to the target system. This is particularly useful for executing automated tests. In natively built projects, automated tests are often optional and executed on the host. For cross compiled projects, however, running automated tests on the host might not be sufficient (even for simple unit tests). It's recommended to cross-compile the tests as well and run them on the target system to ensure they pass in the target environment.

Some build system have built-in cross compilation support, for example:

Please note that projects using Autotools, Meson, and other tools have different interpretations of the terms host and target, and they introduce a new term, build:

  • build: The system where the software is being compiled.

  • host: The system where the software will run after being compiled.

  • target: In the context of building a cross-compiler, the platform for which it generates binaries.

Page updated: