Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/env bash
      2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 # This script will check out llvm and clang into third_party/llvm and build it.
      7 
      8 # Do NOT CHANGE this if you don't know what you're doing -- see
      9 # https://code.google.com/p/chromium/wiki/UpdatingClang
     10 # Reverting problematic clang rolls is safe, though.
     11 CLANG_REVISION=186332
     12 
     13 THIS_DIR="$(dirname "${0}")"
     14 LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
     15 LLVM_BUILD_DIR="${LLVM_DIR}/../llvm-build"
     16 LLVM_BOOTSTRAP_DIR="${LLVM_DIR}/../llvm-bootstrap"
     17 CLANG_DIR="${LLVM_DIR}/tools/clang"
     18 CLANG_TOOLS_EXTRA_DIR="${CLANG_DIR}/tools/extra"
     19 COMPILER_RT_DIR="${LLVM_DIR}/projects/compiler-rt"
     20 ANDROID_NDK_DIR="${LLVM_DIR}/../android_tools/ndk"
     21 STAMP_FILE="${LLVM_BUILD_DIR}/cr_build_revision"
     22 
     23 # ${A:-a} returns $A if it's set, a else.
     24 LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project}
     25 
     26 # Die if any command dies.
     27 set -e
     28 
     29 OS="$(uname -s)"
     30 
     31 # Parse command line options.
     32 force_local_build=
     33 mac_only=
     34 run_tests=
     35 bootstrap=
     36 with_android=yes
     37 chrome_tools="plugins"
     38 
     39 if [[ "${OS}" = "Darwin" ]]; then
     40   with_android=
     41 fi
     42 
     43 while [[ $# > 0 ]]; do
     44   case $1 in
     45     --bootstrap)
     46       bootstrap=yes
     47       ;;
     48     --force-local-build)
     49       force_local_build=yes
     50       ;;
     51     --mac-only)
     52       mac_only=yes
     53       ;;
     54     --run-tests)
     55       run_tests=yes
     56       ;;
     57     --without-android)
     58       with_android=
     59       ;;
     60     --with-chrome-tools)
     61       shift
     62       if [[ $# == 0 ]]; then
     63         echo "--with-chrome-tools requires an argument."
     64         exit 1
     65       fi
     66       chrome_tools=$1
     67       ;;
     68     --help)
     69       echo "usage: $0 [--force-local-build] [--mac-only] [--run-tests] "
     70       echo "--bootstrap: First build clang with CC, then with itself."
     71       echo "--force-local-build: Don't try to download prebuilt binaries."
     72       echo "--mac-only: Do initial download only on Mac systems."
     73       echo "--run-tests: Run tests after building. Only for local builds."
     74       echo "--without-android: Don't build ASan Android runtime library."
     75       echo "--with-chrome-tools: Select which chrome tools to build." \
     76            "Defaults to plugins."
     77       echo "    Example: --with-chrome-tools 'plugins empty-string'"
     78       echo
     79       exit 1
     80       ;;
     81   esac
     82   shift
     83 done
     84 
     85 # --mac-only prevents the initial download on non-mac systems, but if clang has
     86 # already been downloaded in the past, this script keeps it up to date even if
     87 # --mac-only is passed in and the system isn't a mac. People who don't like this
     88 # can just delete their third_party/llvm-build directory.
     89 if [[ -n "$mac_only" ]] && [[ "${OS}" != "Darwin" ]] &&
     90     [[ ! ( "$GYP_DEFINES" =~ .*(clang|tsan|asan)=1.* ) ]] &&
     91     ! [[ -d "${LLVM_BUILD_DIR}" ]]; then
     92   exit 0
     93 fi
     94 
     95 # Xcode and clang don't get along when predictive compilation is enabled.
     96 # http://crbug.com/96315
     97 if [[ "${OS}" = "Darwin" ]] && xcodebuild -version | grep -q 'Xcode 3.2' ; then
     98   XCONF=com.apple.Xcode
     99   if [[ "${GYP_GENERATORS}" != "make" ]] && \
    100      [ "$(defaults read "${XCONF}" EnablePredictiveCompilation)" != "0" ]; then
    101     echo
    102     echo "          HEARKEN!"
    103     echo "You're using Xcode3 and you have 'Predictive Compilation' enabled."
    104     echo "This does not work well with clang (http://crbug.com/96315)."
    105     echo "Disable it in Preferences->Building (lower right), or run"
    106     echo "    defaults write ${XCONF} EnablePredictiveCompilation -boolean NO"
    107     echo "while Xcode is not running."
    108     echo
    109   fi
    110 
    111   SUB_VERSION=$(xcodebuild -version | sed -Ene 's/Xcode 3\.2\.([0-9]+)/\1/p')
    112   if [[ "${SUB_VERSION}" < 6 ]]; then
    113     echo
    114     echo "          YOUR LD IS BUGGY!"
    115     echo "Please upgrade Xcode to at least 3.2.6."
    116     echo
    117   fi
    118 fi
    119 
    120 
    121 # Check if there's anything to be done, exit early if not.
    122 if [[ -f "${STAMP_FILE}" ]]; then
    123   PREVIOUSLY_BUILT_REVISON=$(cat "${STAMP_FILE}")
    124   if [[ -z "$force_local_build" ]] && \
    125        [[ "${PREVIOUSLY_BUILT_REVISON}" = "${CLANG_REVISION}" ]]; then
    126     echo "Clang already at ${CLANG_REVISION}"
    127     exit 0
    128   fi
    129 fi
    130 # To always force a new build if someone interrupts their build half way.
    131 rm -f "${STAMP_FILE}"
    132 
    133 # Clobber pch files, since they only work with the compiler version that
    134 # created them. Also clobber .o files, to make sure everything will be built
    135 # with the new compiler.
    136 if [[ "${OS}" = "Darwin" ]]; then
    137   XCODEBUILD_DIR="${THIS_DIR}/../../../xcodebuild"
    138 
    139   # Xcode groups .o files by project first, configuration second.
    140   if [[ -d "${XCODEBUILD_DIR}" ]]; then
    141     echo "Clobbering .o files for Xcode build"
    142     find "${XCODEBUILD_DIR}" -name '*.o' -exec rm {} +
    143   fi
    144 fi
    145 
    146 MAKE_DIR="${THIS_DIR}/../../../out"
    147 
    148 for CONFIG in Debug Release; do
    149   if [[ -d "${MAKE_DIR}/${CONFIG}/obj.target" ||
    150         -d "${MAKE_DIR}/${CONFIG}/obj.host" ]]; then
    151     echo "Clobbering ${CONFIG} PCH and .o files for make build"
    152     if [[ -d "${MAKE_DIR}/${CONFIG}/obj.target" ]]; then
    153       find "${MAKE_DIR}/${CONFIG}/obj.target" -name '*.gch' -exec rm {} +
    154       find "${MAKE_DIR}/${CONFIG}/obj.target" -name '*.o' -exec rm {} +
    155     fi
    156     if [[ -d "${MAKE_DIR}/${CONFIG}/obj.host" ]]; then
    157       find "${MAKE_DIR}/${CONFIG}/obj.host" -name '*.o' -exec rm {} +
    158     fi
    159   fi
    160 
    161   # ninja puts its output below ${MAKE_DIR} as well.
    162   if [[ -d "${MAKE_DIR}/${CONFIG}/obj" ]]; then
    163     echo "Clobbering ${CONFIG} PCH and .o files for ninja build"
    164     find "${MAKE_DIR}/${CONFIG}/obj" -name '*.gch' -exec rm {} +
    165     find "${MAKE_DIR}/${CONFIG}/obj" -name '*.o' -exec rm {} +
    166     find "${MAKE_DIR}/${CONFIG}/obj" -name '*.o.d' -exec rm {} +
    167   fi
    168 
    169   if [[ "${OS}" = "Darwin" ]]; then
    170     if [[ -d "${XCODEBUILD_DIR}/${CONFIG}/SharedPrecompiledHeaders" ]]; then
    171       echo "Clobbering ${CONFIG} PCH files for Xcode build"
    172       rm -rf "${XCODEBUILD_DIR}/${CONFIG}/SharedPrecompiledHeaders"
    173     fi
    174   fi
    175 done
    176 
    177 # Clobber NaCl toolchain stamp files, see http://crbug.com/159793
    178 if [[ -d "${MAKE_DIR}" ]]; then
    179   find "${MAKE_DIR}" -name 'stamp.untar' -exec rm {} +
    180 fi
    181 if [[ "${OS}" = "Darwin" ]]; then
    182   if [[ -d "${XCODEBUILD_DIR}" ]]; then
    183     find "${XCODEBUILD_DIR}" -name 'stamp.untar' -exec rm {} +
    184   fi
    185 fi
    186 
    187 if [[ -z "$force_local_build" ]]; then
    188   # Check if there's a prebuilt binary and if so just fetch that. That's faster,
    189   # and goma relies on having matching binary hashes on client and server too.
    190   CDS_URL=https://commondatastorage.googleapis.com/chromium-browser-clang
    191   CDS_FILE="clang-${CLANG_REVISION}.tgz"
    192   CDS_OUT_DIR=$(mktemp -d -t clang_download.XXXXXX)
    193   CDS_OUTPUT="${CDS_OUT_DIR}/${CDS_FILE}"
    194   if [ "${OS}" = "Linux" ]; then
    195     CDS_FULL_URL="${CDS_URL}/Linux_x64/${CDS_FILE}"
    196   elif [ "${OS}" = "Darwin" ]; then
    197     CDS_FULL_URL="${CDS_URL}/Mac/${CDS_FILE}"
    198   fi
    199   echo Trying to download prebuilt clang
    200   if which curl > /dev/null; then
    201     curl -L --fail "${CDS_FULL_URL}" -o "${CDS_OUTPUT}" || \
    202         rm -rf "${CDS_OUT_DIR}"
    203   elif which wget > /dev/null; then
    204     wget "${CDS_FULL_URL}" -O "${CDS_OUTPUT}" || rm -rf "${CDS_OUT_DIR}"
    205   else
    206     echo "Neither curl nor wget found. Please install one of these."
    207     exit 1
    208   fi
    209   if [ -f "${CDS_OUTPUT}" ]; then
    210     rm -rf "${LLVM_BUILD_DIR}/Release+Asserts"
    211     mkdir -p "${LLVM_BUILD_DIR}/Release+Asserts"
    212     tar -xzf "${CDS_OUTPUT}" -C "${LLVM_BUILD_DIR}/Release+Asserts"
    213     echo clang "${CLANG_REVISION}" unpacked
    214     echo "${CLANG_REVISION}" > "${STAMP_FILE}"
    215     rm -rf "${CDS_OUT_DIR}"
    216     exit 0
    217   else
    218     echo Did not find prebuilt clang at r"${CLANG_REVISION}", building
    219   fi
    220 fi
    221 
    222 if [[ -n "${with_android}" ]] && ! [[ -d "${ANDROID_NDK_DIR}" ]]; then
    223   echo "Android NDK not found at ${ANDROID_NDK_DIR}"
    224   echo "The Android NDK is needed to build a Clang whose -fsanitize=address"
    225   echo "works on Android. See "
    226   echo "http://code.google.com/p/chromium/wiki/AndroidBuildInstructions for how"
    227   echo "to install the NDK, or pass --without-android."
    228   exit 1
    229 fi
    230 
    231 echo Getting LLVM r"${CLANG_REVISION}" in "${LLVM_DIR}"
    232 if ! svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" \
    233                     "${LLVM_DIR}"; then
    234   echo Checkout failed, retrying
    235   rm -rf "${LLVM_DIR}"
    236   svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" "${LLVM_DIR}"
    237 fi
    238 
    239 echo Getting clang r"${CLANG_REVISION}" in "${CLANG_DIR}"
    240 svn co --force "${LLVM_REPO_URL}/cfe/trunk@${CLANG_REVISION}" "${CLANG_DIR}"
    241 
    242 echo Getting compiler-rt r"${CLANG_REVISION}" in "${COMPILER_RT_DIR}"
    243 svn co --force "${LLVM_REPO_URL}/compiler-rt/trunk@${CLANG_REVISION}" \
    244                "${COMPILER_RT_DIR}"
    245 
    246 # Echo all commands.
    247 set -x
    248 
    249 NUM_JOBS=3
    250 if [[ "${OS}" = "Linux" ]]; then
    251   NUM_JOBS="$(grep -c "^processor" /proc/cpuinfo)"
    252 elif [ "${OS}" = "Darwin" ]; then
    253   NUM_JOBS="$(sysctl -n hw.ncpu)"
    254 fi
    255 
    256 # Build bootstrap clang if requested.
    257 if [[ -n "${bootstrap}" ]]; then
    258   echo "Building bootstrap compiler"
    259   mkdir -p "${LLVM_BOOTSTRAP_DIR}"
    260   cd "${LLVM_BOOTSTRAP_DIR}"
    261   if [[ ! -f ./config.status ]]; then
    262     # The bootstrap compiler only needs to be able to build the real compiler,
    263     # so it needs no cross-compiler output support. In general, the host
    264     # compiler should be as similar to the final compiler as possible, so do
    265     # keep --disable-threads & co.
    266     ../llvm/configure \
    267         --enable-optimized \
    268         --enable-targets=host-only \
    269         --disable-threads \
    270         --disable-pthreads \
    271         --without-llvmgcc \
    272         --without-llvmgxx
    273   fi
    274   MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}"
    275   if [[ -n "${run_tests}" ]]; then
    276     make check-all
    277   fi
    278   cd -
    279   export CC="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang"
    280   export CXX="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang++"
    281   echo "Building final compiler"
    282 fi
    283 
    284 # Build clang (in a separate directory).
    285 # The clang bots have this path hardcoded in built/scripts/slave/compile.py,
    286 # so if you change it you also need to change these links.
    287 mkdir -p "${LLVM_BUILD_DIR}"
    288 cd "${LLVM_BUILD_DIR}"
    289 if [[ ! -f ./config.status ]]; then
    290   ../llvm/configure \
    291       --enable-optimized \
    292       --disable-threads \
    293       --disable-pthreads \
    294       --without-llvmgcc \
    295       --without-llvmgxx
    296 fi
    297 
    298 MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}"
    299 STRIP_FLAGS=
    300 if [ "${OS}" = "Darwin" ]; then
    301   # See http://crbug.com/256342
    302   STRIP_FLAGS=-x
    303 fi
    304 strip ${STRIP_FLAGS} Release+Asserts/bin/clang
    305 cd -
    306 
    307 if [[ -n "${with_android}" ]]; then
    308   # Make a standalone Android toolchain.
    309   ${ANDROID_NDK_DIR}/build/tools/make-standalone-toolchain.sh \
    310       --platform=android-14 \
    311       --install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
    312       --system=linux-x86_64 \
    313       --stl=stlport
    314 
    315   # Build ASan runtime for Android.
    316   # Note: LLVM_ANDROID_TOOLCHAIN_DIR is not relative to PWD, but to where we
    317   # build the runtime, i.e. third_party/llvm/projects/compiler-rt.
    318   cd "${LLVM_BUILD_DIR}"
    319   make -C tools/clang/runtime/ \
    320     LLVM_ANDROID_TOOLCHAIN_DIR="../../../llvm-build/android-toolchain"
    321   cd -
    322 fi
    323 
    324 # Build Chrome-specific clang tools. Paths in this list should be relative to
    325 # tools/clang.
    326 # For each tool directory, copy it into the clang tree and use clang's build
    327 # system to compile it.
    328 for CHROME_TOOL_DIR in ${chrome_tools}; do
    329   TOOL_SRC_DIR="${THIS_DIR}/../${CHROME_TOOL_DIR}"
    330   TOOL_DST_DIR="${LLVM_DIR}/tools/clang/tools/chrome-${CHROME_TOOL_DIR}"
    331   TOOL_BUILD_DIR="${LLVM_BUILD_DIR}/tools/clang/tools/chrome-${CHROME_TOOL_DIR}"
    332   rm -rf "${TOOL_DST_DIR}"
    333   cp -R "${TOOL_SRC_DIR}" "${TOOL_DST_DIR}"
    334   rm -rf "${TOOL_BUILD_DIR}"
    335   mkdir -p "${TOOL_BUILD_DIR}"
    336   cp "${TOOL_SRC_DIR}/Makefile" "${TOOL_BUILD_DIR}"
    337   MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}" -C "${TOOL_BUILD_DIR}"
    338 done
    339 
    340 if [[ -n "$run_tests" ]]; then
    341   # Run a few tests.
    342   PLUGIN_SRC_DIR="${THIS_DIR}/../plugins"
    343   "${PLUGIN_SRC_DIR}/tests/test.sh" "${LLVM_BUILD_DIR}/Release+Asserts"
    344   cd "${LLVM_BUILD_DIR}"
    345   make check-all
    346   cd -
    347 fi
    348 
    349 # After everything is done, log success for this revision.
    350 echo "${CLANG_REVISION}" > "${STAMP_FILE}"
    351