Home | History | Annotate | Download | only in ARM
      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