merge mainline changes
[helenos.git] / tools / toolchain.sh
blob17123afe4a451817ff9cfee6f831fe7da9fbfad7
1 #! /bin/bash
4 # Copyright (c) 2009 Martin Decky
5 # All rights reserved.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
11 # - Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # - Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # - The name of the author may not be used to endorse or promote products
17 # derived from this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 GMP_MAIN=<<EOF
32 #define GCC_GMP_VERSION_NUM(a, b, c) \
33 (((a) << 16L) | ((b) << 8) | (c))
35 #define GCC_GMP_VERSION \
36 GCC_GMP_VERSION_NUM(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, __GNU_MP_VERSION_PATCHLEVEL)
38 #if GCC_GMP_VERSION < GCC_GMP_VERSION_NUM(4, 3, 2)
39 choke me
40 #endif
41 EOF
43 MPFR_MAIN=<<EOF
44 #if MPFR_VERSION < MPFR_VERSION_NUM(2, 4, 2)
45 choke me
46 #endif
47 EOF
49 MPC_MAIN=<<EOF
50 #if MPC_VERSION < MPC_VERSION_NUM(0, 8, 1)
51 choke me
52 #endif
53 EOF
55 BINUTILS_VERSION="2.23.1"
56 BINUTILS_RELEASE=""
57 BINUTILS_PATCHES="toolchain-binutils-2.23.1.patch"
58 GCC_VERSION="4.8.1"
59 GCC_PATCHES="toolchain-gcc-4.8.1-targets.patch toolchain-gcc-4.8.1-headers.patch"
60 GDB_VERSION="7.6.1"
61 GDB_PATCHES="toolchain-gdb-7.6.1.patch"
63 BASEDIR="`pwd`"
64 SRCDIR="$(readlink -f $(dirname "$0"))"
65 BINUTILS="binutils-${BINUTILS_VERSION}${BINUTILS_RELEASE}.tar.bz2"
66 GCC="gcc-${GCC_VERSION}.tar.bz2"
67 GDB="gdb-${GDB_VERSION}.tar.bz2"
69 REAL_INSTALL=true
70 USE_HELENOS_TARGET=false
71 INSTALL_DIR="${BASEDIR}/PKG"
74 # Check if the library described in the argument
75 # exists and has acceptable version.
77 check_dependency() {
78 DEPENDENCY="$1"
79 HEADER="$2"
80 BODY="$3"
82 FNAME="/tmp/conftest-$$"
84 echo "#include ${HEADER}" > "${FNAME}.c"
85 echo >> "${FNAME}.c"
86 echo "int main()" >> "${FNAME}.c"
87 echo "{" >> "${FNAME}.c"
88 echo "${BODY}" >> "${FNAME}.c"
89 echo " return 0;" >> "${FNAME}.c"
90 echo "}" >> "${FNAME}.c"
92 cc -c -o "${FNAME}.o" "${FNAME}.c" 2> "${FNAME}.log"
93 RC="$?"
95 if [ "$RC" -ne "0" ] ; then
96 echo " ${DEPENDENCY} not found, too old or compiler error."
97 echo " Please recheck manually the source file \"${FNAME}.c\"."
98 echo " The compilation of the toolchain is probably going to fail,"
99 echo " you have been warned."
100 echo
101 echo " ===== Compiler output ====="
102 cat "${FNAME}.log"
103 echo " ==========================="
104 echo
105 else
106 echo " ${DEPENDENCY} found"
107 rm -f "${FNAME}.log" "${FNAME}.o" "${FNAME}.c"
111 check_dependecies() {
112 echo ">>> Basic dependency check"
113 check_dependency "GMP" "<gmp.h>" "${GMP_MAIN}"
114 check_dependency "MPFR" "<mpfr.h>" "${MPFR_MAIN}"
115 check_dependency "MPC" "<mpc.h>" "${MPC_MAIN}"
116 echo
119 check_error() {
120 if [ "$1" -ne "0" ]; then
121 echo
122 echo "Script failed: $2"
124 exit 1
128 check_md5() {
129 FILE="$1"
130 SUM="$2"
132 COMPUTED="`md5sum "${FILE}" | cut -d' ' -f1`"
133 if [ "${SUM}" != "${COMPUTED}" ] ; then
134 echo
135 echo "Checksum of ${FILE} does not match."
137 exit 2
141 show_usage() {
142 echo "Cross-compiler toolchain build script"
143 echo
144 echo "Syntax:"
145 echo " $0 [--no-install] [--helenos-target] <platform>"
146 echo
147 echo "Possible target platforms are:"
148 echo " amd64 AMD64 (x86-64, x64)"
149 echo " arm32 ARM"
150 echo " ia32 IA-32 (x86, i386)"
151 echo " ia64 IA-64 (Itanium)"
152 echo " mips32 MIPS little-endian 32b"
153 echo " mips32eb MIPS big-endian 32b"
154 echo " mips64 MIPS little-endian 64b"
155 echo " ppc32 32-bit PowerPC"
156 echo " ppc64 64-bit PowerPC"
157 echo " sparc32 SPARC V8"
158 echo " sparc64 SPARC V9"
159 echo " all build all targets"
160 echo " parallel same as 'all', but all in parallel"
161 echo " 2-way same as 'all', but 2-way parallel"
162 echo
163 echo "The toolchain is installed into directory specified by the"
164 echo "CROSS_PREFIX environment variable. If the variable is not"
165 echo "defined, /usr/local/cross/ is used as default."
166 echo
167 echo "If --no-install is present, the toolchain still uses the"
168 echo "CROSS_PREFIX as the target directory but the installation"
169 echo "copies the files into PKG/ subdirectory without affecting"
170 echo "the actual root file system. That is only useful if you do"
171 echo "not want to run the script under the super user."
172 echo
173 echo "The --helenos-target will build HelenOS-specific toolchain"
174 echo "(i.e. it will use *-helenos-* triplet instead of *-linux-*)."
175 echo "This toolchain is installed into /usr/local/cross-helenos by"
176 echo "default. The settings can be changed by setting environment"
177 echo "variable CROSS_HELENOS_PREFIX."
178 echo "Using the HelenOS-specific toolchain is still an experimental"
179 echo "feature that is not fully supported."
180 echo
182 exit 3
185 change_title() {
186 echo -en "\e]0;$1\a"
189 show_countdown() {
190 TM="$1"
192 if [ "${TM}" -eq 0 ] ; then
193 echo
194 return 0
197 echo -n "${TM} "
198 change_title "${TM}"
199 sleep 1
201 TM="`expr "${TM}" - 1`"
202 show_countdown "${TM}"
205 show_dependencies() {
206 echo "IMPORTANT NOTICE:"
207 echo
208 echo "For a successful compilation and use of the cross-compiler"
209 echo "toolchain you need at least the following dependencies."
210 echo
211 echo "Please make sure that the dependencies are present in your"
212 echo "system. Otherwise the compilation process might fail after"
213 echo "a few seconds or minutes."
214 echo
215 echo " - SED, AWK, Flex, Bison, gzip, bzip2, Bourne Shell"
216 echo " - gettext, zlib, Texinfo, libelf, libgomp"
217 echo " - terminfo"
218 echo " - GNU Multiple Precision Library (GMP)"
219 echo " - GNU Make"
220 echo " - GNU tar"
221 echo " - GNU Coreutils"
222 echo " - GNU Sharutils"
223 echo " - MPFR"
224 echo " - MPC"
225 echo " - Parma Polyhedra Library (PPL)"
226 echo " - ClooG-PPL"
227 echo " - native C compiler, assembler and linker"
228 echo " - native C library with headers"
229 echo
232 download_fetch() {
233 SOURCE="$1"
234 FILE="$2"
235 CHECKSUM="$3"
237 if [ ! -f "${FILE}" ]; then
238 change_title "Downloading ${FILE}"
239 wget -c "${SOURCE}${FILE}"
240 check_error $? "Error downloading ${FILE}."
243 check_md5 "${FILE}" "${CHECKSUM}"
246 source_check() {
247 FILE="$1"
249 if [ ! -f "${FILE}" ]; then
250 echo
251 echo "File ${FILE} not found."
253 exit 4
257 cleanup_dir() {
258 DIR="$1"
260 if [ -d "${DIR}" ]; then
261 change_title "Removing ${DIR}"
262 echo " >>> Removing ${DIR}"
263 rm -fr "${DIR}"
267 create_dir() {
268 DIR="$1"
269 DESC="$2"
271 change_title "Creating ${DESC}"
272 echo ">>> Creating ${DESC}"
274 mkdir -p "${DIR}"
275 test -d "${DIR}"
276 check_error $? "Unable to create ${DIR}."
279 check_dirs() {
280 OUTSIDE="$1"
281 BASE="$2"
282 ORIGINAL="`pwd`"
284 cd "${OUTSIDE}"
285 check_error $? "Unable to change directory to ${OUTSIDE}."
286 ABS_OUTSIDE="`pwd`"
288 cd "${BASE}"
289 check_error $? "Unable to change directory to ${BASE}."
290 ABS_BASE="`pwd`"
292 cd "${ORIGINAL}"
293 check_error $? "Unable to change directory to ${ORIGINAL}."
295 BASE_LEN="${#ABS_BASE}"
296 OUTSIDE_TRIM="${ABS_OUTSIDE:0:${BASE_LEN}}"
298 if [ "${OUTSIDE_TRIM}" == "${ABS_BASE}" ] ; then
299 echo
300 echo "CROSS_PREFIX cannot reside within the working directory."
302 exit 5
306 unpack_tarball() {
307 FILE="$1"
308 DESC="$2"
310 change_title "Unpacking ${DESC}"
311 echo " >>> Unpacking ${DESC}"
313 tar -xjf "${FILE}"
314 check_error $? "Error unpacking ${DESC}."
317 patch_sources() {
318 PATCH_FILE="$1"
319 PATCH_STRIP="$2"
320 DESC="$3"
322 change_title "Patching ${DESC}"
323 echo " >>> Patching ${DESC} with ${PATCH_FILE}"
325 patch -t "-p${PATCH_STRIP}" <"$PATCH_FILE"
326 check_error $? "Error patching ${DESC}."
329 prepare() {
330 show_dependencies
331 check_dependecies
332 show_countdown 10
334 BINUTILS_SOURCE="ftp://ftp.gnu.org/gnu/binutils/"
335 GCC_SOURCE="ftp://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/"
336 GDB_SOURCE="ftp://ftp.gnu.org/gnu/gdb/"
338 download_fetch "${BINUTILS_SOURCE}" "${BINUTILS}" "33adb18c3048d057ac58d07a3f1adb38"
339 download_fetch "${GCC_SOURCE}" "${GCC}" "3b2386c114cd74185aa3754b58a79304"
340 download_fetch "${GDB_SOURCE}" "${GDB}" "fbc4dab4181e6e9937075b43a4ce2732"
343 set_target_from_platform() {
344 case "$1" in
345 "amd64")
346 LINUX_TARGET="amd64-linux-gnu"
347 HELENOS_TARGET="amd64-helenos"
349 "arm32")
350 LINUX_TARGET="arm-linux-gnueabi"
351 HELENOS_TARGET="arm-helenos-gnueabi"
353 "ia32")
354 LINUX_TARGET="i686-pc-linux-gnu"
355 HELENOS_TARGET="i686-pc-helenos"
357 "ia64")
358 LINUX_TARGET="ia64-pc-linux-gnu"
359 HELENOS_TARGET="ia64-pc-helenos"
361 "mips32")
362 LINUX_TARGET="mipsel-linux-gnu"
363 HELENOS_TARGET="mipsel-helenos"
365 "mips32eb")
366 LINUX_TARGET="mips-linux-gnu"
367 HELENOS_TARGET="mips-helenos"
369 "mips64")
370 LINUX_TARGET="mips64el-linux-gnu"
371 HELENOS_TARGET="mips64el-helenos"
373 "ppc32")
374 LINUX_TARGET="ppc-linux-gnu"
375 HELENOS_TARGET="ppc-helenos"
377 "ppc64")
378 LINUX_TARGET="ppc64-linux-gnu"
379 HELENOS_TARGET="ppc64-helenos"
381 "sparc32")
382 LINUX_TARGET="sparc-leon3-linux-gnu"
383 HELENOS_TARGET="sparc-leon3-helenos"
385 "sparc64")
386 LINUX_TARGET="sparc64-linux-gnu"
387 HELENOS_TARGET="sparc64-helenos"
390 check_error 1 "No target known for $1."
392 esac
395 build_target() {
396 PLATFORM="$1"
397 # This sets the *_TARGET variables
398 set_target_from_platform "$PLATFORM"
399 if $USE_HELENOS_TARGET; then
400 TARGET="$HELENOS_TARGET"
401 else
402 TARGET="$LINUX_TARGET"
405 WORKDIR="${BASEDIR}/${PLATFORM}"
406 BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
407 GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
408 OBJDIR="${WORKDIR}/gcc-obj"
409 GDBDIR="${WORKDIR}/gdb-${GDB_VERSION}"
411 if [ -z "${CROSS_PREFIX}" ] ; then
412 CROSS_PREFIX="/usr/local/cross"
414 if [ -z "${CROSS_HELENOS_PREFIX}" ] ; then
415 CROSS_HELENOS_PREFIX="/usr/local/cross-helenos"
418 if $USE_HELENOS_TARGET; then
419 PREFIX="${CROSS_HELENOS_PREFIX}/${PLATFORM}"
420 else
421 PREFIX="${CROSS_PREFIX}/${PLATFORM}"
424 echo ">>> Downloading tarballs"
425 source_check "${BASEDIR}/${BINUTILS}"
426 source_check "${BASEDIR}/${GCC}"
427 source_check "${BASEDIR}/${GDB}"
429 echo ">>> Removing previous content"
430 $REAL_INSTALL && cleanup_dir "${PREFIX}"
431 cleanup_dir "${WORKDIR}"
433 $REAL_INSTALL && create_dir "${PREFIX}" "destination directory"
434 create_dir "${OBJDIR}" "GCC object directory"
436 check_dirs "${PREFIX}" "${WORKDIR}"
438 echo ">>> Unpacking tarballs"
439 cd "${WORKDIR}"
440 check_error $? "Change directory failed."
442 unpack_tarball "${BASEDIR}/${BINUTILS}" "binutils"
443 unpack_tarball "${BASEDIR}/${GCC}" "GCC"
444 unpack_tarball "${BASEDIR}/${GDB}" "GDB"
446 echo ">>> Applying patches"
447 for p in $BINUTILS_PATCHES; do
448 patch_sources "${SRCDIR}/${p}" 0 "binutils"
449 done
450 for p in $GCC_PATCHES; do
451 patch_sources "${SRCDIR}/${p}" 0 "GCC"
452 done
453 for p in $GDB_PATCHES; do
454 patch_sources "${SRCDIR}/${p}" 0 "GDB"
455 done
457 echo ">>> Processing binutils (${PLATFORM})"
458 cd "${BINUTILSDIR}"
459 check_error $? "Change directory failed."
461 change_title "binutils: configure (${PLATFORM})"
462 CFLAGS=-Wno-error ./configure \
463 "--target=${TARGET}" \
464 "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" \
465 --disable-nls --disable-werror
466 check_error $? "Error configuring binutils."
468 change_title "binutils: make (${PLATFORM})"
469 make all
470 check_error $? "Error compiling binutils."
472 change_title "binutils: install (${PLATFORM})"
473 if $REAL_INSTALL; then
474 make install
475 else
476 make install "DESTDIR=${INSTALL_DIR}"
478 check_error $? "Error installing binutils."
481 echo ">>> Processing GCC (${PLATFORM})"
482 cd "${OBJDIR}"
483 check_error $? "Change directory failed."
485 change_title "GCC: configure (${PLATFORM})"
486 PATH="$PATH:${INSTALL_DIR}/${PREFIX}/bin" "${GCCDIR}/configure" \
487 "--target=${TARGET}" \
488 "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" \
489 --with-gnu-as --with-gnu-ld --disable-nls --disable-threads \
490 --enable-languages=c,objc,c++,obj-c++ \
491 --disable-multilib --disable-libgcj --without-headers \
492 --disable-shared --enable-lto --disable-werror
493 check_error $? "Error configuring GCC."
495 change_title "GCC: make (${PLATFORM})"
496 PATH="${PATH}:${PREFIX}/bin:${INSTALL_DIR}/${PREFIX}/bin" make all-gcc
497 check_error $? "Error compiling GCC."
499 change_title "GCC: install (${PLATFORM})"
500 if $REAL_INSTALL; then
501 PATH="${PATH}:${PREFIX}/bin" make install-gcc
502 else
503 PATH="${PATH}:${INSTALL_DIR}/${PREFIX}/bin" make install-gcc "DESTDIR=${INSTALL_DIR}"
505 check_error $? "Error installing GCC."
508 echo ">>> Processing GDB (${PLATFORM})"
509 cd "${GDBDIR}"
510 check_error $? "Change directory failed."
512 change_title "GDB: configure (${PLATFORM})"
513 PATH="$PATH:${INSTALL_DIR}/${PREFIX}/bin" ./configure \
514 "--target=${TARGET}" \
515 "--prefix=${PREFIX}" "--program-prefix=${TARGET}-"
516 check_error $? "Error configuring GDB."
518 change_title "GDB: make (${PLATFORM})"
519 PATH="${PATH}:${PREFIX}/bin:${INSTALL_DIR}/${PREFIX}/bin" make all
520 check_error $? "Error compiling GDB."
522 change_title "GDB: make (${PLATFORM})"
523 if $REAL_INSTALL; then
524 PATH="${PATH}:${PREFIX}/bin" make install
525 else
526 PATH="${PATH}:${INSTALL_DIR}/${PREFIX}/bin" make install "DESTDIR=${INSTALL_DIR}"
528 check_error $? "Error installing GDB."
531 cd "${BASEDIR}"
532 check_error $? "Change directory failed."
534 echo ">>> Cleaning up"
535 cleanup_dir "${WORKDIR}"
537 echo
538 echo ">>> Cross-compiler for ${TARGET} installed."
541 while [ "$#" -gt 1 ]; do
542 case "$1" in
543 --no-install)
544 REAL_INSTALL=false
545 shift
547 --helenos-target)
548 USE_HELENOS_TARGET=true
549 shift
552 show_usage
554 esac
555 done
557 if [ "$#" -lt "1" ]; then
558 show_usage
561 case "$1" in
562 amd64|arm32|ia32|ia64|mips32|mips32eb|mips64|ppc32|ppc64|sparc32|sparc64)
563 prepare
564 build_target "$1"
566 "all")
567 prepare
568 build_target "amd64"
569 build_target "arm32"
570 build_target "ia32"
571 build_target "ia64"
572 build_target "mips32"
573 build_target "mips32eb"
574 build_target "mips64"
575 build_target "ppc32"
576 build_target "ppc64"
577 build_target "sparc32"
578 build_target "sparc64"
580 "parallel")
581 prepare
582 build_target "amd64" &
583 build_target "arm32" &
584 build_target "ia32" &
585 build_target "ia64" &
586 build_target "mips32" &
587 build_target "mips32eb" &
588 build_target "mips64" &
589 build_target "ppc32" &
590 build_target "ppc64" &
591 build_target "sparc32" &
592 build_target "sparc64" &
593 wait
595 "2-way")
596 prepare
597 build_target "amd64" &
598 build_target "arm32" &
599 wait
601 build_target "ia32" &
602 build_target "ia64" &
603 wait
605 build_target "mips32" &
606 build_target "mips32eb" &
607 wait
609 build_target "mips64" &
610 build_target "ppc32" &
611 wait
613 build_target "ppc64" &
614 build_target "sparc32" &
615 wait
617 build_target "sparc64" &
618 wait
621 show_usage
623 esac