CodeLobe.com/dev/hello-cross-compiler-world


Hello Cross Compiler World

This project demonstrates cross compilation to build a simple console application to run on Linux or Windows (or Wine).

A cross compiler is a compiler that generates binaries for a platform other than the host OS / dev machine. We'll use GCC and MinGW to provide ready made compilers for 32bit and 64bit Windows and Linux. For more complex projects a custom built cross complier may be preferable.

Below is the "Hello World" example program we'll be compiling for Windows and Linux.

 #include <stdio.h>

/// Echo greeting and parameter list to standard output.
int main( int argc, char ** args )
{   puts( "Hello cross complier world!" );
    int param = 0;
    for ( ; param < argc; ++param )
    {   printf( "Parameter #%i = [%s]\n", param, args[ param ] );
    }
    return 0;
}

Clone CodeLobe's example Git repository from GitLab

This project is located in the hello-xcomp-world directory. The example repo includes a Vagrantfile to initialize a VM, and a makefile to build a binary for each platform.

git clone git@gitlab.com:lobe-coders/lobe-lab.git
cd lobe-lab/hello-xcomp-world
vagrant up
vagrant ssh
cd /vagrant
make all

See this project's README for more information.

Using a VM to host Cross Compilation

Building upon the prior Vagrant Introduction, this project also demonstrates using a Vagrant virtual machine to create the development environment and install dependencies. Additionally, using a VM allows for ease of reproducing an exact binary, which may be of interest for validation of security conscious applications.

For our VM platform (Ubuntu) and Debian based Linux distros the packages required are build-essential, g++-multilib and mingw-w64. The following lines are thus present in the project's Vagrantfile to perform provisioning.

apt-get update
apt-get install -y build-essential g++-multilib mingw-w64

Note g++-multilib supports compilation of both C++ and C, and mingw-w64 also supports 32bit binaries.

Targeting Foreign Platforms

Within the development VM the platform is 64bit "native". In order to build 32bit binaries we can issue the GCC machine architecture option -m32. Likewise, the -m64 option can be used to compile a 64bit binary on a native 32bit platform.

gcc -m32 hello-world.c
gcc -m64 hello-world.c

Rather than GCC, MinGW is used to compile Windows executables, 32bit and 64bit respectively:

i686-w64-mingw32-gcc hello-world.c
x86_64-w64-mingw32-gcc hello-world.c

The compiler option -mtune=i686 may be used to tune the compiler to 32bit binary optimizations. For 64bit platforms the generic option -mtune=generic is used to ensure the binary is not tailored for a specific chipset. See the Makefile of this project for more details.

To list the available build targets enter make with no parameters or use:

make usage

Running Foreign Binaries

The Linux executables may be ran from within the Vagrant VM, or externally if your machine is running GNU/Linux. End the Vagrant SSH session via the exit command.

./hello-world-lin32 a b c
Hello cross complier world!
Parameter #0 = [./hello-world-lin32]
Parameter #1 = [a]
Parameter #2 = [b]
Parameter #3 = [c]

./hello-world-lin64 1 2 3
Hello cross complier world!
Parameter #0 = [./hello-world-lin64]
Parameter #1 = [1]
Parameter #2 = [2]
Parameter #3 = [3]

exit

Of course, the Windows binaries can be executed natively on Windows. To run the Windows binaries on a GNU/Linux OS install Wine.

apt install wine

Then use the wine command to run the programs.

wine hello-world-w32.exe a b c
Hello cross complier world!
Parameter #0 = [Z:\lobe-lab\hello-xcomp-world\hello-world-win32.exe]
Parameter #1 = [a]
Parameter #2 = [b]
Parameter #3 = [c]

Alternatively, use Wine's Windows console emulator.

wineconsole cmd

Microsoft Windows 5.2.3790 (1.8.7)

Z:\lobe-lab\hello-xcomp-world>hello-world-win64 "Hi!"
Hello cross complier world!
Parameter #0 = [hello-world-win64]
Parameter #1 = [Hi!]

It's interesting how Parameter #0 strings differ on various platforms.

You can also install Wine to the development VM by uncommenting a line in the Vagrantfile, but it's usually best to run wine from the native machine. It is possible, however ridiculous, to run a Windows terminal emulator in a GNU/Linux VM, on top of a native MS Windows platform...

Having completed this project you'll be able to build and run Windows and Linux executables on either Windows or Linux.