Merge pull request #3 from nebulabox/updategitignore
[helenos.git] / tools / toolchain.sh
blob8e366c9fc5234584394775dee30e686168a69cfd
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 ISL_MAIN=<<EOF
56 isl_ctx_get_max_operations (isl_ctx_alloc ());
57 EOF
59 BINUTILS_VERSION="2.28"
60 BINUTILS_RELEASE=""
61 ## BINUTILS_PATCHES="toolchain-binutils-2.23.1.patch"
62 GCC_VERSION="7.1.0"
63 ## GCC_PATCHES="toolchain-gcc-4.8.1-targets.patch toolchain-gcc-4.8.1-headers.patch"
64 GDB_VERSION="7.12.1"
65 ## GDB_PATCHES="toolchain-gdb-7.6.1.patch"
66 ISL_VERSION="0.18"
68 BASEDIR="`pwd`"
69 SRCDIR="$(readlink -f $(dirname "$0"))"
70 BINUTILS="binutils-${BINUTILS_VERSION}${BINUTILS_RELEASE}.tar.bz2"
71 GCC="gcc-${GCC_VERSION}.tar.bz2"
72 GDB="gdb-${GDB_VERSION}.tar.gz"
73 ISL="isl-${ISL_VERSION}.tar.bz2"
75 REAL_INSTALL=true
76 USE_HELENOS_TARGET=false
77 BUILD_ISL=false
80 # Check if the library described in the argument
81 # exists and has acceptable version.
83 check_dependency() {
84 DEPENDENCY="$1"
85 HEADER="$2"
86 BODY="$3"
88 FNAME="/tmp/conftest-$$"
90 echo "#include ${HEADER}" > "${FNAME}.c"
91 echo >> "${FNAME}.c"
92 echo "int main()" >> "${FNAME}.c"
93 echo "{" >> "${FNAME}.c"
94 echo "${BODY}" >> "${FNAME}.c"
95 echo " return 0;" >> "${FNAME}.c"
96 echo "}" >> "${FNAME}.c"
98 cc $CFLAGS -c -o "${FNAME}.o" "${FNAME}.c" 2> "${FNAME}.log"
99 RC="$?"
101 if [ "$RC" -ne "0" ] ; then
102 if [ "${DEPENDENCY}" == "isl" ]; then
103 BUILD_ISL=true
105 echo " isl not found. Will be downloaded and built with GCC."
106 else
107 echo " ${DEPENDENCY} not found, too old or compiler error."
108 echo " Please recheck manually the source file \"${FNAME}.c\"."
109 echo " The compilation of the toolchain is probably going to fail,"
110 echo " you have been warned."
111 echo
112 echo " ===== Compiler output ====="
113 cat "${FNAME}.log"
114 echo " ==========================="
115 echo
117 else
118 echo " ${DEPENDENCY} found"
119 rm -f "${FNAME}.log" "${FNAME}.o" "${FNAME}.c"
123 check_dependecies() {
124 echo ">>> Basic dependency check"
125 check_dependency "GMP" "<gmp.h>" "${GMP_MAIN}"
126 check_dependency "MPFR" "<mpfr.h>" "${MPFR_MAIN}"
127 check_dependency "MPC" "<mpc.h>" "${MPC_MAIN}"
128 check_dependency "isl" "<isl/ctx.h>" "${ISL_MAIN}"
129 echo
132 check_error() {
133 if [ "$1" -ne "0" ] ; then
134 echo
135 echo "Script failed: $2"
137 exit 1
141 check_md5() {
142 FILE="$1"
143 SUM="$2"
145 COMPUTED="`md5sum "${FILE}" | cut -d' ' -f1`"
146 if [ "${SUM}" != "${COMPUTED}" ] ; then
147 echo
148 echo "Checksum of ${FILE} does not match."
150 exit 2
154 show_usage() {
155 echo "Cross-compiler toolchain build script"
156 echo
157 echo "Syntax:"
158 echo " $0 [--no-install] [--helenos-target] <platform>"
159 echo
160 echo "Possible target platforms are:"
161 echo " amd64 AMD64 (x86-64, x64)"
162 echo " arm32 ARM 32b"
163 echo " ia32 IA-32 (x86, i386)"
164 echo " ia64 IA-64 (Itanium)"
165 echo " mips32 MIPS little-endian 32b"
166 echo " mips32eb MIPS big-endian 32b"
167 echo " mips64 MIPS little-endian 64b"
168 echo " ppc32 PowerPC 32b"
169 echo " ppc64 PowerPC 64v"
170 echo " riscv64 RISC-V 64b"
171 echo " sparc64 SPARC V9"
172 echo " all build all targets"
173 echo " essential build only targets currently needed for HelenOS development"
174 echo " parallel same as 'all', but all in parallel"
175 echo " 2-way same as 'all', but 2-way parallel"
176 echo
177 echo "The toolchain is installed into directory specified by the"
178 echo "CROSS_PREFIX environment variable. If the variable is not"
179 echo "defined, /usr/local/cross/ is used as default."
180 echo
181 echo "If --no-install is present, the toolchain still uses the"
182 echo "CROSS_PREFIX as the target directory but the installation"
183 echo "copies the files into PKG/ subdirectory without affecting"
184 echo "the actual root file system. That is only useful if you do"
185 echo "not want to run the script under the super user."
186 echo
187 echo "The --helenos-target will build HelenOS-specific toolchain"
188 echo "(i.e. it will use *-helenos-* triplet instead of *-linux-*)."
189 echo "This toolchain is installed into /usr/local/cross-helenos by"
190 echo "default. The settings can be changed by setting environment"
191 echo "variable CROSS_HELENOS_PREFIX."
192 echo "Using the HelenOS-specific toolchain is still an experimental"
193 echo "feature that is not fully supported."
194 echo
196 exit 3
199 change_title() {
200 echo -en "\e]0;$1\a"
203 show_countdown() {
204 TM="$1"
206 if [ "${TM}" -eq 0 ] ; then
207 echo
208 return 0
211 echo -n "${TM} "
212 change_title "${TM}"
213 sleep 1
215 TM="`expr "${TM}" - 1`"
216 show_countdown "${TM}"
219 show_dependencies() {
220 echo "IMPORTANT NOTICE:"
221 echo
222 echo "For a successful compilation and use of the cross-compiler"
223 echo "toolchain you need at least the following dependencies."
224 echo
225 echo "Please make sure that the dependencies are present in your"
226 echo "system. Otherwise the compilation process might fail after"
227 echo "a few seconds or minutes."
228 echo
229 echo " - SED, AWK, Flex, Bison, gzip, bzip2, Bourne Shell"
230 echo " - gettext, zlib, Texinfo, libelf, libgomp"
231 echo " - GNU Make, Coreutils, Sharutils, tar"
232 echo " - GNU Multiple Precision Library (GMP)"
233 echo " - MPFR"
234 echo " - MPC"
235 echo " - integer point manipulation library (isl)"
236 echo " - native C and C++ compiler, assembler and linker"
237 echo " - native C and C++ standard library with headers"
238 echo
241 download_fetch() {
242 SOURCE="$1"
243 FILE="$2"
244 CHECKSUM="$3"
246 if [ ! -f "${FILE}" ] ; then
247 change_title "Downloading ${FILE}"
248 wget -c "${SOURCE}${FILE}" -O "${FILE}".part
249 check_error $? "Error downloading ${FILE}."
251 mv "${FILE}".part "${FILE}"
254 check_md5 "${FILE}" "${CHECKSUM}"
257 source_check() {
258 FILE="$1"
260 if [ ! -f "${FILE}" ] ; then
261 echo
262 echo "File ${FILE} not found."
264 exit 4
268 cleanup_dir() {
269 DIR="$1"
271 if [ -d "${DIR}" ] ; then
272 change_title "Removing ${DIR}"
273 echo " >>> Removing ${DIR}"
274 rm -fr "${DIR}"
278 create_dir() {
279 DIR="$1"
280 DESC="$2"
282 change_title "Creating ${DESC}"
283 echo ">>> Creating ${DESC}"
285 mkdir -p "${DIR}"
286 test -d "${DIR}"
287 check_error $? "Unable to create ${DIR}."
290 check_dirs() {
291 OUTSIDE="$1"
292 BASE="$2"
293 ORIGINAL="`pwd`"
295 mkdir -p "${OUTSIDE}"
297 cd "${OUTSIDE}"
298 check_error $? "Unable to change directory to ${OUTSIDE}."
299 ABS_OUTSIDE="`pwd`"
301 cd "${BASE}"
302 check_error $? "Unable to change directory to ${BASE}."
303 ABS_BASE="`pwd`"
305 cd "${ORIGINAL}"
306 check_error $? "Unable to change directory to ${ORIGINAL}."
308 BASE_LEN="${#ABS_BASE}"
309 OUTSIDE_TRIM="${ABS_OUTSIDE:0:${BASE_LEN}}"
311 if [ "${OUTSIDE_TRIM}" == "${ABS_BASE}" ] ; then
312 echo
313 echo "CROSS_PREFIX cannot reside within the working directory."
315 exit 5
319 unpack_tarball() {
320 FILE="$1"
321 DESC="$2"
323 change_title "Unpacking ${DESC}"
324 echo " >>> Unpacking ${DESC}"
326 case "${FILE}" in
327 *.gz)
328 tar -xzf "${FILE}"
330 *.xz)
331 tar -xJf "${FILE}"
333 *.bz2)
334 tar -xjf "${FILE}"
337 check_error 1 "Don't know how to unpack ${DESC}."
339 esac
340 check_error $? "Error unpacking ${DESC}."
343 patch_sources() {
344 PATCH_FILE="$1"
345 PATCH_STRIP="$2"
346 DESC="$3"
348 change_title "Patching ${DESC}"
349 echo " >>> Patching ${DESC} with ${PATCH_FILE}"
351 patch -t "-p${PATCH_STRIP}" <"$PATCH_FILE"
352 check_error $? "Error patching ${DESC}."
355 prepare() {
356 show_dependencies
357 check_dependecies
358 show_countdown 10
360 BINUTILS_SOURCE="ftp://ftp.gnu.org/gnu/binutils/"
361 GCC_SOURCE="ftp://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/"
362 GDB_SOURCE="ftp://ftp.gnu.org/gnu/gdb/"
363 ISL_SOURCE="http://isl.gforge.inria.fr/"
365 download_fetch "${BINUTILS_SOURCE}" "${BINUTILS}" "9e8340c96626b469a603c15c9d843727"
366 download_fetch "${GCC_SOURCE}" "${GCC}" "6bf56a2bca9dac9dbbf8e8d1036964a8"
367 download_fetch "${GDB_SOURCE}" "${GDB}" "06c8f40521ed65fe36ebc2be29b56942"
369 if $BUILD_ISL ; then
370 download_fetch "${ISL_SOURCE}" "${ISL}" "11436d6b205e516635b666090b94ab32"
374 set_target_from_platform() {
375 case "$1" in
376 "amd64")
377 LINUX_TARGET="amd64-unknown-elf"
378 HELENOS_TARGET="amd64-helenos"
380 "arm32")
381 LINUX_TARGET="arm-linux-gnueabi"
382 HELENOS_TARGET="arm-helenos-gnueabi"
384 "ia32")
385 LINUX_TARGET="i686-pc-linux-gnu"
386 HELENOS_TARGET="i686-pc-helenos"
388 "ia64")
389 LINUX_TARGET="ia64-pc-linux-gnu"
390 HELENOS_TARGET="ia64-pc-helenos"
392 "mips32")
393 LINUX_TARGET="mipsel-linux-gnu"
394 HELENOS_TARGET="mipsel-helenos"
396 "mips32eb")
397 LINUX_TARGET="mips-linux-gnu"
398 HELENOS_TARGET="mips-helenos"
400 "mips64")
401 LINUX_TARGET="mips64el-linux-gnu"
402 HELENOS_TARGET="mips64el-helenos"
404 "ppc32")
405 LINUX_TARGET="ppc-linux-gnu"
406 HELENOS_TARGET="ppc-helenos"
408 "ppc64")
409 LINUX_TARGET="ppc64-linux-gnu"
410 HELENOS_TARGET="ppc64-helenos"
412 "riscv64")
413 LINUX_TARGET="riscv64-unknown-linux-gnu"
414 HELENOS_TARGET="riscv64-helenos"
416 "sparc64")
417 LINUX_TARGET="sparc64-linux-gnu"
418 HELENOS_TARGET="sparc64-helenos"
421 check_error 1 "No target known for $1."
423 esac
426 build_target() {
427 PLATFORM="$1"
429 # This sets the *_TARGET variables
430 set_target_from_platform "$PLATFORM"
431 if $USE_HELENOS_TARGET ; then
432 TARGET="$HELENOS_TARGET"
433 else
434 TARGET="$LINUX_TARGET"
437 WORKDIR="${BASEDIR}/${TARGET}"
438 INSTALL_DIR="${WORKDIR}/PKG"
439 BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
440 GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
441 ISLDIR="${WORKDIR}/isl-${ISL_VERSION}"
442 OBJDIR="${WORKDIR}/gcc-obj"
443 GDBDIR="${WORKDIR}/gdb-${GDB_VERSION}"
445 if [ -z "${CROSS_PREFIX}" ] ; then
446 CROSS_PREFIX="/usr/local/cross"
449 PREFIX="${CROSS_PREFIX}/${TARGET}"
451 echo ">>> Downloading tarballs"
452 source_check "${BASEDIR}/${BINUTILS}"
453 source_check "${BASEDIR}/${GCC}"
454 source_check "${BASEDIR}/${GDB}"
455 if $BUILD_ISL ; then
456 source_check "${BASEDIR}/${ISL}"
459 echo ">>> Removing previous content"
460 cleanup_dir "${WORKDIR}"
462 create_dir "${OBJDIR}" "GCC object directory"
464 check_dirs "${PREFIX}" "${WORKDIR}"
466 echo ">>> Unpacking tarballs"
467 cd "${WORKDIR}"
468 check_error $? "Change directory failed."
470 unpack_tarball "${BASEDIR}/${BINUTILS}" "binutils"
471 unpack_tarball "${BASEDIR}/${GCC}" "GCC"
472 unpack_tarball "${BASEDIR}/${GDB}" "GDB"
473 if $BUILD_ISL ; then
474 unpack_tarball "${BASEDIR}/${ISL}" "isl"
475 mv "${ISLDIR}" "${GCCDIR}"/isl
478 echo ">>> Applying patches"
479 for p in $BINUTILS_PATCHES ; do
480 patch_sources "${SRCDIR}/${p}" 0 "binutils"
481 done
482 for p in $GCC_PATCHES ; do
483 patch_sources "${SRCDIR}/${p}" 0 "GCC"
484 done
485 for p in $GDB_PATCHES ; do
486 patch_sources "${SRCDIR}/${p}" 0 "GDB"
487 done
489 echo ">>> Processing binutils (${PLATFORM})"
490 cd "${BINUTILSDIR}"
491 check_error $? "Change directory failed."
493 change_title "binutils: configure (${PLATFORM})"
494 CFLAGS=-Wno-error ./configure \
495 "--target=${TARGET}" \
496 "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" \
497 --disable-nls --disable-werror --enable-gold \
498 --enable-deterministic-archives
499 check_error $? "Error configuring binutils."
501 change_title "binutils: make (${PLATFORM})"
502 make all
503 check_error $? "Error compiling binutils."
505 change_title "binutils: install (${PLATFORM})"
506 make install "DESTDIR=${INSTALL_DIR}"
507 check_error $? "Error installing binutils."
510 echo ">>> Processing GCC (${PLATFORM})"
511 cd "${OBJDIR}"
512 check_error $? "Change directory failed."
514 change_title "GCC: configure (${PLATFORM})"
515 PATH="$PATH:${INSTALL_DIR}/${PREFIX}/bin" "${GCCDIR}/configure" \
516 "--target=${TARGET}" \
517 "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" \
518 --with-gnu-as --with-gnu-ld --disable-nls --disable-threads \
519 --enable-languages=c,objc,c++,obj-c++ \
520 --disable-multilib --disable-libgcj --without-headers \
521 --disable-shared --enable-lto --disable-werror
522 check_error $? "Error configuring GCC."
524 change_title "GCC: make (${PLATFORM})"
525 PATH="${PATH}:${PREFIX}/bin:${INSTALL_DIR}/${PREFIX}/bin" make all-gcc
526 check_error $? "Error compiling GCC."
528 change_title "GCC: install (${PLATFORM})"
529 PATH="${PATH}:${INSTALL_DIR}/${PREFIX}/bin" make install-gcc "DESTDIR=${INSTALL_DIR}"
530 check_error $? "Error installing GCC."
533 # No GDB support for RISC-V so far
534 if [ "$PLATFORM" != "riscv64" ] ; then
535 echo ">>> Processing GDB (${PLATFORM})"
536 cd "${GDBDIR}"
537 check_error $? "Change directory failed."
539 change_title "GDB: configure (${PLATFORM})"
540 PATH="$PATH:${INSTALL_DIR}/${PREFIX}/bin" ./configure \
541 "--target=${TARGET}" \
542 "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" \
543 --enable-werror=no --without-guile
544 check_error $? "Error configuring GDB."
546 change_title "GDB: make (${PLATFORM})"
547 PATH="${PATH}:${PREFIX}/bin:${INSTALL_DIR}/${PREFIX}/bin" make all
548 check_error $? "Error compiling GDB."
550 change_title "GDB: make (${PLATFORM})"
551 PATH="${PATH}:${INSTALL_DIR}/${PREFIX}/bin" make install "DESTDIR=${INSTALL_DIR}"
552 check_error $? "Error installing GDB."
555 # Symlink clang and lld to the install path.
556 CLANG=`which clang 2> /dev/null || echo "/usr/bin/clang"`
557 LLD=`which ld.lld 2> /dev/null || echo "/usr/bin/ld.lld"`
559 ln -s $CLANG "${INSTALL_DIR}/${PREFIX}/bin/${TARGET}-clang"
560 ln -s $LLD "${INSTALL_DIR}/${PREFIX}/bin/${TARGET}-ld.lld"
562 if $REAL_INSTALL ; then
563 echo ">>> Moving to the destination directory."
564 cleanup_dir "${PREFIX}"
565 echo mv "${INSTALL_DIR}/${PREFIX}" "${PREFIX}"
566 mv "${INSTALL_DIR}/${PREFIX}" "${PREFIX}"
569 cd "${BASEDIR}"
570 check_error $? "Change directory failed."
572 echo ">>> Cleaning up"
573 cleanup_dir "${WORKDIR}"
575 echo
576 echo ">>> Cross-compiler for ${TARGET} installed."
579 while [ "$#" -gt 1 ] ; do
580 case "$1" in
581 --no-install)
582 REAL_INSTALL=false
583 shift
585 --helenos-target)
586 USE_HELENOS_TARGET=true
587 shift
590 show_usage
592 esac
593 done
595 if [ "$#" -lt "1" ] ; then
596 show_usage
599 case "$1" in
600 amd64|arm32|ia32|ia64|mips32|mips32eb|mips64|ppc32|ppc64|riscv64|sparc64)
601 prepare
602 build_target "$1"
604 "all")
605 prepare
606 build_target "amd64"
607 build_target "arm32"
608 build_target "ia32"
609 build_target "ia64"
610 build_target "mips32"
611 build_target "mips32eb"
612 build_target "mips64"
613 build_target "ppc32"
614 build_target "ppc64"
615 build_target "riscv64"
616 build_target "sparc64"
618 "essential")
619 prepare
620 build_target "amd64"
621 build_target "arm32"
622 build_target "ia32"
623 build_target "ia64"
624 build_target "mips32"
625 build_target "mips32eb"
626 build_target "ppc32"
627 build_target "sparc64"
629 "parallel")
630 prepare
631 build_target "amd64" &
632 build_target "arm32" &
633 build_target "ia32" &
634 build_target "ia64" &
635 build_target "mips32" &
636 build_target "mips32eb" &
637 build_target "mips64" &
638 build_target "ppc32" &
639 build_target "ppc64" &
640 build_target "riscv64" &
641 build_target "sparc64" &
642 wait
644 "2-way")
645 prepare
646 build_target "amd64" &
647 build_target "arm32" &
648 wait
650 build_target "ia32" &
651 build_target "ia64" &
652 wait
654 build_target "mips32" &
655 build_target "mips32eb" &
656 wait
658 build_target "mips64" &
659 build_target "ppc32" &
660 wait
662 build_target "riscv64" &
663 build_target "ppc64" &
664 wait
666 build_target "sparc64" &
667 wait
670 show_usage
672 esac