| #!/bin/bash |
| # |
| # Compiles and installs a Linux/x86_64 -> Linux/ARM crosstool based on LLVM and |
| # LLVM-GCC-4.2 using SVN snapshots in provided tarballs. |
| |
| set -o nounset |
| set -o errexit |
| |
| echo -n "Welcome to LLVM Linux/X86_64 -> Linux/ARM crosstool " |
| echo "builder/installer; some steps will require sudo privileges." |
| |
| readonly INSTALL_ROOT="${INSTALL_ROOT:-/usr/local/crosstool}" |
| # Both $USER and root *must* have read/write access to this dir. |
| readonly SCRATCH_ROOT=$(mktemp -d "${TMPDIR:-/tmp}/llvm-project.XXXXXX") |
| readonly SRC_ROOT="${SCRATCH_ROOT}/src" |
| readonly OBJ_ROOT="${SCRATCH_ROOT}/obj" |
| |
| readonly CROSS_HOST="x86_64-unknown-linux-gnu" |
| readonly CROSS_TARGET="arm-none-linux-gnueabi" |
| readonly CROSS_MARCH="${CROSS_MARCH:-armv6}" |
| |
| readonly CODE_SOURCERY="${INSTALL_ROOT}/codesourcery" |
| readonly CODE_SOURCERY_PKG_PATH="${CODE_SOURCERY_PKG_PATH:-${HOME}/codesourcery}" |
| readonly CODE_SOURCERY_HTTP="http://www.codesourcery.com/sgpp/lite/arm/portal/package1787/public" |
| readonly CODE_SOURCERY_PKG="arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2" |
| readonly CODE_SOURCERY_ROOT="${CODE_SOURCERY}/arm-2007q3" |
| readonly CODE_SOURCERY_BIN="${CODE_SOURCERY_ROOT}/bin" |
| # Make sure ${CROSS_TARGET}-* binutils are in command path |
| export PATH="${CODE_SOURCERY_BIN}:${PATH}" |
| |
| readonly CROSS_TARGET_AS="${CODE_SOURCERY_BIN}/${CROSS_TARGET}-as" |
| readonly CROSS_TARGET_LD="${CODE_SOURCERY_BIN}/${CROSS_TARGET}-ld" |
| |
| readonly SYSROOT="${CODE_SOURCERY_ROOT}/${CROSS_TARGET}/libc" |
| |
| readonly LLVM_PKG_PATH="${LLVM_PKG_PATH:-${HOME}/llvm-project/snapshots}" |
| |
| # Latest SVN revisions known to be working in this configuration. |
| readonly LLVM_DEFAULT_REV="74530" |
| readonly LLVMGCC_DEFAULT_REV="74535" |
| |
| readonly LLVM_PKG="llvm-${LLVM_SVN_REV:-${LLVM_DEFAULT_REV}}.tar.bz2" |
| readonly LLVM_SRC_DIR="${SRC_ROOT}/llvm" |
| readonly LLVM_OBJ_DIR="${OBJ_ROOT}/llvm" |
| readonly LLVM_INSTALL_DIR="${INSTALL_ROOT}/${CROSS_TARGET}/llvm" |
| |
| readonly LLVMGCC_PKG="llvm-gcc-4.2-${LLVMGCC_SVN_REV:-${LLVMGCC_DEFAULT_REV}}.tar.bz2" |
| readonly LLVMGCC_SRC_DIR="${SRC_ROOT}/llvm-gcc-4.2" |
| readonly LLVMGCC_OBJ_DIR="${OBJ_ROOT}/llvm-gcc-4.2" |
| readonly LLVMGCC_INSTALL_DIR="${INSTALL_ROOT}/${CROSS_TARGET}/llvm-gcc-4.2" |
| |
| readonly MAKE_OPTS="${MAKE_OPTS:--j2}" |
| |
| # Params: |
| # $1: directory to be created |
| # $2: optional mkdir command prefix, e.g. "sudo" |
| createDir() { |
| if [[ ! -e $1 ]]; then |
| ${2:-} mkdir -p $1 |
| elif [[ -e $1 && ! -d $1 ]]; then |
| echo "$1 exists but is not a directory; exiting." |
| exit 3 |
| fi |
| } |
| |
| sudoCreateDir() { |
| createDir $1 sudo |
| sudo chown ${USER} $1 |
| } |
| |
| # Prints out and runs the command, but without logging -- intended for use with |
| # lightweight commands that don't have useful output to parse, e.g. mkdir, tar, |
| # etc. |
| runCommand() { |
| local message="$1" |
| shift |
| echo "=> $message" |
| echo "==> Running: $*" |
| $* |
| } |
| |
| runAndLog() { |
| local message="$1" |
| local log_file="$2" |
| shift 2 |
| echo "=> $message; log in $log_file" |
| echo "==> Running: $*" |
| # Pop-up a terminal with the output of the current command? |
| # e.g.: xterm -e /bin/bash -c "$* >| tee $log_file" |
| $* &> $log_file |
| if [[ $? != 0 ]]; then |
| echo "Error occurred: see most recent log file for details." |
| exit |
| fi |
| } |
| |
| installCodeSourcery() { |
| # Unpack the tarball, creating the CodeSourcery dir, if necessary. |
| if [[ ! -d ${CODE_SOURCERY_ROOT} ]]; then |
| sudoCreateDir ${CODE_SOURCERY} |
| cd ${CODE_SOURCERY} |
| if [[ -e ${CODE_SOURCERY_PKG_PATH}/${CODE_SOURCERY_PKG} ]]; then |
| runCommand "Unpacking CodeSourcery in ${CODE_SOURCERY}" \ |
| tar jxf ${CODE_SOURCERY_PKG_PATH}/${CODE_SOURCERY_PKG} |
| else |
| echo -n "CodeSourcery tarball not found in " |
| echo "${CODE_SOURCERY_PKG_PATH}/${CODE_SOURCERY_PKG}" |
| echo -n "Fix the path or download it from " |
| echo "${CODE_SOURCERY_HTTP}/${CROSS_TARGET}/${CODE_SOURCERY_PKG}" |
| exit |
| fi |
| else |
| echo "CodeSourcery install dir already exists; skipping." |
| fi |
| |
| # Verify our CodeSourcery toolchain installation. |
| if [[ ! -d "${SYSROOT}" ]]; then |
| echo -n "Error: CodeSourcery does not contain libc for ${CROSS_TARGET}: " |
| echo "${SYSROOT} not found." |
| exit |
| fi |
| |
| for tool in ${CROSS_TARGET_AS} ${CROSS_TARGET_LD}; do |
| if [[ ! -e $tool ]]; then |
| echo "${tool} not found; exiting." |
| exit |
| fi |
| done |
| } |
| |
| installLLVM() { |
| if [[ -d ${LLVM_INSTALL_DIR} ]]; then |
| echo "LLVM install dir ${LLVM_INSTALL_DIR} exists; skipping." |
| return |
| fi |
| |
| sudoCreateDir ${LLVM_INSTALL_DIR} |
| |
| # Unpack LLVM tarball; should create the directory "llvm". |
| cd ${SRC_ROOT} |
| runCommand "Unpacking LLVM" tar jxf ${LLVM_PKG_PATH}/${LLVM_PKG} |
| |
| # Configure, build, and install LLVM. |
| createDir ${LLVM_OBJ_DIR} |
| cd ${LLVM_OBJ_DIR} |
| runAndLog "Configuring LLVM" ${LLVM_OBJ_DIR}/llvm-configure.log \ |
| ${LLVM_SRC_DIR}/configure \ |
| --disable-jit \ |
| --enable-optimized \ |
| --prefix=${LLVM_INSTALL_DIR} \ |
| --target=${CROSS_TARGET} \ |
| --with-llvmgccdir=${LLVMGCC_INSTALL_DIR} |
| runAndLog "Building LLVM" ${LLVM_OBJ_DIR}/llvm-build.log \ |
| make ${MAKE_OPTS} |
| runAndLog "Installing LLVM" ${LLVM_OBJ_DIR}/llvm-install.log \ |
| make ${MAKE_OPTS} install |
| } |
| |
| installLLVMGCC() { |
| if [[ -d ${LLVMGCC_INSTALL_DIR} ]]; then |
| echo "LLVM-GCC install dir ${LLVMGCC_INSTALL_DIR} exists; skipping." |
| return |
| fi |
| |
| sudoCreateDir ${LLVMGCC_INSTALL_DIR} |
| |
| # Unpack LLVM-GCC tarball; should create the directory "llvm-gcc-4.2". |
| cd ${SRC_ROOT} |
| runCommand "Unpacking LLVM-GCC" tar jxf ${LLVM_PKG_PATH}/${LLVMGCC_PKG} |
| |
| # Configure, build, and install LLVM-GCC. |
| createDir ${LLVMGCC_OBJ_DIR} |
| cd ${LLVMGCC_OBJ_DIR} |
| runAndLog "Configuring LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-configure.log \ |
| ${LLVMGCC_SRC_DIR}/configure \ |
| --enable-languages=c,c++ \ |
| --enable-llvm=${LLVM_INSTALL_DIR} \ |
| --prefix=${LLVMGCC_INSTALL_DIR} \ |
| --program-prefix=llvm- \ |
| --target=${CROSS_TARGET} \ |
| --with-arch=${CROSS_MARCH} \ |
| --with-as=${CROSS_TARGET_AS} \ |
| --with-ld=${CROSS_TARGET_LD} \ |
| --with-sysroot=${SYSROOT} |
| runAndLog "Building LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-build.log \ |
| make |
| runAndLog "Installing LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-install.log \ |
| make install |
| } |
| |
| echo "Building in ${SCRATCH_ROOT}; installing in ${INSTALL_ROOT}" |
| |
| createDir ${SRC_ROOT} |
| createDir ${OBJ_ROOT} |
| |
| installCodeSourcery |
| installLLVM |
| installLLVMGCC |
| |
| echo "Done." |