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