-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathdoit
executable file
·351 lines (304 loc) · 9.7 KB
/
doit
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
340
341
342
343
344
345
346
347
348
349
350
351
#!/usr/bin/env bash
OS="$(uname)"
HOSTARCH="$(uname -m)"
PARALLEL=
FETCH=0
QUIET=0
STRIP=0
TRIPLET=
BINUTILSARGS=
GCCARGS=
GDBARGS=
GDB=1
GNU_MIRROR=https://mirrors.kernel.org/gnu
# Get absolute path, will spawn a subshell then exit so our pwd is retained
SCRIPTROOT=$(cd "$(dirname $0)" && pwd)
PATCHES=$SCRIPTROOT/patches/
# Cause errors in pipes to return failure when necessary
set -o pipefail
function err() {
echo "doit: error during build"
if [ "$QUIET" = "1" ]; then
echo "doit: dumping last 50 lines of build log..."
echo "doit: see $OUTDIR/build.log for the full details"
tail -50 $OUTDIR/build.log
fi
exit 1
}
trap err ERR
function help()
{
echo "Options"
echo " -a <arch list> architectures to build"
echo " example: -a 'arm' or -a 'arm i386 x86_64' for multiple"
echo " -c use compilation cache (ccache must be installed)"
echo " -f fetch source releases from upstream"
echo " -g do not build GDB (not supported on some architectures)"
echo " -h|-? display this help message"
echo " -j<#> use <#> parallel workers to build"
echo " -o <dir> output directory"
echo " -q make the build quieter"
echo " -s strip the binaries"
echo " -T custom triple suffix to add to the architecture"
echo " -B pass custom flags to binutils configure script"
echo " -G pass custom flags to GCC configure script"
echo " -D pass custom flags to GDB configure script"
exit 1
}
function log()
{
if [ "$QUIET" = "1" ]; then
"$@" >> $OUTDIR/build.log 2>&1
else
"$@" 2>&1 | tee -a $OUTDIR/build.log
fi
}
function download-archive()
{
local name="$1"
local ver="$2"
local ext="$3"
local subdir="$4"
local filename="$name-$ver.tar.$ext"
if [ ! -f "$ARCHIVES/$filename" ]; then
echo "fetching $name-$ver"
log wget -P "$ARCHIVES" -N "$GNU_MIRROR/$name/$subdir$filename"
else
log echo "$filename already downloaded, skipping"
fi
}
function full-path {
case "$1" in
[!/]*) echo "$PWD/$1" ;;
*) echo "$1" ;;
esac
}
function extract-tool()
{
#echo "extract-tool" $1 $2 $3 $4 $5
local TARFILE=${1}-${2}.tar$3
local TARGETDIR=${1}-${2}
local HASH="$4"
if [ -z ${TARGETDIR} ]; then
log echo "error, targetdir is empty"
exit 1
fi
if [ -f ${TARGETDIR}/.extracted ]; then
log echo "$TARFILE already extracted into $TARGETDIR, skipping"
return 0
fi
if [ ! -f $ARCHIVES/$TARFILE ]; then
log echo "error, missing $TARFILE"
exit 1
fi
echo "checking $TARFILE integrity"
if [ "$(shasum -a 256 -b "$ARCHIVES/$TARFILE" | cut -f1 -d' ')" != "$HASH" ]; then
log echo "$TARFILE failed integrity check"
exit 1
fi
echo extracting $TARFILE
pushd $OUTDIR > /dev/null
rm -rf -- "$TARGETDIR"
tar xf $ARCHIVES/$TARFILE || exit 1
if [ ! -z "$5" ]; then
local PATCHES=$(echo $5-* | sort)
for i in $PATCHES; do
echo patching $1 with $i
log echo patching $1 with $i
log patch -d "$TARGETDIR" -p1 < "$i" || exit 1
done
fi
touch $TARGETDIR/.extracted || exit 1
popd > /dev/null
}
MAKE=make
if [ "$OS" = "Linux" ]; then
COUNT=`grep processor /proc/cpuinfo | wc -l`
PARALLEL=-j`expr $COUNT + $COUNT`
fi
if [ "$OS" = "Darwin" ]; then
PARALLEL=-j`sysctl -n hw.ncpu`
export CXXFLAGS="-fbracket-depth=1024 -O2"
fi
if [ "$OS" = "FreeBSD" ]; then
PARALLEL=-j`sysctl -n hw.ncpu`
export CXXFLAGS="-fbracket-depth=1024 -O2"
MAKE=gmake
fi
if [ "$HOSTARCH" = "amd64" ]; then
HOSTARCH=x86_64
fi
if [ $# == "0" ]; then
help
fi
while getopts a:cfghj:o:qsT:B:G:D:? arg
do
case $arg in
a ) ARCHES=$OPTARG ;;
c ) CCACHE=1 ;;
f ) FETCH=1 ;;
g ) GDB=0 ;;
j ) PARALLEL="-j$OPTARG" ;;
o ) OUTDIR="$OPTARG" ;;
q ) QUIET=1 ;;
s ) STRIP=1 ;;
T ) TRIPLET="$OPTARG" ;;
B ) BINUTILSARGS="$OPTARG" ;;
G ) GCCARGS="$OPTARG" ;;
D ) GDBARGS="$OPTARG" ;;
h ) help ;;
? ) help ;;
* ) echo "unrecognized option '$arg'" ; exit 1 ;;
esac
done
if [ -z "$ARCHES" ]; then
echo need to specify architectures to build
echo ie -a "arm sh"
exit 1
fi
if [ -z "$OUTDIR" ]; then
OUTDIR=`pwd`
else
if ! mkdir -p -- "$OUTDIR"; then
log echo Unable to create output directory "$OUTDIR"
exit 1
fi
OUTDIR="$(full-path "$OUTDIR")"
fi
ARCHIVES=$OUTDIR/archives
if [ -z $(which makeinfo) ]; then
echo makeinfo not found. On debian/ubuntu this is provided by the texinfo package.
exit 1
fi
export CC="cc"
export CXX="c++"
if [ "$CCACHE" = "1" ]; then
export CC="ccache $CC"
export CXX="ccache $CXX"
fi
log date
log echo "ARCHES='$ARCHES' PARALLEL='$PARALLEL' FETCH='$FETCH' CCACHE='$CCACHE'"
# load GCCVER and BINVER
. toolvers
if [ "$FETCH" = "1" ]; then
download-archive binutils $BINVER xz
download-archive gcc $GCCVER xz "gcc-$GCCVER/"
download-archive gdb $GDBVER xz
download-archive gmp $GMPVER xz
download-archive mpc $MPCVER gz
download-archive mpfr $MPFRVER xz
fi
if [ ! -f $OUTDIR/.extracted-stamp ]; then
extract-tool binutils $BINVER .xz $BINHASH $PATCHES/binutils-patch
extract-tool gcc $GCCVER .xz $GCCHASH $PATCHES/gcc-patch
extract-tool gdb $GDBVER .xz $GDBHASH $PATCHES/gdb-patch
extract-tool gmp $GMPVER .xz $GMPHASH
extract-tool mpc $MPCVER .gz $MPCHASH
extract-tool mpfr $MPFRVER .xz $MPFRHASH
# link the last three libs into gcc
pushd $OUTDIR/gcc-$GCCVER > /dev/null
ln -sf ../gmp-$GMPVER gmp
ln -sf ../mpc-$MPCVER mpc
ln -sf ../mpfr-$MPFRVER mpfr
popd > /dev/null
# link the last three libs into gdb
pushd $OUTDIR/gdb-$GDBVER > /dev/null
ln -sf ../gmp-$GMPVER gmp
ln -sf ../mpfr-$MPFRVER mpfr
popd > /dev/null
touch $OUTDIR/.extracted-stamp
fi
# switch to the outdir to root all further activities
pushd $OUTDIR > /dev/null
for ARCH in $ARCHES; do
echo building for arch $ARCH
if [ -n "$TRIPLET" ]
then
TARGET="$ARCH-$TRIPLET"
else
case $ARCH in
arm) TARGET=arm-eabi;;
pdp11) TARGET=pdp11-aout;;
vax) TARGET=vax--netbsdelf;;
*) TARGET=$ARCH-elf;;
esac
fi
echo target triple is $TARGET
INSTALLPATH=$OUTDIR/$TARGET-$GCCVER-$OS-$HOSTARCH
BINBUILDPATH=$OUTDIR/build-binutils-$BINVER-$ARCH-$OS-$HOSTARCH
GCCBUILDPATH=$OUTDIR/build-gcc-$GCCVER-$ARCH-$OS-$HOSTARCH
GDBBUILDPATH=$OUTDIR/build-gdb-$GDBVER-$ARCH-$OS-$HOSTARCH
export PATH=$INSTALLPATH/bin:$PATH
# Building Binutils
if [ ! -f $BINBUILDPATH/built.txt ]; then
echo building binutils
mkdir -p $BINBUILDPATH
pushd $BINBUILDPATH > /dev/null
log ../binutils-$BINVER/configure --target=$TARGET --prefix=$INSTALLPATH --disable-werror $BINUTILSARGS
log $MAKE $PARALLEL
log $MAKE install
touch built.txt
popd > /dev/null
fi
# Building GCC
if [ ! -f $GCCBUILDPATH/built.txt ]; then
echo building gcc
ARCH_OPTIONS=
case "$TARGET" in
arm-eabi)
# build a very aggressive set of multi libs
ARCH_OPTIONS="--with-multilib-list=aprofile,rmprofile"
;;
vax--netbsdelf)
ARCH_OPTIONS="--disable-multilib --disable-nls --without-isl --enable-long-long"
;;
esac
mkdir -p $GCCBUILDPATH
pushd $GCCBUILDPATH > /dev/null
log ../gcc-$GCCVER/configure --target=$TARGET --prefix=$INSTALLPATH --enable-languages=c,c++ $ARCH_OPTIONS --disable-werror $GCCARGS
log $MAKE all-gcc $PARALLEL
log $MAKE all-target-libgcc $PARALLEL
log $MAKE install-gcc
log $MAKE install-target-libgcc
touch built.txt
popd > /dev/null
fi
if (( $GDB )); then
if [ ! -f $GDBBUILDPATH/built.txt ]; then
case "$TARGET" in
aarch64-elf) ARCH_OPTIONS="--enable-targets=arm-eabi --disable-sim" ;;
sparc-elf) ARCH_OPTIONS="--disable-sim" ;;
*) ARCH_OPTIONS="" ;;
esac
if [ "$OS" = "Darwin" ]; then
# a hack to work around gdb not wanting to find libgmp
export LDFLAGS="-L/usr/lib -L/opt/local/lib"
export CPPFLAGS="-I/usr/include -I/opt/local/include"
fi
if [ "$OS" = "FreeBSD" ]; then
# a hack to work around gdb not wanting to find libgmp
export LDFLAGS="-L/usr/lib -L/usr/local/lib"
export CPPFLAGS="-I/usr/include -I/usr/local/include"
fi
echo building gdb
mkdir -p $GDBBUILDPATH
pushd $GDBBUILDPATH > /dev/null
log ../gdb-$GDBVER/configure --target=$TARGET --prefix=$INSTALLPATH $ARCH_OPTIONS --disable-werror $GDBARGS
log $MAKE $PARALLEL
log $MAKE install
touch built.txt
popd > /dev/null
export -n LDFLAGS
export -n CPPFLAGS
fi
fi
# Optionally strip the binaries
if [ "${STRIP}" = "1" ]; then
find "${INSTALLPATH}/bin" -type f -exec strip {} \;
for filename in $(find "${INSTALLPATH}/libexec" -type f); do
(file "${filename}" | grep -q ELF) && strip "${filename}"
done
fi
done
echo all done
# vim: ts=4 sw=4 expandtab