DOC

cmake cross compiling

By Melanie Morales,2015-01-21 20:41
10 views 0
CMake Cross Compiling Cross compiling is supported by CMake starting with version 2.6.0. Cross compiling means that the software is built for a different system than the one which does the build. This means CMake cannot autodetect the target system usually the executables don't run on the build host the build process has to use a differen..

CMake Cross Compiling

    Cross compiling is supported by CMake starting with version 2.6.0.

    Cross compiling means that the software is built for a different system than the one which does the build. This means

    CMake cannot autodetect the target system

    usually the executables don't run on the build host

    the build process has to use a different set of include files and libraries for building, i.e. not the native ones

    Contents

    1 Setting up the system and toolchain

    2 Searching and finding external software

    3 The toolchain file

    4 System introspection

    5 Using executables in the build created during the build

    6 Information how to set up various cross compiling toolchains

    7 How to cross compile ParaView, Python

    8 FAQ/Potential Problems

Setting up the system and toolchain

    When cross compiling, CMake cannot guess the target system, so you have to preset some CMake variables, e.g. using a toolchain file. The following variables have to be preset:

CMAKE_SYSTEM_NAME

    this one is mandatory, it is the name of the target system, i.e. the same as CMAKE_SYSTEM_NAME would have if CMake would

    run on the target system. Typical examples are "Linux" and "Windows". This variable is used for constructing the file names of the platform files like Linux.cmake or Windows-gcc.cmake. If your target is an embedded system without OS set

    CMAKE_SYSTEM_NAME to "Generic". If

    CMAKE_SYSTEM_NAME is preset, the CMake variable

    CMAKE_CROSSCOMPILING is automatically set to TRUE, so

    this can be used for testing in the CMake files.

    CMAKE_SYSTEM_VERSION

    optional, version of your target system, not used very much.

    CMAKE_SYSTEM_PROCESSOR

    optional, processor (or hardware) of the target system. This variable is not used very much except for one purpose, it is used to load a CMAKE_SYSTEM_NAME-compiler-CMAKE_SYSTEM_PROCE

    SSOR.cmake file, which can be used to modify settings like compiler flags etc. for the target. You probably only have to set this one if you are using a cross compiler where every target hardware needs special build settings.

    Since CMake cannot guess the target system, it also cannot guess

which compiler it should use, so you have to preset this too:

    CMAKE_C_COMPILER

    the C compiler executable, may be the full path or just the filename. If it is specified with full path, then this path will be prefered when searching the C++ compiler and the other tools (binutils, linker, etc.). If this compiler is a gcc-cross compiler with a prefixed name (e.g. "arm-elf-gcc") CMake will detect this and automatically find the corresponding C++ compiler (i.e. "arm-elf-c++"). The compiler can also be preset via the CC environment variables.

    CMAKE_CXX_COMPILER

    the C++ compiler executable, may be the full path or just the filename. It is handled the same way as CMAKE_C_COMPILER. If the toolchain is a GNU toolchain, you only need to set one of both.

    Once the system and the compiler are determined by CMake, it loads the corresponding files in the following order:

    Platform/${CMAKE_SYSTEM_NAME}.cmake (mandatory)

    Platform/${CMAKE_SYSTEM_NAME}-<compiler>.cmake

    (optional)

    Platform/${CMAKE_SYSTEM_NAME}-<compiler>-${CMAKE_

    SYSTEM_PROCESSOR}.cmake (optional)

    <compiler> is either the basename of the compiler executable, e.g. "gcc" (this is also used if gcc has a different name) or "cl", or by a

compiler id, which is detected by compiling a test source file.

    For testing the host system, there is a corresponding set of variables, which is set automatically by CMake:

    CMAKE_HOST_SYSTEM_NAME

    CMAKE_HOST_SYSTEM_VERSION

    CMAKE_HOST_SYSTEM_PROCESSOR

    CMAKE_HOST_SYSTEM

    Without cross compiling the variables for the host system and the target system are identical. In most cases you will want to test for the target system, then the same way as without cross compiling use the CMAKE_SYSTEM_xxx variables, this will work both for cross compiling and for native building.

    With these variables correctly set, CMake will now use the cross compiling toolchain for building and in the CMakeLists.txt you can still use the CMAKE_SYSTEM_XXX variables for testing for which system you are building. This is already enough to use CMake for cross compiling simple (buildsystem-wise) projects.

    Searching and finding external software

    Most non-trivial projects will depend on external libraries or tools. CMake offers the FIND_PROGRAM(), FIND_LIBRARY(),

    FIND_FILE(), FIND_PATH() and FIND_PACKAGE() commands

    for this purpose. They search the file system in common places for

    files and return the results. FIND_PACKAGE() is a bit different in that it actually doesn't search itself, but "only" executes FindXXX.cmake modules, which usually call the

    FIND_PROGRAM(), FIND_LIBRARY(), FIND_FILE() and

    FIND_PATH() commands then.

    When cross compiling e.g. for a target with an ARM processor getting /usr/lib/libjpeg.so as the result of a FIND_PACKAGE(JPEG) wouldn't be much of a help, since this would be the JPEG library for the host system, e.g. an x86 Linux box. So you need to tell CMake to search in other locations. This can be done by setting the following variables:

    CMAKE_FIND_ROOT_PATH

    this is a list of directories, each of the directories listed there will be prepended to each of the search directories of every FIND_XXX() command. So e.g. if your target environment is installed under /opt/eldk/ppc_74xx, set CMAKE_FIND_ROOT_PATH to this

    directory. Then e.g. FIND_LIBRARY(BZ2_LIB bz2) will search in /opt/eldk/ppc_74xx/lib, /opt/eldk/ppc_74xx/usr/lib, /lib, /usr/lib and so give /opt/eldk/ppc_74xx/usr/lib/libbz2.so as result. By default CMAKE_FIND_ROOT_PATH is empty. If set, at first the

    directories prefixed with the directories given in

    CMAKE_FIND_ROOT_PATH will be searched and after that the

    unprefixed versions of the search directories will be searched. This behaviour can be modified individually for every FIND_XXX() call with the NO_CMAKE_FIND_ROOT_PATH,

    ONLY_CMAKE_FIND_ROOT_PATH and

    CMAKE_FIND_ROOT_PATH_BOTH options or the default for all FIND_XXX() commands can be adjusted with the

    CMAKE_FIND_ROOT_PATH_MODE_PROGRAM,

    CMAKE_FIND_ROOT_PATH_MODE_LIBRARY and

    CMAKE_FIND_ROOT_PATH_MODE_INCLUDE variables. If you

    don't want to use only libraries that come with the toolchain but also build and use additional libraries for your target platform, you should create an install directory for these packages, e.g. $HOME/eldk-ppc_74xx-inst/ and add this to

    CMAKE_FIND_ROOT_PATH, so the FIND_XXX() commands

    will search there too. If you then build packages for your target platform, they should be installed into this directory.

    CMAKE_FIND_ROOT_PATH_MODE_PROGRAM

    This sets the default behaviour for the FIND_PROGRAM() command. It can be set to NEVER, ONLY or BOTH (default). If set to NEVER, CMAKE_FIND_ROOT_PATH will not be used for

    FIND_PROGRAM() calls (except where it is enabled explicitely). If set to ONLY, only the search directories with the prefixes coming

from CMAKE_FIND_ROOT_PATH will be used in

    FIND_PROGRAM(). The default is BOTH, which means that at first the prefixed directories and after that the unprefixed directories will be searched. In most cases FIND_PROGRAM() is used to search for an executable which will then be executed e.g. using EXECUTE_PROCESS() or ADD_CUSTOM_COMMAND(). So in

    most cases an executable from the build host is required, so usually set CMAKE_FIND_ROOT_PATH_MODE_PROGRAM to

    NEVER.

    CMAKE_FIND_ROOT_PATH_MODE_LIBRARY

    This is the same as above, but for the FIND_LIBRARY() command. In most cases this is used to find a library which will then be used for linking, so a library for the target is required. So in the common case, set it to ONLY.

    CMAKE_FIND_ROOT_PATH_MODE_INCLUDE

    This is the same as above and used for both FIND_PATH() and FIND_FILE(). In many cases this is used for finding include directories, so the target environment should be searched. So in the common case, set it to ONLY. You may have to adjust this behaviour for some of the FIND_PATH() or FIND_FILE() calls using the NO_CMAKE_FIND_ROOT_PATH,

    ONLY_CMAKE_FIND_ROOT_PATH and

CMAKE_FIND_ROOT_PATH_BOTH options.

    The toolchain file

    Defining all the variables mentioned above using -DCMAKE_SYSTEM_NAME etc. would be quite tedious and error prone. To make things easier, there is another cmake variable you can set:

    CMAKE_TOOLCHAIN_FILE

    absolute or relative path to a cmake script which sets up all the toolchain related variables mentioned above

    For instance for crosscompiling from Linux to Embedded Linux on PowerPC this file could look like this:

    # this one is important

    SET(CMAKE_SYSTEM_NAME Linux)

    #this one not so much

    SET(CMAKE_SYSTEM_VERSION 1)

# specify the cross compiler

    SET(CMAKE_C_COMPILER

    /opt/eldk-2007-01-19/usr/bin/ppc_74xx-gcc)

    SET(CMAKE_CXX_COMPILER

    /opt/eldk-2007-01-19/usr/bin/ppc_74xx-g++)

# where is the target environment

    SET(CMAKE_FIND_ROOT_PATH

    /opt/eldk-2007-01-19/ppc_74xx /home/alex/eldk-ppc74xx-inst)

# search for programs in the build host directories

    SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

    # for libraries and headers in the target directories

    SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)

    SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

    If this file is named Toolchain-eldk-ppc74xx.cmake and is located in your home directory and you are building in the subdirectory build then you can do:

    ~/src$ cd build

    ~/src/build$ cmake

    -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-eldk-ppc74xx.cmake

     ..

    ...

    You don't have to write a toolchain file for every piece of software you want to build, the toolchain files are per target platform, i.e. if you are building several software packages all for the same target

    platform, you have to write only one toolchain file and you can use this for all packages.

    If your compiler is not able to build a simple program by default without special flags or files (e.g. linker scripts or memory layout files), the toolchain file as shown above doesn't work. Then you have to force the compiler:

    INCLUDE(CMakeForceCompiler)

# this one is important

    SET(CMAKE_SYSTEM_NAME eCos)

# specify the cross compiler

    CMAKE_FORCE_C_COMPILER(arm-elf-gcc GNU)

    CMAKE_FORCE_CXX_COMPILER(arm-elf-g++ GNU)

# where is the target environment

    SET(CMAKE_FIND_ROOT_PATH /home/alex/src/ecos/install )

# search for programs in the build host directories

    SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

    # for libraries and headers in the target directories

    SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)

Report this document

For any questions or suggestions please email
cust-service@docsford.com