|
| 1 | +# Machine Learning Build Machine Setup for Linux aarch64 cross compiled |
| 2 | + |
| 3 | +You will need the following environment variables to be defined: |
| 4 | + |
| 5 | +- `JAVA_HOME` - Should point to the JDK you want to use to run Gradle. |
| 6 | +- `CPP_CROSS_COMPILE` - Should be set to "aarch64". |
| 7 | +- `CPP_SRC_HOME` - Only required if building the C++ code directly using `make`, as Gradle sets it automatically. |
| 8 | +- `PATH` - Must have `/usr/local/gcc75/bin` before `/usr/bin` and `/bin`. |
| 9 | +- `LD_LIBRARY_PATH` - Must have `/usr/local/gcc75/lib64` and `/usr/local/gcc75/lib` before `/usr/lib` and `/lib`. |
| 10 | + |
| 11 | +For example, you might create a .bashrc file in your home directory containing this: |
| 12 | + |
| 13 | +``` |
| 14 | +umask 0002 |
| 15 | +export JAVA_HOME=/usr/local/jdk1.8.0_121 |
| 16 | +export LD_LIBRARY_PATH=/usr/local/gcc75/lib64:/usr/local/gcc75/lib:/usr/lib:/lib |
| 17 | +export PATH=$JAVA_HOME/bin:/usr/local/gcc75/bin:/usr/bin:/bin:/usr/sbin:/sbin |
| 18 | +# Only required if building the C++ code directly using make - adjust depending on the location of your Git clone |
| 19 | +export CPP_SRC_HOME=$HOME/ml-cpp |
| 20 | +export CPP_CROSS_COMPILE=aarch64 |
| 21 | +``` |
| 22 | + |
| 23 | +### Initial Preparation |
| 24 | + |
| 25 | +Start by configuring a native Linux aarch64 build server as described in [linux.md](linux.md). |
| 26 | + |
| 27 | +The remainder of these instructions assume the native aarch64 build server you have configured is for CentOS 7. This is what builds for distribution are currently built on. |
| 28 | + |
| 29 | +On the fully configured native aarch64 build server, run the following commands: |
| 30 | + |
| 31 | +``` |
| 32 | +cd /usr |
| 33 | +tar jcvf ~/usr-aarch64-linux-gnu.tar.bz2 include lib lib64 local |
| 34 | +``` |
| 35 | + |
| 36 | +These instructions assume the host platform is also CentOS 7, but x86_64 instead of aarch64. It makes life much easier if the host distribution is the same as the target distribution. |
| 37 | + |
| 38 | +Transfer the archive created in your home directory on the native aarch64 build server, `usr-aarch64-linux-gnu.tar.bz2`, to your home directory on the x86_64 host build server. |
| 39 | + |
| 40 | +### OS Packages |
| 41 | + |
| 42 | +You need the C++ compiler and the headers for the `zlib` library that comes with the OS. You also need the archive utilities `unzip` and `bzip2`. On RHEL/CentOS these can be installed using: |
| 43 | + |
| 44 | +``` |
| 45 | +sudo yum install bzip2 gcc-c++ texinfo unzip zlib-devel |
| 46 | +``` |
| 47 | + |
| 48 | +### Transferred Build Dependencies |
| 49 | + |
| 50 | +Add the dependencies that you copied from the fully configured native aarch64 build server in the "Initial Preparation" step. |
| 51 | + |
| 52 | +``` |
| 53 | +sudo mkdir -p /usr/local/sysroot-aarch64-linux-gnu/usr |
| 54 | +cd /usr/local/sysroot-aarch64-linux-gnu/usr |
| 55 | +sudo tar jxvf ~/usr-aarch64-linux-gnu.tar.bz2 |
| 56 | +cd .. |
| 57 | +sudo ln -s usr/lib lib |
| 58 | +sudo ln -s usr/lib64 lib64 |
| 59 | +``` |
| 60 | + |
| 61 | +### General settings for building the tools |
| 62 | + |
| 63 | +Most of the tools are built via a GNU "configure" script. There are some environment variables that affect the behaviour of this. Therefore, when building ANY tool on Linux, set the following environment variables: |
| 64 | + |
| 65 | +``` |
| 66 | +export CFLAGS='-g -O3 -fstack-protector -D_FORTIFY_SOURCE=2' |
| 67 | +export CXXFLAGS='-g -O3 -fstack-protector -D_FORTIFY_SOURCE=2' |
| 68 | +export LDFLAGS='-Wl,-z,relro -Wl,-z,now' |
| 69 | +export LDFLAGS_FOR_TARGET='-Wl,-z,relro -Wl,-z,now' |
| 70 | +unset LIBRARY_PATH |
| 71 | +``` |
| 72 | + |
| 73 | +These environment variables only need to be set when building tools on Linux. They should NOT be set when compiling the Machine Learning source code (as this should pick up all settings from our Makefiles). |
| 74 | + |
| 75 | +### binutils (bootstrap version) |
| 76 | + |
| 77 | +Since we build with a more recent gcc than comes with the host system, we must build it from source. To build a cross compiler we need cross build tools, so we need to build versions that are compatible with the system compiler that we'll use to build the more recent gcc. |
| 78 | + |
| 79 | +Download `binutils-2.25.tar.bz2` from <http://ftpmirror.gnu.org/binutils/binutils-2.25.tar.bz2>. |
| 80 | + |
| 81 | +Uncompress and untar the resulting file. Then run: |
| 82 | + |
| 83 | +``` |
| 84 | +unset LD_LIBRARY_PATH |
| 85 | +export PATH=/usr/bin:/bin:/usr/sbin:/sbin |
| 86 | +./configure --with-sysroot=/usr/local/sysroot-aarch64-linux-gnu --target=aarch64-linux-gnu --with-system-zlib --disable-multilib --disable-libstdcxx |
| 87 | +``` |
| 88 | + |
| 89 | +This should build an appropriate Makefile. Assuming it does, type: |
| 90 | + |
| 91 | +``` |
| 92 | +make |
| 93 | +sudo make install |
| 94 | +``` |
| 95 | + |
| 96 | +to install. |
| 97 | + |
| 98 | +### gcc |
| 99 | + |
| 100 | +We have to build on old Linux versions to enable our software to run on the older versions of Linux that users have. However, this means the default compiler on our Linux build servers is also very old. To enable use of more modern C++ features, we use the default compiler to build a newer version of gcc and then use that to build all our other dependencies. |
| 101 | + |
| 102 | +Download `gcc-7.5.0.tar.gz` from <http://ftpmirror.gnu.org/gcc/gcc-7.5.0/gcc-7.5.0.tar.gz>. |
| 103 | + |
| 104 | +Unlike most automake-based tools, gcc must be built in a directory adjacent to the directory containing its source code, so build and install it like this: |
| 105 | + |
| 106 | +``` |
| 107 | +tar zxvf gcc-7.5.0.tar.gz |
| 108 | +cd gcc-7.5.0 |
| 109 | +contrib/download_prerequisites |
| 110 | +sed -i -e 's/$(SHLIB_LDFLAGS)/-Wl,-z,relro -Wl,-z,now $(SHLIB_LDFLAGS)/' libgcc/config/t-slibgcc |
| 111 | +cd .. |
| 112 | +mkdir gcc-7.5.0-build |
| 113 | +cd gcc-7.5.0-build |
| 114 | +unset LD_LIBRARY_PATH |
| 115 | +export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin |
| 116 | +../gcc-7.5.0/configure --prefix=/usr/local/gcc75 --with-sysroot=/usr/local/sysroot-aarch64-linux-gnu --target=aarch64-linux-gnu --enable-languages=c,c++ --enable-vtable-verify --with-system-zlib --disable-multilib |
| 117 | +make -j 6 |
| 118 | +sudo env PATH="$PATH" make install |
| 119 | +``` |
| 120 | + |
| 121 | +(Note the `env PATH="$PATH"` bit in the install command - this is because the cross tools we put in `/usr/local/bin` are needed during the install.) |
| 122 | + |
| 123 | +To confirm that everything works correctly run: |
| 124 | + |
| 125 | +``` |
| 126 | +aarch64-linux-gnu-g++ --version |
| 127 | +``` |
| 128 | + |
| 129 | +It should print: |
| 130 | + |
| 131 | +``` |
| 132 | +aarch64-linux-gnu-g++ (GCC) 7.5.0 |
| 133 | +``` |
| 134 | + |
| 135 | +in the first line of the output. If it doesn't then double check that `/usr/local/gcc75/bin` is near the beginning of your `PATH`. |
| 136 | + |
| 137 | +### binutils (final version) |
| 138 | + |
| 139 | +Also due to building on old Linux versions yet wanting to use modern libraries we have to install an up-to-date version of binutils. This will be used in preference to the bootstrap version by ensuring that `/usr/local/gcc75/bin` is at the beginning of `PATH`. |
| 140 | + |
| 141 | +Download `binutils-2.34.tar.bz2` from <http://ftpmirror.gnu.org/binutils/binutils-2.34.tar.bz2>. |
| 142 | + |
| 143 | +Uncompress and untar the resulting file. Then run: |
| 144 | + |
| 145 | +``` |
| 146 | +./configure --prefix=/usr/local/gcc75 --with-sysroot=/usr/local/sysroot-aarch64-linux-gnu --target=aarch64-linux-gnu --enable-vtable-verify --with-system-zlib --disable-multilib --disable-libstdcxx --with-gcc-major-version-only |
| 147 | +``` |
| 148 | + |
| 149 | +This should build an appropriate Makefile. Assuming it does, type: |
| 150 | + |
| 151 | +``` |
| 152 | +make |
| 153 | +sudo make install |
| 154 | +``` |
| 155 | + |
| 156 | +to install. |
| 157 | + |
| 158 | +### patchelf |
| 159 | + |
| 160 | +Obtain patchelf from <http://nixos.org/releases/patchelf/patchelf-0.9/> - the download file will be `patchelf-0.9.tar.bz2`. |
| 161 | + |
| 162 | +Extract it to a temporary directory using: |
| 163 | + |
| 164 | +``` |
| 165 | +bzip2 -cd patchelf-0.9.tar.bz2 | tar xvf - |
| 166 | +``` |
| 167 | + |
| 168 | +In the resulting `patchelf-0.9` directory, run the: |
| 169 | + |
| 170 | +``` |
| 171 | +./configure --prefix=/usr/local/gcc75 |
| 172 | +``` |
| 173 | + |
| 174 | +script. This should build an appropriate Makefile. Assuming it does, run: |
| 175 | + |
| 176 | +``` |
| 177 | +make |
| 178 | +sudo make install |
| 179 | +``` |
| 180 | + |
| 181 | +to complete the build. |
0 commit comments