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