|
|
(4 intermediate revisions by 2 users not shown) |
Line 1: |
Line 1: |
| = How to use gcc-multilib to cross compile software for Linux =
| | {{CMake/Template/Moved}} |
|
| |
|
| Goal: compile a 32bits exe on running amd64 linux system.
| | This page has moved [https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/cross_compiling/Gccm32 here]. |
| | |
| == 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:
| |
| <pre>
| |
| # 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)
| |
| </pre>
| |
| | |
| 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:
| |
| <pre>
| |
| #include <stdio.h>
| |
| | |
| int main()
| |
| {
| |
| printf("Hello world\n");
| |
| return 0;
| |
| }
| |
| </pre>
| |
| | |
| CMakeLists.txt:
| |
| <pre>
| |
| ADD_EXECUTABLE(hello main.c)
| |
| </pre>
| |
| | |
| 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:
| |
| <pre>
| |
| ~/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
| |
| </pre>
| |
| | |
| 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)
| |
| ...
| |