CmakeGccm32
How to use gcc-multilib to cross compile software for Linux
Goal: compile a 32bits exe on running amd64 linux system.
Install the gcc-multilib package
$ sudo apt-get install gcc-multilib
Write a CMake toolchain file
For CMake to be able to crosscompile software, it requires you to write a toolchain file, which tells CMake some information about the toolchain. With the examples used above it will look like:
# the name of the target operating system SET(CMAKE_SYSTEM_NAME Linux) # which compilers to use for C and C++ SET(CMAKE_C_COMPILER gcc) SET(CMAKE_C_FLAGS -m32) SET(CMAKE_CXX_COMPILER g++) SET(CMAKE_CXX_FLAGS -m32) # here is the target environment located SET(CMAKE_FIND_ROOT_PATH /usr/i486-linux-gnu ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Save this file as Toolchain-gcc-m32.cmake to some location where you will put all your toolchain files, e.g. $HOME. As you can see CMAKE_FIND_ROOT_PATH is set to /usr/i486-linux-gnu, which contains the libraries and headers installed with the toolchain.
Build the software for Linux
Let's say you have the classical hello world software with a CMake based buildsystem and want to build this for Linux using gcc -m32. main.c:
#include <stdio.h> int main() { printf("Hello world\n"); return 0; }
CMakeLists.txt:
ADD_EXECUTABLE(hello main.c)
Then run CMake on it to generate the buildfiles, the important point is that you tell it to use the toolchain file you just wrote:
~/src/helloworld/ $ mkdir build ~/src/helloworld/ $ cd build ~/src/helloworld/build/ $ cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-gcc-m32.cmake -DCMAKE_INSTALL_PREFIX=/home/mathieu/gcc-m32-install .. -- Configuring done -- Generating done -- Build files have been written to: /home/mathieu/src/helloworld/build ~/src/helloworld/build/ $ make Scanning dependencies of target hello [100%] Building C object CMakeFiles/hello.dir/main.o Linking C executable hello [100%] Built target hello
You can then verify:
$ file hello hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, not stripped
In case you have a more complex application that is using let say zlib, you would need first to install it:
$ apt-cross --arch i386 -i zlib1g-dev
And after compilation, you can check that you are indeed using this zlib and not your system one:
$ ldd ./myapp ... libz.so.1 => /usr/i486-linux-gnu/lib/libz.so.1 (0xf7b6b000) ...