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