-
Notifications
You must be signed in to change notification settings - Fork 48
/
build-elf32.sh
executable file
·444 lines (371 loc) · 17.1 KB
/
build-elf32.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
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
#!/usr/bin/env bash
# Copyright (C) 2009, 2011, 2012, 2013 Embecosm Limited
# Copyright (C) 2012-2017 Synopsys Inc.
# Contributor Joern Rennecke <[email protected]>
# Contributor Jeremy Bennett <[email protected]>
# Contributor Anton Kolesov <[email protected]>
# This script builds the ARC 32-bit ELF tool chain.
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------
# Usage:
# ${ARC_GNU}/toolchain/build-elf32.sh
# The directory in which we are invoked is the build directory, in which we
# find the components source trees and in which all build directories are created.
# All other parameters are set by environment variables
# LOGDIR
# Directory for all log files.
# ARC_GNU
# The directory containing all the sources. If not set, this will default
# to the directory containing this script.
# INSTALLDIR
# The directory where the tool chain should be installed
# ARC_ENDIAN
# "little" or "big"
# ELF32_DISABLE_MULTILIB
# Either --enable-multilib or --disable-multilib to control the building
# of multilibs.
# ISA_CPU
# For use with the --with-cpu flag to specify the ISA. Can be arc700 or
# arcem.
# CONFIG_EXTRA
# Additional flags for use with configuration.
# CFLAGS_FOR_TARGET
# CXXFLAGS_FOR_TARGET
# Additional flags used when building the target libraries (e.g. for
# compact libraries) picked up automatically by make. This variable is used
# by configure scripts and make, and build-elf.sh doesn't do anything about
# it explicitly.
# DO_PDF
# Either --pdf or --no-pdf to control whether we build and install PDFs of
# the user guides.
# PARALLEL
# string "-j <jobs> -l <load>" to control parallel make.
# HOST_INSTALL
# Make target prefix to install host application. Should be either
# "install" or "install-strip".
# BUILD_OPTSIZE_NEWLIB
# Build newlib libraries optimized for size in addition to normal ones.
# BUILD_OPTSIZE_LIBSTDCXX
# Build libstdc++ libraries optimized for size in addition to normal ones.
# DO_STRIP_TARGET_LIBRARIES
# See build-all.sh --elf32-strip-target-libs option.
# We source the script arc-init.sh to set up variables needed by the script
# and define a function to get to the configuration directory (which can be
# tricky under MinGW/MSYS environments).
# The script uses a build directory (bd-elf32[eb]) local to the directory in
# which it is executed.
# The script generates a date and time stamped log file in the logs directory.
# This version is modified to work with the source tree as organized in
# GitHub.
# ------------------------------------------------------------------------------
# Local variables.
if [ "${ARC_ENDIAN}" = "big" ]
then
arch=arceb
build_dir="$(echo "${PWD}")/bd-elf32eb"
else
arch=arc
build_dir="$(echo "${PWD}")/bd-elf32"
fi
if [ "${HOST}" = "macos" ]
then
macos_params="--with-guile=no"
fi
# Set up a logfile
logfile="${LOGDIR}/elf32-build-$(date -u +%F-%H%M).log"
rm -f "${logfile}"
echo "START ELF32: $(date)" | tee -a "$logfile"
# Initialize common variables and functions.
. "${ARC_GNU}"/toolchain/arc-init.sh
toolchain_build_dir=$PWD/toolchain
echo "Installing in ${INSTALLDIR}" | tee -a "$logfile"
# Purge old build dir if there is any and create a new one.
rm -rf "$build_dir"
mkdir -p "$build_dir"
# Location for toolchain with libs optimized for size.
optsize_install_dir=$build_dir/optsize_libs_install
# Binutils
build_dir_init binutils
configure_elf32 binutils binutils --disable-gdb
make_target building all
# Gas requires opcodes to be installed, LD requires BFD to be installed.
# However those dependencies are not described in the Makefiles, instead if
# required components is not yet installed, then dummy as-new and ld-new will
# be installed. Both libraries are installed by install-binutils. Therefore it
# is required that binutils is installed before ld and gas. That order
# denedency showed up only with Linux toolchain so far, but for safety same
# patch is applied to baremetal toolchain.
# Currently we simply use "install" instead of explicit install targets for
# each project, so it is not a problem.
# While it is possible to build with `all`, it is not possible to install with
# `install`, because in case of `strip-install` there is an error in the
# "readline" packet that doesn't support this target.
make_target_ordered installing ${HOST_INSTALL}-binutils ${HOST_INSTALL}-ld \
${HOST_INSTALL}-gas
# To play safe, libstdc++ is not built separately, but with the whole gcc,
# because it might not behave properly if it will be built by external
# compiler. Thus it is requried to install binutils to dummy installation dir
# for optsize libs. Cannot use "make DESTDIR=..." install, because prefix is !=
# /. Perhaps it makes sense to do prefix=/ and install everything with properly
# set DESTDIR.
if [ $BUILD_OPTSIZE_LIBSTDCXX = yes ]; then
cp -a $INSTALLDIR $optsize_install_dir
fi
if [ "$DO_PDF" = "--pdf" ]
then
make_target "generating PDF documentation" install-pdf-binutils \
install-pdf-ld install-pdf-gas
fi
# GCC precompiled headers are basically a dump of GCC memory - it is not some
# sort of a portable serialization format. This means that precompiled header
# generated by one compiler executable is not compatible with another
# executable. GCC documentation mentions this:
# https://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html . As a result
# with cross building precompiled headers of "host toolchain" are not
# applicable to "target toolchain". In the old times, when those build scripts
# used unified source tree, precompiled headers were generated (but were
# useless), but after unified source tree has been removed precompiled headers
# started to cause build issues. As a result it is required to disable them
# explicitly - otherwise either there would a build failure or a bunch of
# useless but large files.
if [ $IS_CROSS_COMPILING = yes ]; then
pch_opt=--disable-libstdcxx-pch
else
pch_opt=
fi
# GCC must be built in 2 stages. First minimal GCC build is for building
# newlib and second stage is a complete GCC with newlib headers. See:
# http://www.ifp.illinois.edu/~nakazato/tips/xgcc.html
# When building in Canadian cross stage 1 toolchain is useless, because it is
# not runnable on a build host, hence toolchain that can run on host should be
# already present in PATH and stage 1 may be skipped.
if [ "$DO_ELF32_GCC_STAGE1" = "yes" ]; then
build_dir_init gcc-stage1
configure_elf32 gcc gcc --without-headers --with-newlib
make_target building all-gcc
# It looks like that libssp install target is not parallel-friendly - I had
# occassional issues, when installing it's header.
make_target_ordered installing ${HOST_INSTALL}-gcc
fi
#
# Newlib (build in sub-shell with new tools added to the PATH)
#
build_dir_init newlib
(
PATH=$INSTALLDIR/bin:$PATH
configure_elf32 newlib
make_target building all
make_target installing install
if [ "$DO_PDF" = "--pdf" ]
then
# When texinfo is not in the /usr/bin, but in the custom location, then
# texi2pdf will fail to grab texinfo.tex macros file from its own
# distribution. At the same time, newlib/lib{c,m}/Makefile.in has an error
# where path to the texinfo.tex, shipped with newlib is invalid - it does
# not have enough ".." entries in it. To avoid this problem we have to
# explicitly set TEXINPUTS variable to point to texinfo.tex from newlib
# repository.
# In theory it should be good enough to just set TEXINPUTS to a path with
# newlib texinfo.tex and that would work regardless of whether there is a
# file in the /usr/share. But texinfo always has a turd up in its sleeve and
# on Ubuntu 16.04 it doesns't work - work on other distros, though. So to
# avoid the problem, I've made usage of this variable only when it is
# needed. It doesn't really address the problem that it doesn't work on
# Ubuntu 16.04, but in practice the only case where this hack was needed is
# a Synopsys environment, which is based on RHEL
# This trick breaks the build on MacOS.
if [ "$IS_MAC_OS" != "yes" -a ! -f /usr/share/texmf/tex/texinfo/texinfo.tex ]; then
export TEXINPUTS=$ARC_GNU/newlib/texinfo
fi
# Cannot use install-pdf because libgloss/doc does not support this target.
if [[ $TEXINFO_VERSION_MAJOR = 6 && $TEXINFO_VERSION_MINOR > 0 ]]; then
# There are problems with building newlib PDF documentation on Ubuntu 16.04: lib{c,m}.pdf is
# created but texi2pdf exits with !0 code due to:
# "/usr/bin/texi2dvi: pdfetex exited with bad status, quitting."
# Hence we have to invoke make trice - once for each PDF to be built, and then to install
# them. Detection is based on texinfo version instead of the OS.
# `make_target_ordered` will emit it's own error messages on make failures, so they should
# be suppressed, so that users will not be confused.
make_target_ordered "generating PDF documentation" \
install-pdf-target-newlib &>/dev/null || true
make_target_ordered "generating PDF documentation" \
install-pdf-target-newlib &>/dev/null || true
make_target_ordered "generating PDF documentation" install-pdf-target-newlib
else
make_target "generating PDF documentation" install-pdf-target-newlib
fi
fi
)
# GCC + libstdc++ with newly installed newlib headers
# Historical note for whoever would want (for some reason) to build gcc-stage2
# and libstdc++ separately: Libstdc++ is built in the build tree of GCC to
# avoid nasty problems which might happen when libstdc++ is being built in the
# separate directory while new compiler is in the PATH. Notably a known broken
# situation is when new toolchain is being installed on top of the previous
# installation and libstdc++ configure script will find some header files left
# from previous installation and will decide that some features are present,
# while they are not. That problem doesn't occur when libstdc++ is built in
# same build tree as GCC before that.
build_dir_init gcc-stage2
# -f{function,data}-sections is passed for libgcc. This is especially
# beneficial when generic software floating point implementation is used - it
# is all in one file, so using one function will pull in whole file, which can
# be as big as some smaller applications. Note that this will make sense only
# if final application is linked with --gc-sections.
configure_elf32 gcc gcc --with-newlib \
--with-headers="$INSTALLDIR/${arch}-elf32/include" \
--with-libs="$INSTALLDIR/${arch}-elf32/lib" $pch_opt \
CFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections $CFLAGS_FOR_TARGET"
make_target building all
# It looks like that libssp install target is not parallel-friendly - I had
# occassional issues, when installing it's header.
make_target_ordered installing ${HOST_INSTALL}-host install-target
if [ "$DO_PDF" = "--pdf" ]
then
# Don't build libstdc++ documentation because it requires additional
# software on build host.
make_target "generating PDF documentation" install-pdf-gcc
fi
# Compiler flags which tend to produce best code size results for ARC.
# CFLAGS_FOR_TARGET will be used after this optsize_flags, therefore one still
# can override default flags using --target-cflags. An exception is -Os - this
# flag is not in this variables and overrides C[XX]FLAGS_FOR_TARGET values of
# -Ox. This is done because for the general purpose library we let
# --target-cflags to override library flags completely, including -Ox value and
# hence in general --target-cflags should always contain some -Ox value (except
# for -O0, where it is not needed). But that would override -Os that is needed
# to size optimized libraries. Hence -Os is enforced.
optsize_flags="-g -ffunction-sections -fdata-sections \
-fno-branch-count-reg -fira-loop-pressure -fira-region=all \
-fno-sched-spec-insn-heuristic -fno-move-loop-invariants -mindexed-loads \
-mauto-modify-reg -fno-delayed-branch"
#
# Newlib optimized for size (build in sub-shell with new tools added to the PATH)
#
if [ $BUILD_OPTSIZE_NEWLIB = yes ]; then
build_dir_init newlib_optsize
(
PATH=$INSTALLDIR/bin:$PATH
INSTALLDIR=$optsize_install_dir
export CFLAGS_FOR_TARGET="$optsize_flags $CFLAGS_FOR_TARGET -Os"
configure_elf32 newlib_name newlib \
--enable-newlib-reent-small \
--disable-newlib-fvwrite-in-streamio \
--disable-newlib-fseek-optimization \
--disable-newlib-wide-orient \
--enable-newlib-nano-malloc \
--disable-newlib-unbuf-stream-opt \
--enable-lite-exit \
--enable-newlib-global-atexit \
--enable-newlib-nano-formatted-io \
--disable-newlib-multithread
make_target building all
make_target installing install
)
# Now copy multilibs. Code has been borrowed from ARM toolchain
# build-common.sh file found at https://launchpad.net/gcc-arm-embedded
multilibs=$(get_multilibs)
for multilib in ${multilibs[@]} ; do
multi_dir="${arch}-elf32/lib/${multilib%%;*}"
src_dir=$optsize_install_dir/$multi_dir
dst_dir=$INSTALLDIR/$multi_dir
cp -f $src_dir/libc.a $dst_dir/libc_nano.a
cp -f $src_dir/libg.a $dst_dir/libg_nano.a
cp -f $src_dir/libm.a $dst_dir/libm_nano.a
done
fi
#
# libstdc++ optimized for size
#
# Note that it will effectively build gcc-stage2 one more time for it's purposes.
if [ $BUILD_OPTSIZE_LIBSTDCXX = yes ]; then
build_dir_init libstdcxx_optsize
(
INSTALLDIR=$optsize_install_dir
configure_elf32 libstdc++_optsize gcc --with-newlib $pch_opt \
--with-headers="$INSTALLDIR/${arch}-elf32/include" \
--with-libs="$INSTALLDIR/${arch}-elf32/lib" $pch_opt \
CXXFLAGS_FOR_TARGET="$optsize_flags -fno-exceptions $CXXFLAGS_FOR_TARGET -Os"
)
make_target building all-target-libstdc++-v3
make_target installing install-target-libstdc++-v3
# Now copy multilibs. Code has been borrowed from ARM toolchain
# build-common.sh file found at https://launchpad.net/gcc-arm-embedded
# Default multi-lib `.' will not contain listdc++ files in case of GCC 6+.
multilibs=$(get_multilibs)
for multilib in ${multilibs[@]} ; do
if [ "${multilib%%;*}" = "." ]; then
continue
fi
multi_dir="${arch}-elf32/lib/${multilib%%;*}"
src_dir=$optsize_install_dir/$multi_dir
dst_dir=$INSTALLDIR/$multi_dir
cp -f $src_dir/libstdc++.a $dst_dir/libstdc++_nano.a
cp -f $src_dir/libsupc++.a $dst_dir/libsupc++_nano.a
done
fi
# Expat if requested
if [ "$SYSTEM_EXPAT" = no ]
then
build_expat $toolchain_build_dir/_download_tmp elf32
fi
# GDB
# Similar to ARC Linux targets, on Windows there are issues with exceptions when
# GDB is compiled as a C++ applications, so as a temporary measure disable C++
# when doing canadian cross.
if [ $IS_CROSS_COMPILING = yes ]; then
cxx_build=--disable-build-with-cxx
else
cxx_build=
fi
build_dir_init gdb
configure_elf32 gdb gdb --disable-ld --disable-gas --disable-binutils ${macos_params} \
--enable-targets=arc-linux-uclibc $cxx_build
make_target building all
make_target installing ${HOST_INSTALL}-gdb
if [ "$DO_PDF" = "--pdf" ]
then
make_target "generating PDF documentation" install-pdf-gdb
fi
# Copy TCF handler.
cp "$ARC_GNU/toolchain/extras/arc-tcf-gcc" "$INSTALLDIR/bin/${arch}-elf32-tcf-gcc"
# Strip files from debug symbols
if [ "$DO_STRIP_TARGET_LIBRARIES" = yes ]; then
if [ $IS_CROSS_COMPILING = yes ]; then
# Use cross tools in the PATH
objcopy=${arch}-elf32-objcopy
else
objcopy=$INSTALLDIR/bin/${arch}-elf32-objcopy
fi
# Note that in case lib/gcc/arc-elf32 contains files for some another GCC
# version - those will be stripped as well.
files=$(find $INSTALLDIR/${arch}-elf32/lib \
$INSTALLDIR/lib/gcc/${arch}-elf32 -name \*.a -o -name \*.o)
# Using `strip` instead of `objcopy` would render archives usable - linker
# would complain about missing index in .a files. As of note - libgmon.h
# includes a header file libgcc_tm.h so `objcopy` would emit an error
# message that this file has "unrecognizable format". Whether header file
# is included in archive by purpose or by mistake is not known to me,
# however this is done in the generic part of libgcc.
# It is also possible to strip target libraries by installing them with
# make target `install-strip-target`. However this target doesn't strip
# libgcc.a.
for f in $files ; do
$objcopy -R .comment -R .note \
-R .debug_info -R .debug_aranges -R .debug_pubnames \
-R .debug_pubtypes -R .debug_abbrev -R .debug_line -R .debug_str \
-R .debug_ranges -R .debug_loc \
$f >> "$logfile" 2>&1 || true
done
fi
echo "DONE ELF32: $(date)" | tee -a "$logfile"
# vim: noexpandtab sts=4 ts=8 textwidth=100: