From 63443d642dff00c7eb4c3f3826878d3547827616 Mon Sep 17 00:00:00 2001
From: Daniel Garcia-Sanchez
- It is possible to use CMake to cross compile
- deal.II for a foreign platform.
- Further information on that topic can be found at the CMake
- wiki.
+ It is possible to use the
+ CMake toolchain
+ to cross compile deal.II for a platform other than the one on which the
+ compiler is running. The target platform can have a different operating
+ system, different architecture or different set of libraries. Cross
+ compilation is a very useful technique, for instance it can be used to
+ compile deal.II with a compiler that is not available in the target
+ machine. An alternative technique is to use a
+ Docker container or a
+ virtual machine
+ that mimics the target machine.
- You have to set up a native deal.II build directory first and run
- Cross compiling
make expand_instantiations_exe
in it. The executable is
- needed for the build system (and obviously the cross compiled version
- cannot be used). Locate the expand_instantiations
- executable (it usually resides under
- ${CMAKE_BINARY_DIR}/bin
and export its location with the
- PATH
environment variable.
+ You can use any compiler for cross compilation, although
+ LLVM/clang might be more versatile
+ because it supports multiple architecture targets in a single
+ executable natively (see
+ Cross-compilation using Clang).
+ Below you can find an example toolchain file for cross compilation with
+ clang (and another example for
+ Windows64 using MinGW).
+
+set(target_root /path/to/sysroot)
+set(dealii_dir ${target_root}/path/to/lib/dealii)
+
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR x86_64)
+
+set(CMAKE_SYSROOT ${target_root})
+
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_CXX_COMPILER clang++)
+
+set(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN ${target_root}/path/to/gcc/toolchain)
+set(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN ${target_root}/path/to/gcc/toolchain)
+
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+
+ If you use LLVM/clang you can use the gcc toolchain of the
+ target with the option CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN
,
+ this is equivalent to the clang option
+ --gcc-toolchain.
+ You should place all the relevant libraries of the target in
+ $target_root
. ldd
is a great tool figure out the
+ libraries that you need. You can use the C libraries of the target such as
+ Blas, HDF5 and MPI. On the other hand C++ libraries can be problematic
+ because different C++ compilers (or even different versions of the same
+ compiler, or the same compiler on different platforms) mangle public
+ symbols in radically different ways. For this reason C++ libraries such
+ as Trilinos should be cross compiled by the same compiler as deal.II.
- Assuming you have a working cross compilation toolchain, the next
- step is to set up a
- toolchain file
- (or for for
- Windows64 using MinGW).
- After that invoke cmake
with something like:
+ If the host and the target have a different architecture, you have to set
+ up a native deal.II build directory first and run
+ make expand_instantiations_exe
in it. The executable is
+ needed for the build system (the cross compiled version cannot be used if
+ the architecture of the target and the host are not the same). Locate the
+ expand_instantiations
executable (it usually resides under
+ ${CMAKE_BINARY_DIR}/bin
) and export its location with the
+ PATH
environment variable. Below you can find a minimal cmake
+ script for the configuration of deal.II.
-$ cmake -DCMAKE_TOOLCHAIN_FILE=<...>/Toolchain.sample \ +mkdir $dealii_build +cd $dealii_build +export LD_LIBRARY_PATH=$target_root/lib/directories +cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \ -DDEAL_II_FORCE_BUNDLED_BOOST=ON \ -DDEAL_II_ALLOW_AUTODETECTION=OFF \ - ../deal.II + -DDEAL_II_WITH_MPI=ON \ + -DMPI_CXX_INCLUDE_PATH:STRING=$target_root'/path/to/mpi/include' \ + -DMPI_CXX_LIBRARIES:STRING=$target_root'/path/to/mpi/lib/libmpi_1.so;'$target_root'/path/to/mpi/lib/libmpi_2.so' \ + -DDEAL_II_WITH_TRILINOS=ON \ + -DTRILINOS_DIR=$target_root/path/to/trilinos \ + -DDEAL_II_WITH_P4EST=ON \ + -DP4EST_DIR=$target_root/path/to/p4est \ + -DCMAKE_INSTALL_PREFIX=$target_root/path/to/dealii \ + /path/to/dealii/repository +make expand_instantiations_exe +export PATH=$dealii_build/bin/:$PATH +make -jN install- where
CMAKE_TOOLCHAIN_FILE
points to the toolchain file.
- The remaining configuration can be adjusted at will, see the documentation.
+ If the target uses LD_LIBRARY_PATH
to set up some libraries,
+ you may need to export LD_PRELOAD_PATH
with those libraries
+ before you call CMake. Note that CMake might not be able to guess the MPI
+ configuration, therefore you may have to give all the MPI flags to CMake.
+ There are two ways to obtain the MPI flags, you can compile another
+ program at the target and then inspect CMakeCache.txt
+ or you can obtain the flags using mpic++ --showme:compile
and
+ mpic++ --showme:link
. The remaining configuration can be
+ adjusted at will, see the documentation. Note
+ that the rpaths of the
+ examples might not be correct, this can be fixed using
+ LD_LIBRARY_PATH
or chrpath
.