-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathbuild-toolchain.sh
executable file
·339 lines (299 loc) · 12.1 KB
/
build-toolchain.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#! /bin/bash
# N64 MIPS GCC toolchain build/install script for Unix distributions
# (c) 2012-2023 DragonMinded and libDragon Contributors.
# See the root folder for license information.
# Bash strict mode http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'
# Check that N64_INST is defined
if [ -z "${N64_INST-}" ]; then
echo "N64_INST environment variable is not defined."
echo "Please define N64_INST and point it to the requested installation directory"
exit 1
fi
# Path where the toolchain will be built.
BUILD_PATH="${BUILD_PATH:-toolchain}"
DOWNLOAD_PATH="${DOWNLOAD_PATH:-$BUILD_PATH}"
# Defines the build system variables to allow cross compilation.
N64_BUILD=${N64_BUILD:-""}
N64_HOST=${N64_HOST:-""}
N64_TARGET=${N64_TARGET:-mips64-elf}
# Set N64_INST before calling the script to change the default installation directory path
INSTALL_PATH="${N64_INST}"
# Set PATH for newlib to compile using GCC for MIPS N64 (pass 1)
export PATH="$PATH:$INSTALL_PATH/bin"
# Determine how many parallel Make jobs to run based on CPU count
JOBS="${JOBS:-$(getconf _NPROCESSORS_ONLN)}"
JOBS="${JOBS:-1}" # If getconf returned nothing, default to 1
# GCC configure arguments to use system GMP/MPC/MFPF
GCC_CONFIGURE_ARGS=()
# Dependency source libs (Versions)
BINUTILS_V=2.43.1
GCC_V=14.2.0
NEWLIB_V=4.4.0.20231231
GMP_V=6.3.0
MPC_V=1.3.1
MPFR_V=4.2.1
MAKE_V=${MAKE_V:-""}
# Create build and download directories
mkdir -p "$BUILD_PATH" "$DOWNLOAD_PATH"
# Resolve absolute paths for build and download directories
BUILD_PATH=$(cd "$BUILD_PATH" && pwd)
DOWNLOAD_PATH=$(cd "$DOWNLOAD_PATH" && pwd)
# Check if a command-line tool is available: status 0 means "yes"; status 1 means "no"
command_exists () {
(command -v "$1" >/dev/null 2>&1)
return $?
}
# Download the file URL using wget or curl (depending on which is installed)
download () {
if command_exists wget ; then (cd "$DOWNLOAD_PATH" && wget -c "$1")
elif command_exists curl ; then (cd "$DOWNLOAD_PATH" && curl -LO "$1")
else
echo "Install wget or curl to download toolchain sources" 1>&2
return 1
fi
}
# Compilation on macOS via homebrew
if [[ $OSTYPE == 'darwin'* ]]; then
if ! command_exists brew; then
echo "Compilation on macOS is supported via Homebrew (https://brew.sh)"
echo "Please install homebrew and try again"
exit 1
fi
# Install required dependencies. gsed is really required, the others are optionals
# and just speed up build.
brew install -q gmp mpfr libmpc gsed gcc isl libpng lz4 make mpc texinfo zlib
# FIXME: we could avoid download/symlink GMP and friends for a cross-compiler
# but we need to symlink them for the canadian compiler.
#GMP_V=""
#MPC_V=""
#MPFR_V=""
# Tell GCC configure where to find the dependent libraries
GCC_CONFIGURE_ARGS=(
"--with-gmp=$(brew --prefix)"
"--with-mpfr=$(brew --prefix)"
"--with-mpc=$(brew --prefix)"
"--with-zlib=$(brew --prefix)"
)
# Install GNU sed as default sed in PATH. GCC compilation fails otherwise,
# because it does not work with BSD sed.
PATH="$(brew --prefix gsed)/libexec/gnubin:$PATH"
export PATH
else
# Configure GCC arguments for non-macOS platforms
GCC_CONFIGURE_ARGS+=("--with-system-zlib")
fi
# Dependency downloads and unpack
test -f "$DOWNLOAD_PATH/binutils-$BINUTILS_V.tar.gz" || download "https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_V.tar.gz"
test -d "$BUILD_PATH/binutils-$BINUTILS_V" || tar -xzf "$DOWNLOAD_PATH/binutils-$BINUTILS_V.tar.gz" -C "$BUILD_PATH"
test -f "$DOWNLOAD_PATH/gcc-$GCC_V.tar.gz" || download "https://ftp.gnu.org/gnu/gcc/gcc-$GCC_V/gcc-$GCC_V.tar.gz"
test -d "$BUILD_PATH/gcc-$GCC_V" || tar -xzf "$DOWNLOAD_PATH/gcc-$GCC_V.tar.gz" -C "$BUILD_PATH"
test -f "$DOWNLOAD_PATH/newlib-$NEWLIB_V.tar.gz" || download "https://sourceware.org/pub/newlib/newlib-$NEWLIB_V.tar.gz"
test -d "$BUILD_PATH/newlib-$NEWLIB_V" || tar -xzf "$DOWNLOAD_PATH/newlib-$NEWLIB_V.tar.gz" -C "$BUILD_PATH"
if [ "$GMP_V" != "" ]; then
test -f "$DOWNLOAD_PATH/gmp-$GMP_V.tar.bz2" || download "https://ftp.gnu.org/gnu/gmp/gmp-$GMP_V.tar.bz2"
test -d "$BUILD_PATH/gmp-$GMP_V" || tar -xf "$DOWNLOAD_PATH/gmp-$GMP_V.tar.bz2" -C "$BUILD_PATH" # note: no .gz download file currently available
pushd "$BUILD_PATH/gcc-$GCC_V"
ln -sf ../"gmp-$GMP_V" "gmp"
popd
fi
if [ "$MPC_V" != "" ]; then
test -f "$DOWNLOAD_PATH/mpc-$MPC_V.tar.gz" || download "https://ftp.gnu.org/gnu/mpc/mpc-$MPC_V.tar.gz"
test -d "$BUILD_PATH/mpc-$MPC_V" || tar -xzf "$DOWNLOAD_PATH/mpc-$MPC_V.tar.gz" -C "$BUILD_PATH"
pushd "$BUILD_PATH/gcc-$GCC_V"
ln -sf ../"mpc-$MPC_V" "mpc"
popd
fi
if [ "$MPFR_V" != "" ]; then
test -f "$DOWNLOAD_PATH/mpfr-$MPFR_V.tar.gz" || download "https://ftp.gnu.org/gnu/mpfr/mpfr-$MPFR_V.tar.gz"
test -d "$BUILD_PATH/mpfr-$MPFR_V" || tar -xzf "$DOWNLOAD_PATH/mpfr-$MPFR_V.tar.gz" -C "$BUILD_PATH"
pushd "$BUILD_PATH/gcc-$GCC_V"
ln -sf ../"mpfr-$MPFR_V" "mpfr"
popd
fi
if [ "$MAKE_V" != "" ]; then
test -f "$DOWNLOAD_PATH/make-$MAKE_V.tar.gz" || download "https://ftp.gnu.org/gnu/make/make-$MAKE_V.tar.gz"
test -d "$BUILD_PATH/make-$MAKE_V" || tar -xzf "$DOWNLOAD_PATH/make-$MAKE_V.tar.gz" -C "$BUILD_PATH"
fi
cd "$BUILD_PATH"
# Deduce build triplet using config.guess (if not specified)
# This is by the definition the current system so it should be OK.
if [ "$N64_BUILD" == "" ]; then
N64_BUILD=$("binutils-$BINUTILS_V"/config.guess)
fi
if [ "$N64_HOST" == "" ]; then
N64_HOST="$N64_BUILD"
fi
if [ "$N64_BUILD" == "$N64_HOST" ]; then
# Standard cross.
CROSS_PREFIX=$INSTALL_PATH
else
# Canadian cross.
# The standard BUILD->TARGET cross-compiler will be installed into a separate prefix, as it is not
# part of the distribution.
mkdir -p cross_prefix
CROSS_PREFIX="$(cd "$(dirname -- "cross_prefix")" >/dev/null; pwd -P)/$(basename -- "cross_prefix")"
PATH="$CROSS_PREFIX/bin:$PATH"
export PATH
# Instead, the HOST->TARGET cross-compiler can be installed into the final installation path
CANADIAN_PREFIX=$INSTALL_PATH
# We need to build a canadian toolchain.
# First we need a host compiler, that is binutils+gcc targeting the host. For instance,
# when building a Libdragon Windows toolchain from Linux, this would be x86_64-w64-ming32,
# that is, a compiler that we run that generates Windows executables.
# Check if a host compiler is available. If so, we can just skip this step.
if command_exists "$N64_HOST"-gcc; then
echo Found host compiler: "$N64_HOST"-gcc in PATH. Using it.
else
if [ "$N64_HOST" == "x86_64-w64-mingw32" ]; then
echo This script requires a working Windows cross-compiler.
echo We could build it for you, but it would make the process even longer.
echo Install it instead:
echo " * Linux (Debian/Ubuntu): apt install mingw-w64"
echo " * macOS: brew install mingw-w64"
exit 1
else
echo "Unimplemented option: we support building a Windows toolchain only, for now."
fi
fi
fi
# Compile BUILD->TARGET binutils
mkdir -p binutils_compile_target
pushd binutils_compile_target
../"binutils-$BINUTILS_V"/configure \
--prefix="$CROSS_PREFIX" \
--target="$N64_TARGET" \
--with-cpu=mips64vr4300 \
--disable-werror
make -j "$JOBS"
make install-strip || sudo make install-strip || su -c "make install-strip"
popd
# Compile GCC for MIPS N64.
# We need to build the C++ compiler to build the target libstd++ later.
mkdir -p gcc_compile_target
pushd gcc_compile_target
../"gcc-$GCC_V"/configure "${GCC_CONFIGURE_ARGS[@]}" \
--prefix="$CROSS_PREFIX" \
--target="$N64_TARGET" \
--with-arch=vr4300 \
--with-tune=vr4300 \
--enable-languages=c,c++ \
--without-headers \
--disable-libssp \
--enable-multilib \
--disable-shared \
--with-gcc \
--with-newlib \
--disable-win32-registry \
--disable-nls \
--disable-werror
make all-gcc -j "$JOBS"
make install-gcc || sudo make install-gcc || su -c "make install-gcc"
make all-target-libgcc -j "$JOBS"
make install-target-libgcc || sudo make install-target-libgcc || su -c "make install-target-libgcc"
popd
# Compile newlib for target.
mkdir -p newlib_compile_target
pushd newlib_compile_target
CFLAGS_FOR_TARGET="-DHAVE_ASSERT_FUNC -O2 -fpermissive" ../"newlib-$NEWLIB_V"/configure \
--prefix="$CROSS_PREFIX" \
--target="$N64_TARGET" \
--with-cpu=mips64vr4300 \
--disable-libssp \
--disable-werror \
--enable-newlib-multithread \
--enable-newlib-retargetable-locking
make -j "$JOBS"
make install || sudo env PATH="$PATH" make install || su -c "env PATH=\"$PATH\" make install"
popd
# For a standard cross-compiler, the only thing left is to finish compiling the target libraries
# like libstd++. We can continue on the previous GCC build target.
if [ "$N64_BUILD" == "$N64_HOST" ]; then
pushd gcc_compile_target
make all -j "$JOBS"
make install-strip || sudo make install-strip || su -c "make install-strip"
popd
else
# Compile HOST->TARGET binutils
# NOTE: we pass --without-msgpack to workaround a bug in Binutils, introduced
# with this commit: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=2952f10cd79af4645222f124f28c7928287d8113
# This is due to the fact that pkg-config is used to activate compilation with msgpack
# but that it is not correct in the case of a canadian cross.
echo "Compiling binutils-$BINUTILS_V for foreign host"
mkdir -p binutils_compile_host
pushd binutils_compile_host
../"binutils-$BINUTILS_V"/configure \
--prefix="$INSTALL_PATH" \
--build="$N64_BUILD" \
--host="$N64_HOST" \
--target="$N64_TARGET" \
--disable-werror \
--without-msgpack
make -j "$JOBS"
make install-strip || sudo make install-strip || su -c "make install-strip"
popd
# Compile HOST->TARGET gcc
mkdir -p gcc_compile
pushd gcc_compile
CFLAGS_FOR_TARGET="-O2" CXXFLAGS_FOR_TARGET="-O2" \
../"gcc-$GCC_V"/configure \
--prefix="$INSTALL_PATH" \
--target="$N64_TARGET" \
--build="$N64_BUILD" \
--host="$N64_HOST" \
--disable-werror \
--with-arch=vr4300 \
--with-tune=vr4300 \
--enable-languages=c,c++ \
--with-newlib \
--enable-multilib \
--with-gcc \
--disable-libssp \
--disable-shared \
--disable-win32-registry \
--disable-nls
make all-target-libgcc -j "$JOBS"
make install-target-libgcc || sudo make install-target-libgcc || su -c "make install-target-libgcc"
popd
# Compile newlib for target.
mkdir -p newlib_compile
pushd newlib_compile
CFLAGS_FOR_TARGET="-DHAVE_ASSERT_FUNC -O2 -fpermissive" ../"newlib-$NEWLIB_V"/configure \
--prefix="$INSTALL_PATH" \
--target="$N64_TARGET" \
--with-cpu=mips64vr4300 \
--disable-libssp \
--disable-werror \
--enable-newlib-multithread \
--enable-newlib-retargetable-locking
make -j "$JOBS"
make install || sudo env PATH="$PATH" make install || su -c "env PATH=\"$PATH\" make install"
popd
# Finish compiling GCC
mkdir -p gcc_compile
pushd gcc_compile
make all -j "$JOBS"
make install-strip || sudo make install-strip || su -c "make install-strip"
popd
fi
if [ "$MAKE_V" != "" ]; then
pushd "make-$MAKE_V"
./configure \
--prefix="$INSTALL_PATH" \
--disable-largefile \
--disable-nls \
--disable-rpath \
--build="$N64_BUILD" \
--host="$N64_HOST"
make -j "$JOBS"
make install-strip || sudo make install-strip || su -c "make install-strip"
popd
fi
# Final message
echo
echo "***********************************************"
echo "Libdragon toolchain correctly built and installed"
echo "Installation directory: \"${N64_INST}\""
echo "Build directory: \"${BUILD_PATH}\" (can be removed now)"
echo "If you would like to install GDB in your toolchain, run build-gdb.sh"