yann@1: #!/bin/bash yann@1: # Copyright 2007 Yann E. MORIN yann@1: # Licensed under the GPL v2. See COPYING in the root of this package. yann@1: yann@1: # This is the main entry point to crosstool yann@1: # This will: yann@1: # - download, extract and patch the toolchain components yann@1: # - build and install each components in turn yann@1: # - and eventually test the resulting toolchain yann@1: yann@1: # What this file does is prepare the environment, based upon the user-choosen yann@1: # options. It also checks the existing environment for un-friendly variables, yann@1: # and checks for needed tools. It eventually calls the main build script. yann@1: yann@1: # User must set CT_TOP_DIR in is environment! yann@1: # Once we can build out-of-tree, then this will have to go. yann@1: if [ -z "${CT_TOP_DIR}" -o ! -d "${CT_TOP_DIR}" ]; then yann@1: # We don't have the functions right now, because we don't have CT_TOP_DIR. yann@1: # Do the print stuff by hand: yann@1: echo "CT_TOP_DIR not set. You must set CT_TOP_DIR to the top directory where crosstool is installed." yann@1: exit 1 yann@1: fi yann@1: yann@1: # Parse the common functions yann@1: . "${CT_TOP_DIR}/scripts/functions" yann@1: yann@1: CT_STAR_DATE=`CT_DoDate +%s%N` yann@1: CT_STAR_DATE_HUMAN=`CT_DoDate +%Y%m%d.%H%M%S` yann@1: yann@1: # Log to a temporary file until we have built our environment yann@63: CT_ACTUAL_LOG_FILE="${CT_TOP_DIR}/$$.log" yann@1: yann@1: # CT_TOP_DIR should be an absolute path. yann@1: CT_TOP_DIR="`CT_MakeAbsolutePath \"${CT_TOP_DIR}\"`" yann@1: yann@1: # Parse the configuration file yann@1: CT_TestOrAbort "Configuration file not found. Please create one." -f "${CT_TOP_DIR}/.config" yann@1: . "${CT_TOP_DIR}/.config" yann@1: yann@82: # Override the color scheme if needed yann@1: if [ "${CT_LOG_USE_COLORS}" = "y" ]; then yann@1: CT_ERROR_COLOR="${_A_NOR}${_A_BRI}${_F_RED}" yann@1: CT_WARN_COLOR="${_A_NOR}${_A_BRI}${_F_YEL}" yann@1: CT_INFO_COLOR="${_A_NOR}${_A_BRI}${_F_GRN}" yann@1: CT_EXTRA_COLOR="${_A_NOR}${_A_DIM}${_F_GRN}" yann@78: CT_DEBUG_COLOR="${_A_NOR}${_A_BRI}${_F_BLU}" yann@78: CT_ALL_COLOR="${_A_NOR}${_A_DIM}${_F_WHI}" yann@1: CT_NORMAL_COLOR="${_A_NOR}" yann@1: else yann@1: CT_ERROR_COLOR= yann@1: CT_WARN_COLOR= yann@1: CT_INFO_COLOR= yann@1: CT_EXTRA_COLOR= yann@1: CT_DEBUG_COLOR= yann@78: CT_ALL_COLOR= yann@1: CT_NORMAL_COLOR= yann@1: fi yann@1: yann@1: # Yes! We can do full logging from now on! yann@1: CT_DoLog INFO "Build started ${CT_STAR_DATE_HUMAN}" yann@1: yann@63: # renice oursleves yann@63: renice ${CT_NICE} $$ |CT_DoLog DEBUG yann@63: yann@1: # Some sanity checks in the environment and needed tools yann@1: CT_DoLog INFO "Checking environment sanity" yann@1: yann@1: # Enable known ordering of files in directory listings: yann@1: CT_Test "Crosstool-NG might not work as expected with LANG=\"${LANG}\"" -n "${LANG}" yann@1: case "${LC_COLLATE},${LC_ALL}" in yann@1: # These four combinations are known to sort files in the correct order: yann@1: fr_FR*,) ;; yann@1: en_US*,) ;; yann@1: *,fr_FR*) ;; yann@1: *,en_US*) ;; yann@1: # Anything else is destined to be borked if not gracefuly handled: yann@1: *) CT_DoLog WARN "Either LC_COLLATE=\"${LC_COLLATE}\" or LC_ALL=\"${LC_ALL}\" is not supported." yann@1: export LC_ALL=`locale -a |egrep "^(fr_FR|en_US)" |head -n 1` yann@1: CT_TestOrAbort "Neither en_US* nor fr_FR* locales found on your system." -n "${LC_ALL}" yann@1: CT_DoLog WARN "Forcing to known working LC_ALL=\"${LC_ALL}\"." yann@1: ;; yann@1: esac yann@1: yann@1: # Other environment sanity checks yann@1: CT_TestAndAbort "Don't set LD_LIBRARY_PATH. It screws up the build." -n "${LD_LIBRARY_PATH}" yann@1: CT_TestAndAbort "Don't set CFLAGS. It screws up the build." -n "${CFLAGS}" yann@1: CT_TestAndAbort "Don't set CXXFLAGS. It screws up the build." -n "${CXXFLAGS}" yann@1: CT_Test "GREP_OPTIONS screws up the build. Resetting." -n "${GREP_OPTIONS}" yann@1: GREP_OPTIONS= yann@1: CT_HasOrAbort awk yann@1: CT_HasOrAbort sed yann@1: CT_HasOrAbort bison yann@1: CT_HasOrAbort flex yann@1: yann@1: CT_DoStep DEBUG "Dumping crosstool-NG configuration" yann@1: cat ${CT_TOP_DIR}/.config |egrep '^(# |)CT_' |CT_DoLog DEBUG yann@1: CT_EndStep yann@1: yann@1: CT_DoLog INFO "Building environment variables" yann@1: yann@1: # Target triplet: CT_TARGET needs a little love: yann@63: CT_DoBuildTargetTriplet yann@1: yann@1: # Now, build up the variables from the user-configured options. yann@1: CT_KERNEL_FILE="${CT_KERNEL}-${CT_KERNEL_VERSION}" yann@1: CT_BINUTILS_FILE="binutils-${CT_BINUTILS_VERSION}" yann@1: if [ "${CT_CC_USE_CORE}" != "y" ]; then yann@1: CT_CC_CORE="${CT_CC}" yann@1: CT_CC_CORE_VERSION="${CT_CC_VERSION}" yann@1: CT_CC_CORE_EXTRA_CONFIG="${CT_CC_EXTRA_CONFIG}" yann@1: fi yann@1: CT_CC_CORE_FILE="${CT_CC_CORE}-${CT_CC_CORE_VERSION}" yann@1: CT_CC_FILE="${CT_CC}-${CT_CC_VERSION}" yann@1: CT_LIBC_FILE="${CT_LIBC}-${CT_LIBC_VERSION}" yann@1: [ "${CT_ARCH_FLOAT_SW_LIBFLOAT}" = "y" ] && CT_LIBFLOAT_FILE="libfloat-990616" yann@1: yann@1: # Kludge: If any of the configured options needs CT_TARGET or CT_TOP_DIR, yann@1: # then rescan the options file now: yann@1: . "${CT_TOP_DIR}/.config" yann@1: yann@85: # Where will we work? yann@85: CT_TARBALLS_DIR="${CT_TOP_DIR}/targets/tarballs" yann@85: CT_SRC_DIR="${CT_TOP_DIR}/targets/${CT_TARGET}/src" yann@85: CT_BUILD_DIR="${CT_TOP_DIR}/targets/${CT_TARGET}/build" yann@85: yann@85: # Make all path absolute, it so much easier! yann@85: CT_LOCAL_TARBALLS_DIR="`CT_MakeAbsolutePath \"${CT_LOCAL_TARBALLS_DIR}\"`" yann@85: yann@1: # Some more sanity checks now that we have all paths set up yann@1: case "${CT_TARBALLS_DIR},${CT_SRC_DIR},${CT_BUILD_DIR},${CT_PREFIX_DIR},${CT_INSTALL_DIR}" in yann@1: *" "*) CT_Abort "Don't use spaces in paths, it breaks things.";; yann@1: esac yann@1: yann@85: # Check now if we can write to the destination directory: yann@85: if [ -d "${CT_INSTALL_DIR}" ]; then yann@85: CT_TestAndAbort "Destination directory \"${CT_INSTALL_DIR}\" is not removable" ! -w `dirname "${CT_INSTALL_DIR}"` yann@85: fi yann@85: yann@85: # Get rid of pre-existing installed toolchain and previous build directories. yann@85: # We need to do that _before_ we can safely log, because the log file will yann@85: # most probably be in the toolchain directory. yann@85: if [ "${CT_FORCE_DOWNLOAD}" = "y" -a -d "${CT_TARBALLS_DIR}" ]; then yann@85: mv "${CT_TARBALLS_DIR}" "${CT_TARBALLS_DIR}.$$" yann@85: nohup rm -rf "${CT_TARBALLS_DIR}.$$" >/dev/null 2>&1 & yann@85: fi yann@85: if [ "${CT_FORCE_EXTRACT}" = "y" -a -d "${CT_SRC_DIR}" ]; then yann@85: mv "${CT_SRC_DIR}" "${CT_SRC_DIR}.$$" yann@85: nohup rm -rf "${CT_SRC_DIR}.$$" >/dev/null 2>&1 & yann@85: fi yann@85: if [ -d "${CT_BUILD_DIR}" ]; then yann@85: mv "${CT_BUILD_DIR}" "${CT_BUILD_DIR}.$$" yann@85: nohup rm -rf "${CT_BUILD_DIR}.$$" >/dev/null 2>&1 & yann@85: fi yann@85: if [ -d "${CT_INSTALL_DIR}" ]; then yann@85: mv "${CT_INSTALL_DIR}" "${CT_INSTALL_DIR}.$$" yann@85: nohup rm -rf "${CT_INSTALL_DIR}.$$" >/dev/null 2>&1 & yann@85: fi yann@85: yann@1: # Note: we'll always install the core compiler in its own directory, so as to yann@1: # not mix the two builds: core and final. Anyway, its generic, wether we use yann@1: # a different compiler as core, or not. yann@1: CT_CC_CORE_PREFIX_DIR="${CT_BUILD_DIR}/${CT_CC}-core" yann@1: yann@85: # Create the directories we'll use yann@85: mkdir -p "${CT_TARBALLS_DIR}" yann@85: mkdir -p "${CT_SRC_DIR}" yann@85: mkdir -p "${CT_BUILD_DIR}" yann@85: mkdir -p "${CT_INSTALL_DIR}" yann@85: mkdir -p "${CT_CC_CORE_PREFIX_DIR}" yann@85: yann@1: # Good, now grab a bit of informations on the system we're being run, yann@1: # just in case something goes awok, and it's not our fault: yann@1: CT_SYS_HOSTNAME=`hostname -f 2>/dev/null || true` yann@1: # Hmmm. Some non-DHCP-enabled machines do not have an FQDN... Fall back to node name. yann@1: CT_SYS_HOSTNAME="${CT_SYS_HOSTNAME:-`uname -n`}" yann@1: CT_SYS_KERNEL=`uname -s` yann@1: CT_SYS_REVISION=`uname -r` yann@1: # MacOS X lacks '-o' : yann@63: CT_SYS_OS=`uname -o || echo "Unknown (maybe MacOS-X)"` yann@1: CT_SYS_MACHINE=`uname -m` yann@1: CT_SYS_PROCESSOR=`uname -p` yann@1: CT_SYS_USER="`id -un`" yann@1: CT_SYS_DATE=`CT_DoDate +%Y%m%d.%H%M%S` yann@1: CT_SYS_GCC=`gcc -dumpversion` yann@1: CT_TOOLCHAIN_ID="crosstool-${CT_VERSION} build ${CT_SYS_DATE} by ${CT_SYS_USER}@${CT_SYS_HOSTNAME} for ${CT_TARGET}" yann@1: yann@63: # Redirect log to the actual log file now we can yann@63: # It's quite understandable that the log file will be installed in the install yann@63: # directory, so we must first ensure it exists and is writeable (above) before yann@63: # we can log there yann@63: case "${CT_LOG_TO_FILE},${CT_LOG_FILE}" in yann@63: ,*) rm -f "${CT_ACTUAL_LOG_FILE}" yann@63: CT_ACTUAL_LOG_FILE=/dev/null yann@63: ;; yann@63: y,/*) mkdir -p "`dirname \"${CT_LOG_FILE}\"`" yann@63: mv "${CT_ACTUAL_LOG_FILE}" "${CT_LOG_FILE}" yann@63: CT_ACTUAL_LOG_FILE="${CT_LOG_FILE}" yann@63: ;; yann@63: y,*) mkdir -p "`pwd`/`dirname \"${CT_LOG_FILE}\"`" yann@63: mv "${CT_ACTUAL_LOG_FILE}" "`pwd`/${CT_LOG_FILE}" yann@63: CT_ACTUAL_LOG_FILE="`pwd`/${CT_LOG_FILE}" yann@63: ;; yann@63: esac yann@63: yann@63: # Determine build system if not set by the user yann@63: CT_Test "You did not specify the build system. Guessing." -z "${CT_BUILD}" yann@63: CT_BUILD="`${CT_TOP_DIR}/tools/config.sub \"${CT_BUILD:-\`${CT_TOP_DIR}/tools/config.guess\`}\"`" yann@63: yann@63: # Arrange paths depending on wether we use sys-root or not. yann@63: if [ "${CT_USE_SYSROOT}" = "y" ]; then yann@63: CT_SYSROOT_DIR="${CT_PREFIX_DIR}/${CT_TARGET}/sys-root" yann@63: CT_HEADERS_DIR="${CT_SYSROOT_DIR}/usr/include" yann@63: BINUTILS_SYSROOT_ARG="--with-sysroot=${CT_SYSROOT_DIR}" yann@63: CC_CORE_SYSROOT_ARG="--with-sysroot=${CT_SYSROOT_DIR}" yann@63: CC_SYSROOT_ARG="--with-sysroot=${CT_SYSROOT_DIR}" yann@63: LIBC_SYSROOT_ARG="" yann@63: # glibc's prefix must be exactly /usr, else --with-sysroot'd gcc will get yann@63: # confused when $sysroot/usr/include is not present. yann@63: # Note: --prefix=/usr is magic! yann@63: # See http://www.gnu.org/software/libc/FAQ.html#s-2.2 yann@63: else yann@63: # plain old way. All libraries in prefix/target/lib yann@63: CT_SYSROOT_DIR="${CT_PREFIX_DIR}/${CT_TARGET}" yann@63: CT_HEADERS_DIR="${CT_SYSROOT_DIR}/include" yann@63: # hack! Always use --with-sysroot for binutils. yann@63: # binutils 2.14 and later obey it, older binutils ignore it. yann@63: # Lets you build a working 32->64 bit cross gcc yann@63: BINUTILS_SYSROOT_ARG="--with-sysroot=${CT_SYSROOT_DIR}" yann@63: # Use --with-headers, else final gcc will define disable_glibc while yann@63: # building libgcc, and you'll have no profiling yann@63: CC_CORE_SYSROOT_ARG="--without-headers" yann@63: CC_SYSROOT_ARG="--with-headers=${CT_HEADERS_DIR}" yann@63: LIBC_SYSROOT_ARG="prefix=" yann@63: fi yann@63: yann@63: # Prepare the 'lib' directories in sysroot, else the ../lib64 hack used by yann@63: # 32 -> 64 bit crosscompilers won't work, and build of final gcc will fail with yann@63: # "ld: cannot open crti.o: No such file or directory" yann@63: mkdir -p "${CT_SYSROOT_DIR}/lib" yann@63: mkdir -p "${CT_SYSROOT_DIR}/usr/lib" yann@63: yann@63: # Canadian-cross are really picky on the way they are built. Tweak the values. yann@63: if [ "${CT_CANADIAN}" = "y" ]; then yann@63: # Arrange so that gcc never, ever think that build system == host system yann@63: CT_CANADIAN_OPT="--build=`echo \"${CT_BUILD}\" |sed -r -e 's/-/-build_/'`" yann@63: # We shall have a compiler for this target! yann@63: # Do test here... yann@63: else yann@63: CT_HOST="${CT_BUILD}" yann@63: CT_CANADIAN_OPT= yann@63: # Add the target toolchain in the path so that we can build the C library yann@63: export PATH="${CT_PREFIX_DIR}/bin:${CT_CC_CORE_PREFIX_DIR}/bin:${PATH}" yann@63: fi yann@63: yann@63: # Modify GCC_HOST to never be equal to $BUILD or $TARGET yann@63: # This strange operation causes gcc to always generate a cross-compiler yann@63: # even if the build machine is the same kind as the host. yann@63: # This is why CC has to be set when doing a canadian cross; you can't find a yann@63: # host compiler by appending -gcc to our whacky $GCC_HOST yann@63: # Kludge: it is reported that the above causes canadian crosses with cygwin yann@63: # hosts to fail, so avoid it just in that one case. It would be cleaner to yann@63: # just move this into the non-canadian case above, but I'm afraid that might yann@63: # cause some configure script somewhere to decide that since build==host, they yann@63: # could run host binaries. yann@63: # (Copied almost as-is from original crosstool): yann@63: case "${CT_KERNEL},${CT_CANADIAN}" in yann@63: cygwin,y) ;; yann@63: *) CT_HOST="`echo \"${CT_HOST}\" |sed -r -e 's/-/-host_/;'`";; yann@63: esac yann@63: yann@63: # Ah! Recent versions of binutils need some of the build and/or host system yann@63: # (read CT_BUILD and CT_HOST) tools to be accessible (ar is but an example). yann@63: # Do that: yann@63: CT_DoLog EXTRA "Making build system tools available" yann@63: mkdir -p "${CT_PREFIX_DIR}/bin" yann@63: for tool in ar; do yann@63: ln -s "`which ${tool}`" "${CT_PREFIX_DIR}/bin/${CT_BUILD}-${tool}" yann@63: ln -s "`which ${tool}`" "${CT_PREFIX_DIR}/bin/${CT_HOST}-${tool}" yann@63: done yann@63: yann@63: # Ha. cygwin host have an .exe suffix (extension) for executables. yann@63: [ "${CT_KERNEL}" = "cygwin" ] && EXEEXT=".exe" || EXEEXT="" yann@63: yann@63: # Transform the ARCH into a kernel-understandable ARCH yann@63: case "${CT_ARCH}" in yann@63: x86) CT_KERNEL_ARCH=i386;; yann@63: ppc) CT_KERNEL_ARCH=powerpc;; yann@63: *) CT_KERNEL_ARCH="${CT_ARCH}";; yann@63: esac yann@63: yann@63: # Build up the TARGET_CFLAGS from user-provided options yann@63: # Override with user-specified CFLAGS yann@63: [ -n "${CT_ARCH_CPU}" ] && CT_TARGET_CFLAGS="-mcpu=${CT_ARCH_CPU} ${CT_TARGET_CFLAGS}" yann@63: [ -n "${CT_ARCH_TUNE}" ] && CT_TARGET_CFLAGS="-mtune=${CT_ARCH_TUNE} ${CT_TARGET_CFLAGS}" yann@63: [ -n "${CT_ARCH_ARCH}" ] && CT_TARGET_CFLAGS="-march=${CT_ARCH_ARCH} ${CT_TARGET_CFLAGS}" yann@63: [ -n "${CT_ARCH_FPU}" ] && CT_TARGET_CFLAGS="-mfpu=${CT_ARCH_FPU} ${CT_TARGET_CFLAGS}" yann@63: yann@63: # Help gcc yann@63: CT_CFLAGS_FOR_HOST= yann@63: [ "${CT_USE_PIPES}" = "y" ] && CT_CFLAGS_FOR_HOST="${CT_CFLAGS_FOR_HOST} -pipe" yann@63: yann@63: # And help make go faster yann@63: PARALLELMFLAGS= yann@63: [ ${CT_PARALLEL_JOBS} -ne 0 ] && PARALLELMFLAGS="${PARALLELMFLAGS} -j${CT_PARALLEL_JOBS}" yann@63: [ ${CT_LOAD} -ne 0 ] && PARALLELMFLAGS="${PARALLELMFLAGS} -l${CT_LOAD}" yann@63: yann@63: CT_DoStep EXTRA "Dumping internal crosstool-NG configuration" yann@63: CT_DoLog EXTRA "Building a toolchain for:" yann@63: CT_DoLog EXTRA " build = ${CT_BUILD}" yann@63: CT_DoLog EXTRA " host = ${CT_HOST}" yann@63: CT_DoLog EXTRA " target = ${CT_TARGET}" yann@63: set |egrep '^CT_.+=' |sort |CT_DoLog DEBUG yann@63: CT_EndStep yann@1: yann@1: # Include sub-scripts instead of calling them: that way, we do not have to yann@1: # export any variable, nor re-parse the configuration and functions files. yann@63: . "${CT_TOP_DIR}/scripts/build/kernel_${CT_KERNEL}.sh" yann@63: . "${CT_TOP_DIR}/scripts/build/binutils.sh" yann@83: . "${CT_TOP_DIR}/scripts/build/libfloat.sh" yann@63: . "${CT_TOP_DIR}/scripts/build/libc_${CT_LIBC}.sh" yann@63: . "${CT_TOP_DIR}/scripts/build/cc_core_${CT_CC_CORE}.sh" yann@63: . "${CT_TOP_DIR}/scripts/build/cc_${CT_CC}.sh" yann@63: yann@63: # Now for the job by itself. Go have a coffee! yann@85: CT_DoStep INFO "Retrieving needed toolchain components' tarballs" yann@85: do_kernel_get yann@85: do_binutils_get yann@85: do_cc_core_get yann@85: do_libfloat_get yann@85: do_libc_get yann@85: do_cc_get yann@85: CT_EndStep yann@63: yann@63: if [ "${CT_ONLY_DOWNLOAD}" != "y" ]; then yann@63: if [ "${CT_FORCE_EXTRACT}" = "y" ]; then yann@63: mv "${CT_SRC_DIR}" "${CT_SRC_DIR}.$$" yann@63: nohup rm -rf "${CT_SRC_DIR}.$$" >/dev/null 2>&1 yann@63: fi yann@63: CT_DoStep INFO "Extracting and patching toolchain components" yann@63: do_kernel_extract yann@63: do_binutils_extract yann@63: do_libc_extract yann@63: do_libfloat_extract yann@63: do_cc_core_extract yann@63: do_cc_extract yann@63: CT_EndStep yann@63: yann@63: if [ "${CT_ONLY_EXTRACT}" != "y" ]; then yann@63: do_libc_check_config yann@63: do_kernel_check_config yann@63: do_kernel_headers yann@63: do_binutils yann@63: do_libc_headers yann@63: do_cc_core yann@63: do_libfloat yann@63: do_libc yann@63: do_cc yann@63: do_libc_finish yann@85: yann@85: # Create the aliases to the target tools yann@85: if [ -n "${CT_TARGET_ALIAS}" ]; then yann@85: CT_DoLog EXTRA "Creating symlinks from \"${CT_TARGET}-*\" to \"${CT_TARGET_ALIAS}-*\"" yann@85: CT_Pushd "${CT_PREFIX_DIR}/bin" yann@85: for t in "${CT_TARGET}-"*; do yann@85: _t="`echo \"$t\" |sed -r -e 's/^'\"${CT_TARGET}\"'-/'\"${CT_TARGET_ALIAS}\"'-/;'`" yann@85: CT_DoLog DEBUG "Linking \"${_t}\" -> \"${t}\"" yann@85: ln -s "${t}" "${_t}" yann@85: done yann@85: CT_Popd yann@85: fi yann@85: yann@85: # Remove the generated documentation files yann@85: if [ "${CT_REMOVE_DOCS}" = "y" ]; then yann@85: CT_DoLog INFO "Removing installed documentation" yann@85: rm -rf "${CT_PREFIX_DIR}/"{man,info} yann@85: fi yann@63: fi yann@63: fi yann@1: yann@1: CT_STOP_DATE=`CT_DoDate +%s%N` yann@1: CT_STOP_DATE_HUMAN=`CT_DoDate +%Y%m%d.%H%M%S` yann@1: CT_DoLog INFO "Build completed at ${CT_STOP_DATE_HUMAN}" yann@1: elapsed=$((CT_STOP_DATE-CT_STAR_DATE)) yann@1: elapsed_min=$((elapsed/(60*1000*1000*1000))) yann@1: elapsed_sec=`printf "%02d" $(((elapsed%(60*1000*1000*1000))/(1000*1000*1000)))` yann@1: elapsed_csec=`printf "%02d" $(((elapsed%(1000*1000*1000))/(10*1000*1000)))` yann@1: CT_DoLog INFO "(elapsed: ${elapsed_min}:${elapsed_sec}.${elapsed_csec})" yann@1: yann@1: # Restore a 'normal' color setting yann@1: echo -en "${CT_NORMAL_COLOR}" yann@1: yann@1: trap - EXIT