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@96: # and builds the tools. yann@1: yann@96: # CT_TOP_DIR is set by the makefile. If we don't have it, something's gone horribly wrong... 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@96: echo "CT_TOP_DIR not set, or not a directory. Something's gone horribly wrong." yann@96: echo "Please send a bug report (see README)" 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@96: # Are we configured? We'll need that later... yann@96: CT_TestOrAbort "Configuration file not found. Please create one." -f "${CT_TOP_DIR}/.config" yann@96: yann@1: # Parse the configuration file yann@96: # It has some info about the logging facility, so include it early yann@1: . "${CT_TOP_DIR}/.config" yann@1: yann@96: # renice oursleves yann@96: renice ${CT_NICE} $$ |CT_DoLog DEBUG 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@96: CT_DoStep DEBUG "Dumping crosstool-NG configuration" yann@96: cat ${CT_TOP_DIR}/.config |egrep '^(# |)CT_' |CT_DoLog DEBUG yann@96: CT_EndStep 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_DoLog INFO "Building environment variables" yann@1: yann@1: # Target triplet: CT_TARGET needs a little love: yann@63: CT_DoBuildTargetTriplet yann@1: yann@96: # Kludge: If any of the configured options needs CT_TARGET, yann@96: # then rescan the options file now: yann@96: . "${CT_TOP_DIR}/.config" yann@96: 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@107: CT_LIBFLOAT_FILE="libfloat-${CT_LIBFLOAT_VERSION}" 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@96: CT_DEBUG_INSTALL_DIR="${CT_INSTALL_DIR}/${CT_TARGET}/debug-root" 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@96: # Good, now grab a bit of informations on the system we're being run on, yann@96: # just in case something goes awok, and it's not our fault: yann@96: CT_SYS_USER="`id -un`" yann@96: CT_SYS_HOSTNAME=`hostname -f 2>/dev/null || true` yann@96: # Hmmm. Some non-DHCP-enabled machines do not have an FQDN... Fall back to node name. yann@96: CT_SYS_HOSTNAME="${CT_SYS_HOSTNAME:-`uname -n`}" yann@96: CT_SYS_KERNEL=`uname -s` yann@96: CT_SYS_REVISION=`uname -r` yann@96: # MacOS X lacks '-o' : yann@96: CT_SYS_OS=`uname -o || echo "Unknown (maybe MacOS-X)"` yann@96: CT_SYS_MACHINE=`uname -m` yann@96: CT_SYS_PROCESSOR=`uname -p` yann@96: CT_SYS_GCC=`gcc -dumpversion` yann@96: CT_SYS_TARGET=`${CT_TOP_DIR}/tools/config.guess` yann@96: CT_TOOLCHAIN_ID="crosstool-${CT_VERSION} build ${CT_STAR_DATE_HUMAN} by ${CT_SYS_USER}@${CT_SYS_HOSTNAME}" yann@96: yann@96: CT_DoLog EXTRA "Preparing working directories" yann@96: 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@96: chmod -R u+w "${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@96: chmod -R u+w "${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@96: chmod -R u+w "${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@96: chmod -R u+w "${CT_INSTALL_DIR}.$$" yann@85: nohup rm -rf "${CT_INSTALL_DIR}.$$" >/dev/null 2>&1 & yann@85: fi yann@96: if [ -d "${CT_DEBUG_INSTALL_DIR}" ]; then yann@96: mv "${CT_DEBUG_INSTALL_DIR}" "${CT_DEBUG_INSTALL_DIR}.$$" yann@96: chmod -R u+w "${CT_DEBUG_INSTALL_DIR}.$$" yann@96: nohup rm -rf "${CT_DEBUG_INSTALL_DIR}.$$" >/dev/null 2>&1 & yann@96: 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@96: mkdir -p "${CT_DEBUG_INSTALL_DIR}" yann@85: mkdir -p "${CT_CC_CORE_PREFIX_DIR}" yann@85: 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@96: for tool in ar gcc; do yann@63: ln -s "`which ${tool}`" "${CT_PREFIX_DIR}/bin/${CT_BUILD}-${tool}" yann@96: case "${CT_TOOLCHAIN_TYPE}" in yann@96: cross|native) ln -s "`which ${tool}`" "${CT_PREFIX_DIR}/bin/${CT_HOST}-${tool}";; yann@96: esac 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@96: . "${CT_TOP_DIR}/scripts/build/debug.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@96: do_debug_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@96: do_cc_core_extract yann@96: do_libfloat_extract yann@63: do_libc_extract yann@63: do_cc_extract yann@96: do_debug_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@96: do_debug 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@101: rm -rf "${CT_PREFIX_DIR}/"{,usr/}{man,info} yann@101: rm -rf "${CT_SYSROOT_DIR}/"{,usr/}{man,info} yann@101: rm -rf "${CT_DEBUG_INSTALL_DIR}/"{,usr/}{man,info} yann@85: fi yann@63: fi yann@63: fi yann@1: yann@96: # OK, now we're done, set the toolchain read-only yann@96: # Don't log, the log file may become read-only any moment... yann@96: chmod -R a-w "${CT_INSTALL_DIR}" yann@96: yann@96: # We stil have some small bits to log yann@96: chmod u+w "${CT_LOG_FILE}" yann@96: yann@96: CT_DoEnd INFO yann@96: yann@96: # All files should now be read-only, log-file included yann@96: chmod a-w "${CT_LOG_FILE}" yann@1: yann@1: # Restore a 'normal' color setting yann@1: echo -en "${CT_NORMAL_COLOR}" yann@1: yann@1: trap - EXIT