Misha Brukman | cb6f9c8 | 2009-06-12 01:55:57 +0000 | [diff] [blame^] | 1 | #!/bin/bash |
| 2 | # |
| 3 | # Compiles and installs a Linux/x86_64 -> Linux/ARM crosstool based on LLVM and |
| 4 | # LLVM-GCC-4.2 using SVN snapshots in provided tarballs. |
| 5 | |
| 6 | set -o nounset |
| 7 | set -o errexit |
| 8 | |
| 9 | echo -n "Welcome to LLVM Linux/X86_64 -> Linux/ARM crosstool " |
| 10 | echo "builder/installer; some steps will require sudo privileges." |
| 11 | |
| 12 | readonly INSTALL_ROOT="${INSTALL_ROOT:-/usr/local}" |
| 13 | # Both $USER and root *must* have read/write access to this dir. |
| 14 | readonly SCRATCH_ROOT=$(mktemp -d "${TMPDIR:-/tmp}/llvm-project.XXXXXX") |
| 15 | readonly SRC_ROOT="${SCRATCH_ROOT}/src" |
| 16 | readonly OBJ_ROOT="${SCRATCH_ROOT}/obj" |
| 17 | |
| 18 | readonly CROSS_HOST="x86_64-unknown-linux-gnu" |
| 19 | readonly CROSS_TARGET="arm-none-linux-gnueabi" |
| 20 | |
| 21 | readonly CODE_SOURCERY="${INSTALL_ROOT}/codesourcery" |
| 22 | readonly CODE_SOURCERY_PKG_PATH="${CODE_SOURCERY_PKG_PATH:-${HOME}/codesourcery}" |
| 23 | readonly CODE_SOURCERY_PKG="arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2" |
| 24 | readonly CODE_SOURCERY_ROOT="${CODE_SOURCERY}/arm-2007q3" |
| 25 | readonly CODE_SOURCERY_BIN="${CODE_SOURCERY_ROOT}/bin" |
| 26 | # Make sure ${CROSS_TARGET}-* binutils are in command path |
| 27 | export PATH="${CODE_SOURCERY_BIN}:${PATH}" |
| 28 | |
| 29 | readonly CROSS_TARGET_AS="${CODE_SOURCERY_BIN}/${CROSS_TARGET}-as" |
| 30 | readonly CROSS_TARGET_LD="${CODE_SOURCERY_BIN}/${CROSS_TARGET}-ld" |
| 31 | |
| 32 | readonly SYSROOT="${CODE_SOURCERY_ROOT}/${CROSS_TARGET}/libc" |
| 33 | |
| 34 | readonly LLVM_PROJECT="${INSTALL_ROOT}/llvm-project" |
| 35 | readonly LLVM_INSTALL_ROOT="${LLVM_PROJECT}/${CROSS_HOST}/${CROSS_TARGET}" |
| 36 | readonly LLVM_PKG_PATH="${LLVM_PKG_PATH:-${HOME}/llvm-project/snapshots}" |
| 37 | |
| 38 | # Latest SVN revision known to be working in this configuration. |
| 39 | readonly LLVM_DEFAULT_REV="70786" |
| 40 | |
| 41 | readonly LLVM_PKG="llvm-${LLVM_SVN_REV:-${LLVM_DEFAULT_REV}}.tar.bz2" |
| 42 | readonly LLVM_SRC_DIR="${SRC_ROOT}/llvm" |
| 43 | readonly LLVM_OBJ_DIR="${OBJ_ROOT}/llvm" |
| 44 | readonly LLVM_INSTALL_DIR="${LLVM_INSTALL_ROOT}/llvm" |
| 45 | |
| 46 | readonly LLVMGCC_PKG="llvm-gcc-4.2-${LLVMGCC_SVN_REV:-${LLVM_DEFAULT_REV}}.tar.bz2" |
| 47 | readonly LLVMGCC_SRC_DIR="${SRC_ROOT}/llvm-gcc-4.2" |
| 48 | readonly LLVMGCC_OBJ_DIR="${OBJ_ROOT}/llvm-gcc-4.2" |
| 49 | readonly LLVMGCC_INSTALL_DIR="${LLVM_INSTALL_ROOT}/llvm-gcc-4.2" |
| 50 | |
| 51 | readonly MAKE_OPTS="-j2" |
| 52 | |
| 53 | # Verify we aren't going to install into an existing directory as this might |
| 54 | # create problems as we won't have a clean install. |
| 55 | verifyNotDir() { |
| 56 | if [[ -d $1 ]]; then |
| 57 | echo "Install dir $1 already exists; remove it to continue." |
| 58 | exit |
| 59 | fi |
| 60 | } |
| 61 | |
| 62 | # Params: |
| 63 | # $1: directory to be created |
| 64 | # $2: optional mkdir command prefix, e.g. "sudo" |
| 65 | createDir() { |
| 66 | if [[ ! -e $1 ]]; then |
| 67 | ${2:-} mkdir -p $1 |
| 68 | elif [[ -e $1 && ! -d $1 ]]; then |
| 69 | echo "$1 exists but is not a directory; exiting." |
| 70 | exit 3 |
| 71 | fi |
| 72 | } |
| 73 | |
| 74 | sudoCreateDir() { |
| 75 | createDir $1 sudo |
| 76 | sudo chown ${USER} $1 |
| 77 | } |
| 78 | |
| 79 | # Prints out and runs the command, but without logging -- intended for use with |
| 80 | # lightweight commands that don't have useful output to parse, e.g. mkdir, tar, |
| 81 | # etc. |
| 82 | runCommand() { |
| 83 | local message="$1" |
| 84 | shift |
| 85 | echo "=> $message" |
| 86 | echo "==> Running: $*" |
| 87 | $* |
| 88 | } |
| 89 | |
| 90 | runAndLog() { |
| 91 | local message="$1" |
| 92 | local log_file="$2" |
| 93 | shift 2 |
| 94 | echo "=> $message; log in $log_file" |
| 95 | echo "==> Running: $*" |
| 96 | # Pop-up a terminal with the output of the current command? |
| 97 | # e.g.: xterm -e /bin/bash -c "$* >| tee $log_file" |
| 98 | $* &> $log_file |
| 99 | if [[ $? != 0 ]]; then |
| 100 | echo "Error occurred: see most recent log file for details." |
| 101 | exit |
| 102 | fi |
| 103 | } |
| 104 | |
| 105 | installCodeSourcery() { |
| 106 | # Create CodeSourcery dir, if necessary. |
| 107 | verifyNotDir ${CODE_SOURCERY} |
| 108 | sudoCreateDir ${CODE_SOURCERY} |
| 109 | |
| 110 | # Unpack the tarball. |
| 111 | if [[ ! -d ${CODE_SOURCERY_ROOT} ]]; then |
| 112 | cd ${CODE_SOURCERY} |
| 113 | runCommand "Unpacking CodeSourcery in ${CODE_SOURCERY}" \ |
| 114 | tar jxf ${CODE_SOURCERY_PKG_PATH}/${CODE_SOURCERY_PKG} |
| 115 | else |
| 116 | echo "CodeSourcery install dir already exists." |
| 117 | fi |
| 118 | |
| 119 | # Verify our CodeSourcery toolchain installation. |
| 120 | if [[ ! -d "${SYSROOT}" ]]; then |
| 121 | echo -n "Error: CodeSourcery does not contain libc for ${CROSS_TARGET}: " |
| 122 | echo "${SYSROOT} not found." |
| 123 | exit |
| 124 | fi |
| 125 | |
| 126 | for tool in ${CROSS_TARGET_AS} ${CROSS_TARGET_LD}; do |
| 127 | if [[ ! -e $tool ]]; then |
| 128 | echo "${tool} not found; exiting." |
| 129 | exit |
| 130 | fi |
| 131 | done |
| 132 | } |
| 133 | |
| 134 | installLLVM() { |
| 135 | verifyNotDir ${LLVM_INSTALL_DIR} |
| 136 | sudoCreateDir ${LLVM_INSTALL_DIR} |
| 137 | |
| 138 | # Unpack LLVM tarball; should create the directory "llvm". |
| 139 | cd ${SRC_ROOT} |
| 140 | runCommand "Unpacking LLVM" tar jxf ${LLVM_PKG_PATH}/${LLVM_PKG} |
| 141 | |
| 142 | # Configure, build, and install LLVM. |
| 143 | createDir ${LLVM_OBJ_DIR} |
| 144 | cd ${LLVM_OBJ_DIR} |
| 145 | runAndLog "Configuring LLVM" ${LLVM_OBJ_DIR}/llvm-configure.log \ |
| 146 | ${LLVM_SRC_DIR}/configure \ |
| 147 | --disable-jit \ |
| 148 | --enable-optimized \ |
| 149 | --prefix=${LLVM_INSTALL_DIR} \ |
| 150 | --target=${CROSS_TARGET} \ |
| 151 | --with-llvmgccdir=${LLVMGCC_INSTALL_DIR} |
| 152 | runAndLog "Building LLVM" ${LLVM_OBJ_DIR}/llvm-build.log \ |
| 153 | make ${MAKE_OPTS} |
| 154 | runAndLog "Installing LLVM" ${LLVM_OBJ_DIR}/llvm-install.log \ |
| 155 | make ${MAKE_OPTS} install |
| 156 | } |
| 157 | |
| 158 | installLLVMGCC() { |
| 159 | verifyNotDir ${LLVMGCC_INSTALL_DIR} |
| 160 | sudoCreateDir ${LLVMGCC_INSTALL_DIR} |
| 161 | |
| 162 | # Unpack LLVM-GCC tarball; should create the directory "llvm-gcc-4.2". |
| 163 | cd ${SRC_ROOT} |
| 164 | runCommand "Unpacking LLVM-GCC" tar jxf ${LLVM_PKG_PATH}/${LLVMGCC_PKG} |
| 165 | |
| 166 | # Configure, build, and install LLVM-GCC. |
| 167 | createDir ${LLVMGCC_OBJ_DIR} |
| 168 | cd ${LLVMGCC_OBJ_DIR} |
| 169 | runAndLog "Configuring LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-configure.log \ |
| 170 | ${LLVMGCC_SRC_DIR}/configure \ |
| 171 | --enable-languages=c,c++ \ |
| 172 | --enable-llvm=${LLVM_INSTALL_DIR} \ |
| 173 | --prefix=${LLVMGCC_INSTALL_DIR} \ |
| 174 | --program-prefix=llvm- \ |
| 175 | --target=${CROSS_TARGET} \ |
| 176 | --with-gnu-as=${CROSS_TARGET_AS} \ |
| 177 | --with-gnu-ld=${CROSS_TARGET_LD} \ |
| 178 | --with-sysroot=${SYSROOT} |
| 179 | runAndLog "Building LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-build.log \ |
| 180 | make |
| 181 | runAndLog "Installing LLVM-GCC" ${LLVMGCC_OBJ_DIR}/llvmgcc-install.log \ |
| 182 | make install |
| 183 | } |
| 184 | |
| 185 | echo "Building in ${SCRATCH_ROOT}; installing in ${INSTALL_ROOT}" |
| 186 | |
| 187 | createDir ${SRC_ROOT} |
| 188 | createDir ${OBJ_ROOT} |
| 189 | |
| 190 | installCodeSourcery |
| 191 | installLLVM |
| 192 | installLLVMGCC |
| 193 | |
| 194 | echo "Done." |