5f4cace5e198090bc19ab3a0ac892c453d4cb623
[kernel-tools.git] / setup-toolchain.sh
1 #!/bin/bash
2 set -euo pipefail
3 set -x
4
5 # SPDX-FileCopyrightText: 2022 Jason Self <j@jxself.org>
6 # SPDX-License-Identifier: AGPL-3.0-or-later
7 #
8 # This program is used to set up compilers to use for building GNU
9 # Linux-libre.
10 #
11 # You will need a GNU/Linux system with a working compiler; GCC is
12 # assumed.
13 #
14 # You'll also need Autoconf, including Autoconf Archive, Bison,
15 # Flex, GnuPG, Gzip, Libtool, Lzip, Make, Tar, Texinfo, Wget, and
16 # XZ Utils.
17 #
18 # On Trisquel you can install these with:
19 #
20 #       apt install autoconf autoconf-archive bison flex g++ gcc gnupg
21 #       gcc-multilib gzip libtool lzip make tar texinfo wget xz-utils
22 #
23 # Note that the GNU C Library is not built so these compilers are only
24 # functional for kernel builds; they cannot be used to build userspace
25 # code.
26
27 # These are the architectures that compilers will be built for.
28 # Adjust as needed. Changes may also need to be made further down to
29 # account for architectures-specific differences.
30 architectures=(
31   aarch64-linux
32   arm-linux-gnueabihf
33   i386-linux
34   m68k-linux
35   mipsel-linux
36   or1k-linux
37   powerpc-linux
38   powerpc64-linux
39   powerpc64le-linux
40   riscv64-linux
41   s390x-linux
42   sparc64-linux
43   x86_64-linux
44 )
45
46 setup_keyring () {
47   # We'll be downloading the source code for various programs and
48   # will need to use GPG to verify that things haven't been tampered
49   # with. While it could be possible to download the gnu-keyring.gpg
50   # file, downloading the keys from the same place that you're
51   # getting the source code from could open up problems if both are
52   # replaced with malicious versions. For this reason the expected
53   # keys are stored independently here, in the 'keys' directory and
54   # used for verification. Each file is named with the key
55   # fingerprint. They're stored in ASCII-armored format.
56   if [ ! -f "gnu-keyring.gpg" ]; then
57     for keyfile in keys/*.asc
58     do
59       gpg --no-default-keyring --keyring ./gnu-keyring.gpg --import $keyfile
60     done
61   fi
62 }
63
64 setup_keyring
65
66 download_source () {
67   # This handles the actual downloading the of the source code from
68   # the GNU FTP mirrors along with invoking GPG for verification.
69   if [ ! -f "binutils-$binutils_version.tar.lz" ]; then
70     wget http://ftpmirror.gnu.org/gnu/binutils/binutils-$binutils_version.tar.lz
71     wget http://ftpmirror.gnu.org/gnu/binutils/binutils-$binutils_version.tar.lz.sig
72     gpg --no-default-keyring --keyring ./gnu-keyring.gpg --verify binutils-$binutils_version.tar.lz.sig
73   fi
74   if [ ! -f "gcc-$gcc_version.tar.xz" ]; then
75     wget http://ftpmirror.gnu.org/gnu/gcc/gcc-$gcc_version/gcc-$gcc_version.tar.xz
76     wget http://ftpmirror.gnu.org/gnu/gcc/gcc-$gcc_version/gcc-$gcc_version.tar.xz.sig
77     gpg --no-default-keyring --keyring ./gnu-keyring.gpg --verify gcc-$gcc_version.tar.xz.sig
78   fi
79   if [ ! -f "gmp-$gmp_version.tar.lz" ]; then
80     wget http://ftpmirror.gnu.org/gnu/gmp/gmp-$gmp_version.tar.lz
81     wget http://ftpmirror.gnu.org/gnu/gmp/gmp-$gmp_version.tar.lz.sig
82     gpg --no-default-keyring --keyring ./gnu-keyring.gpg --verify gmp-$gmp_version.tar.lz.sig
83   fi
84   if [ ! -f "mpc-$mpc_version.tar.gz" ]; then
85     wget http://ftpmirror.gnu.org/gnu/mpc/mpc-$mpc_version.tar.gz
86     wget http://ftpmirror.gnu.org/gnu/mpc/mpc-$mpc_version.tar.gz.sig
87     gpg --no-default-keyring --keyring ./gnu-keyring.gpg --verify mpc-$mpc_version.tar.gz.sig
88   fi
89   if [ ! -f "mpfr-$mpfr_version.tar.xz" ]; then
90     wget http://ftpmirror.gnu.org/gnu/mpfr/mpfr-$mpfr_version.tar.xz
91     wget http://ftpmirror.gnu.org/gnu/mpfr/mpfr-$mpfr_version.tar.xz.sig
92     gpg --no-default-keyring --keyring ./gnu-keyring.gpg --verify mpfr-$mpfr_version.tar.xz.sig
93   fi
94 }
95
96 setup_source () {
97   # After the source code has been downloaded and verified, this
98   # function extracts the tarballs and places things into the
99   # appropriate locations as needed.
100   if [ ! -d "binutils-$binutils_version" ]; then
101     tar xf binutils-$binutils_version.tar.lz
102   fi
103   if [ ! -d "gcc-$gcc_version" ]; then
104     tar xf gcc-$gcc_version.tar.xz
105   fi
106   if [ ! -d "gcc-$gcc_version/gmp" ]; then
107     mkdir gcc-$gcc_version/gmp
108     tar xf gmp-$gmp_version.tar.lz -C gcc-$gcc_version/gmp --strip-components=1
109   fi
110   if [ ! -d "gcc-$gcc_version/mpc" ]; then
111     mkdir gcc-$gcc_version/mpc
112     tar xf mpc-$mpc_version.tar.gz -C gcc-$gcc_version/mpc --strip-components=1
113   fi
114   if [ ! -d "gcc-$gcc_version/mpfr" ]; then
115     mkdir gcc-$gcc_version/mpfr
116     tar xf mpfr-$mpfr_version.tar.xz -C gcc-$gcc_version/mpfr --strip-components=1
117     # Regenerate GNU build system files for MPFR due to version
118     # differences with MPFR wanting a newer version of Automake
119     # than I had.
120     cd gcc-$gcc_version/mpfr
121     autoreconf -f -i
122     cd ../../
123   fi
124 }
125
126 build () {
127   # This function handles the actual compiling of the toolchain.
128   mkdir build
129   cd build
130   if [ "$1" = "binutils" ]; then
131     ../binutils-$binutils_version/configure --target=$target --prefix=$dir/$toolchain_directory --disable-gdb --disable-libdecnumber --disable-nls --disable-readline --disable-sim --disable-werror --enable-64-bit-bfd --enable-obsolete 2>&1 | tee ../logs-$toolchain_directory/$target.log
132     elif [ "$1" = "gcc" ]; then
133     ../gcc-$gcc_version/configure --target=$target --prefix=$dir/$toolchain_directory --disable-bootstrap --disable-decimal-float --disable-libatomic --disable-libcc1 --disable-libgomp --disable-libmpx --disable-libmudflap --disable-libquadmath --disable-libssp --disable-nls --disable-shared --disable-threads --enable-checking=release --enable-languages=c --enable-targets=all --without-headers `if [[ $architectures == powerpc64le-* ]]; then echo "--disable-multilib";fi` 2>&1 | tee -a ../logs-$toolchain_directory/$target.log
134   fi
135   make -j`nproc` 2>&1 | tee -a ../logs-$toolchain_directory/$target.log
136   make install 2>&1 | tee -a ../logs-$toolchain_directory/$target.log
137   cd ../
138   rm -fr build
139 }
140
141 set_path () {
142   # This adjusts the path to point to the location where the
143   # programs are being installed in order to use them during this
144   # process.
145   # Where are we?
146   dir=$(pwd)
147   # Save $PATH for later restoration
148   export OLDPATH=$PATH
149   export PATH=$dir/$toolchain_directory/bin:$PATH
150 }
151
152 reset_path () {
153   # This changes the $PATH back to what it was originally. This is
154   # to prevent the $PATH from continuing to grow between loops and
155   # make sure it always points to the correct place, as adjusted for
156   # each run through the loop for each architecture.
157   export PATH=$OLDPATH
158 }
159
160 setup_directories () {
161   # This make sure that certain needed directories exist before
162   # starting and to also make sure that any intermediate build
163   # directory is removed before starting, in case there had been a
164   # build failure in a prior attempt.
165   if [ ! -d "logs-$toolchain_directory" ]; then
166     mkdir logs-$toolchain_directory
167   fi
168
169   if [ ! -d "$toolchain_directory" ]; then
170     mkdir $toolchain_directory
171   fi
172
173   if [ -d "build" ]; then
174     rm -fr build
175   fi
176 }
177
178 # This loop is responsible for setting up any architecture-specific
179 # adjustments. Anything not called out as being a special case will be
180 # built using the default settings.
181 for target in "${architectures[@]}"
182 do
183   :
184   # Note the generally desired software versions. In some cases
185   # some architectures may need different versions of these.
186   # Examples include older kernel series that don't build with new
187   # versions of GCC, or for other reasons. As a result any given
188   # architecture may need to set up more than one combination of
189   # these. These are just the defaults and are adjusted for specific
190   # architectures as needed as the program runs.
191   export gcc_version="12.2.0"
192   export binutils_version="2.39"
193   export gmp_version="6.2.1"
194   export mpc_version="1.2.1"
195   export mpfr_version="4.1.0"
196   # The $toolchain_directory variable is used to store each
197   # compiled toolchain, named after the associated GCC version when
198   # the above versions are being used. The intention is to change
199   # the directory name to something else when needing to assemble a
200   # different variant based on the need of some specific
201   # architecture, such as needing to build the latest GCC but with
202   # an older version of binutils or for any other situation where a
203   # different name would be desirable so as to distinguish them from
204   # other toolchain builds that use the defaults.
205   export toolchain_directory="toolchain-$gcc_version"
206   set_path
207   reset_path
208   set_path
209   setup_directories
210   download_source
211   setup_source
212   build binutils
213   build gcc
214   reset_path
215   # Now build some additional toolchains beyond the default ones. This
216   # is because some older kernels needs older toolchain versions.
217   case $target in
218     mipsel-linux)
219       # The 4.9 kernel series needs to be built with GCC 11.3
220       export gcc_version="11.3.0"
221       export toolchain_directory="toolchain-$gcc_version"
222       reset_path
223       set_path
224       reset_path
225       set_path
226       setup_directories
227       download_source
228       setup_source
229       build binutils
230       build gcc
231       reset_path
232     ;;
233     powerpc64-linux)
234       # The 5.10 and 4.9 series needs to be build with GCC 11.3
235       export gcc_version="11.3.0"
236       export toolchain_directory="toolchain-$gcc_version"
237       reset_path
238       set_path
239       reset_path
240       set_path
241       setup_directories
242       download_source
243       setup_source
244       build binutils
245       build gcc
246       reset_path
247     ;;
248     powerpc64le-linux)
249       # The 5.10 and 4.9 series needs to be build with GCC 11.3
250       export gcc_version="11.3.0"
251       export toolchain_directory="toolchain-$gcc_version"
252       reset_path
253       set_path
254       reset_path
255       set_path
256       setup_directories
257       download_source
258       setup_source
259       build binutils
260       build gcc
261       reset_path
262     ;;
263     s390x-linux)
264       # The 4.19 kerrnel series needs to be built with GCC 11.3
265       export gcc_version="11.3.0"
266       export toolchain_directory="toolchain-$gcc_version"
267       reset_path
268       set_path
269       reset_path
270       set_path
271       setup_directories
272       download_source
273       setup_source
274       build binutils
275       build gcc
276       reset_path
277       # The 4.9, and 4.14 kernel series needs to be built with GCC 8.5
278       export gcc_version="8.5.0"
279       export toolchain_directory="toolchain-$gcc_version"
280       reset_path
281       set_path
282       reset_path
283       set_path
284       setup_directories
285       download_source
286       setup_source
287       build binutils
288       build gcc
289       reset_path
290     ;;
291   esac
292 done