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.
6 # This script will check out llvm and clang into third_party/llvm and build it.
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.
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"
23 # ${A:-a} returns $A if it's set, a else.
24 LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project}
26 if [[ -z "$GYP_DEFINES" ]]; then
29 if [[ -z "$GYP_GENERATORS" ]]; then
34 # Die if any command dies, error on undefined variable expansions.
39 # Parse command line options.
45 chrome_tools="plugins blink_gc_plugin"
48 if [[ "${OS}" = "Darwin" ]]; then
51 if [ "${OS}" = "FreeBSD" ]; then
57 while [[ $# > 0 ]]; do
76 if [[ $# == 0 ]]; then
77 echo "--with-chrome-tools requires an argument."
84 if [[ $# == 0 ]]; then
85 echo "--gcc-toolchain requires an argument."
88 if [[ -x "$1/bin/gcc" ]]; then
91 echo "Invalid --gcc-toolchain: '$1'."
92 echo "'$1/bin/gcc' does not appear to be valid."
98 echo "usage: $0 [--force-local-build] [--mac-only] [--run-tests] "
99 echo "--bootstrap: First build clang with CC, then with itself."
100 echo "--force-local-build: Don't try to download prebuilt binaries."
101 echo "--mac-only: Do initial download only on Mac systems."
102 echo "--run-tests: Run tests after building. Only for local builds."
103 echo "--without-android: Don't build ASan Android runtime library."
104 echo "--with-chrome-tools: Select which chrome tools to build." \
105 "Defaults to plugins."
106 echo " Example: --with-chrome-tools 'plugins empty-string'"
107 echo "--gcc-toolchain: Set the prefix for which GCC version should"
108 echo " be used for building. For example, to use gcc in"
109 echo " /opt/foo/bin/gcc, use '--gcc-toolchain '/opt/foo"
114 echo "Unknown argument: '$1'."
115 echo "Use --help for help."
122 # --mac-only prevents the initial download on non-mac systems, but if clang has
123 # already been downloaded in the past, this script keeps it up to date even if
124 # --mac-only is passed in and the system isn't a mac. People who don't like this
125 # can just delete their third_party/llvm-build directory.
126 if [[ -n "$mac_only" ]] && [[ "${OS}" != "Darwin" ]] &&
127 [[ ! ( "$GYP_DEFINES" =~ .*(clang|tsan|asan|lsan|msan)=1.* ) ]] &&
128 ! [[ -d "${LLVM_BUILD_DIR}" ]]; then
132 # Xcode and clang don't get along when predictive compilation is enabled.
133 # http://crbug.com/96315
134 if [[ "${OS}" = "Darwin" ]] && xcodebuild -version | grep -q 'Xcode 3.2' ; then
135 XCONF=com.apple.Xcode
136 if [[ "${GYP_GENERATORS}" != "make" ]] && \
137 [ "$(defaults read "${XCONF}" EnablePredictiveCompilation)" != "0" ]; then
140 echo "You're using Xcode3 and you have 'Predictive Compilation' enabled."
141 echo "This does not work well with clang (http://crbug.com/96315)."
142 echo "Disable it in Preferences->Building (lower right), or run"
143 echo " defaults write ${XCONF} EnablePredictiveCompilation -boolean NO"
144 echo "while Xcode is not running."
148 SUB_VERSION=$(xcodebuild -version | sed -Ene 's/Xcode 3\.2\.([0-9]+)/\1/p')
149 if [[ "${SUB_VERSION}" < 6 ]]; then
151 echo " YOUR LD IS BUGGY!"
152 echo "Please upgrade Xcode to at least 3.2.6."
158 # Check if there's anything to be done, exit early if not.
159 if [[ -f "${STAMP_FILE}" ]]; then
160 PREVIOUSLY_BUILT_REVISON=$(cat "${STAMP_FILE}")
161 if [[ -z "$force_local_build" ]] && \
162 [[ "${PREVIOUSLY_BUILT_REVISON}" = "${CLANG_REVISION}" ]]; then
163 echo "Clang already at ${CLANG_REVISION}"
167 # To always force a new build if someone interrupts their build half way.
168 rm -f "${STAMP_FILE}"
171 # Clobber build files. PCH files only work with the compiler that created them.
172 # We delete .o files to make sure all files are built with the new compiler.
173 echo "Clobbering build files"
174 MAKE_DIR="${THIS_DIR}/../../../out"
175 XCODEBUILD_DIR="${THIS_DIR}/../../../xcodebuild"
176 for DIR in "${XCODEBUILD_DIR}" "${MAKE_DIR}/Debug" "${MAKE_DIR}/Release"; do
177 if [[ -d "${DIR}" ]]; then
178 find "${DIR}" -name '*.o' -exec rm {} +
179 find "${DIR}" -name '*.o.d' -exec rm {} +
180 find "${DIR}" -name '*.gch' -exec rm {} +
181 find "${DIR}" -name '*.dylib' -exec rm -rf {} +
182 find "${DIR}" -name 'SharedPrecompiledHeaders' -exec rm -rf {} +
186 # Clobber NaCl toolchain stamp files, see http://crbug.com/159793
187 if [[ -d "${MAKE_DIR}" ]]; then
188 find "${MAKE_DIR}" -name 'stamp.untar' -exec rm {} +
190 if [[ "${OS}" = "Darwin" ]]; then
191 if [[ -d "${XCODEBUILD_DIR}" ]]; then
192 find "${XCODEBUILD_DIR}" -name 'stamp.untar' -exec rm {} +
196 if [[ -z "$force_local_build" ]]; then
197 # Check if there's a prebuilt binary and if so just fetch that. That's faster,
198 # and goma relies on having matching binary hashes on client and server too.
199 CDS_URL=https://commondatastorage.googleapis.com/chromium-browser-clang
200 CDS_FILE="clang-${CLANG_REVISION}.tgz"
201 CDS_OUT_DIR=$(mktemp -d -t clang_download.XXXXXX)
202 CDS_OUTPUT="${CDS_OUT_DIR}/${CDS_FILE}"
203 if [ "${OS}" = "Linux" ]; then
204 CDS_FULL_URL="${CDS_URL}/Linux_x64/${CDS_FILE}"
205 elif [ "${OS}" = "Darwin" ]; then
206 CDS_FULL_URL="${CDS_URL}/Mac/${CDS_FILE}"
208 echo Trying to download prebuilt clang
209 if which curl > /dev/null; then
210 curl -L --fail "${CDS_FULL_URL}" -o "${CDS_OUTPUT}" || \
211 rm -rf "${CDS_OUT_DIR}"
212 elif which wget > /dev/null; then
213 wget "${CDS_FULL_URL}" -O "${CDS_OUTPUT}" || rm -rf "${CDS_OUT_DIR}"
215 echo "Neither curl nor wget found. Please install one of these."
218 if [ -f "${CDS_OUTPUT}" ]; then
219 rm -rf "${LLVM_BUILD_DIR}/Release+Asserts"
220 mkdir -p "${LLVM_BUILD_DIR}/Release+Asserts"
221 tar -xzf "${CDS_OUTPUT}" -C "${LLVM_BUILD_DIR}/Release+Asserts"
222 echo clang "${CLANG_REVISION}" unpacked
223 echo "${CLANG_REVISION}" > "${STAMP_FILE}"
224 rm -rf "${CDS_OUT_DIR}"
227 echo Did not find prebuilt clang at r"${CLANG_REVISION}", building
231 if [[ -n "${with_android}" ]] && ! [[ -d "${ANDROID_NDK_DIR}" ]]; then
232 echo "Android NDK not found at ${ANDROID_NDK_DIR}"
233 echo "The Android NDK is needed to build a Clang whose -fsanitize=address"
234 echo "works on Android. See "
235 echo "http://code.google.com/p/chromium/wiki/AndroidBuildInstructions for how"
236 echo "to install the NDK, or pass --without-android."
240 echo Getting LLVM r"${CLANG_REVISION}" in "${LLVM_DIR}"
241 if ! svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" \
243 echo Checkout failed, retrying
245 svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" "${LLVM_DIR}"
248 echo Getting clang r"${CLANG_REVISION}" in "${CLANG_DIR}"
249 svn co --force "${LLVM_REPO_URL}/cfe/trunk@${CLANG_REVISION}" "${CLANG_DIR}"
251 echo Getting compiler-rt r"${CLANG_REVISION}" in "${COMPILER_RT_DIR}"
252 svn co --force "${LLVM_REPO_URL}/compiler-rt/trunk@${CLANG_REVISION}" \
259 if [[ "${OS}" = "Linux" ]]; then
260 NUM_JOBS="$(grep -c "^processor" /proc/cpuinfo)"
261 elif [ "${OS}" = "Darwin" -o "${OS}" = "FreeBSD" ]; then
262 NUM_JOBS="$(sysctl -n hw.ncpu)"
265 if [[ -n "${gcc_toolchain}" ]]; then
266 # Use the specified gcc installation for building.
267 export CC="$gcc_toolchain/bin/gcc"
268 export CXX="$gcc_toolchain/bin/g++"
274 # Build bootstrap clang if requested.
275 if [[ -n "${bootstrap}" ]]; then
276 echo "Building bootstrap compiler"
277 mkdir -p "${LLVM_BOOTSTRAP_DIR}"
278 cd "${LLVM_BOOTSTRAP_DIR}"
279 if [[ ! -f ./config.status ]]; then
280 # The bootstrap compiler only needs to be able to build the real compiler,
281 # so it needs no cross-compiler output support. In general, the host
282 # compiler should be as similar to the final compiler as possible, so do
283 # keep --disable-threads & co.
286 --enable-targets=host-only \
293 if [[ -n "${gcc_toolchain}" ]]; then
294 # Copy that gcc's stdlibc++.so.6 to the build dir, so the bootstrap
295 # compiler can start.
296 mkdir -p Release+Asserts/lib
297 cp -v "$(${CXX} -print-file-name=libstdc++.so.6)" \
298 "Release+Asserts/lib/"
302 MACOSX_DEPLOYMENT_TARGET=10.5 ${MAKE} -j"${NUM_JOBS}"
303 if [[ -n "${run_tests}" ]]; then
307 export CC="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang"
308 export CXX="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang++"
310 if [[ -n "${gcc_toolchain}" ]]; then
311 # Tell the bootstrap compiler to use a specific gcc prefix to search
312 # for standard library headers and shared object file.
313 export CFLAGS="--gcc-toolchain=${gcc_toolchain}"
314 export CXXFLAGS="--gcc-toolchain=${gcc_toolchain}"
317 echo "Building final compiler"
320 # Build clang (in a separate directory).
321 # The clang bots have this path hardcoded in built/scripts/slave/compile.py,
322 # so if you change it you also need to change these links.
323 mkdir -p "${LLVM_BUILD_DIR}"
324 cd "${LLVM_BUILD_DIR}"
325 if [[ ! -f ./config.status ]]; then
334 if [[ -n "${gcc_toolchain}" ]]; then
335 # Copy in the right stdlibc++.so.6 so clang can start.
336 mkdir -p Release+Asserts/lib
337 cp -v "$(${CXX} ${CXXFLAGS} -print-file-name=libstdc++.so.6)" \
340 MACOSX_DEPLOYMENT_TARGET=10.5 ${MAKE} -j"${NUM_JOBS}"
342 if [ "${OS}" = "Darwin" ]; then
343 # See http://crbug.com/256342
346 strip ${STRIP_FLAGS} Release+Asserts/bin/clang
349 if [[ -n "${with_android}" ]]; then
350 # Make a standalone Android toolchain.
351 ${ANDROID_NDK_DIR}/build/tools/make-standalone-toolchain.sh \
352 --platform=android-14 \
353 --install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
354 --system=linux-x86_64 \
357 # Build ASan runtime for Android.
358 # Note: LLVM_ANDROID_TOOLCHAIN_DIR is not relative to PWD, but to where we
359 # build the runtime, i.e. third_party/llvm/projects/compiler-rt.
360 cd "${LLVM_BUILD_DIR}"
361 ${MAKE} -C tools/clang/runtime/ \
362 LLVM_ANDROID_TOOLCHAIN_DIR="../../../llvm-build/android-toolchain"
366 # Build Chrome-specific clang tools. Paths in this list should be relative to
368 # For each tool directory, copy it into the clang tree and use clang's build
369 # system to compile it.
370 for CHROME_TOOL_DIR in ${chrome_tools}; do
371 TOOL_SRC_DIR="${THIS_DIR}/../${CHROME_TOOL_DIR}"
372 TOOL_DST_DIR="${LLVM_DIR}/tools/clang/tools/chrome-${CHROME_TOOL_DIR}"
373 TOOL_BUILD_DIR="${LLVM_BUILD_DIR}/tools/clang/tools/chrome-${CHROME_TOOL_DIR}"
374 rm -rf "${TOOL_DST_DIR}"
375 cp -R "${TOOL_SRC_DIR}" "${TOOL_DST_DIR}"
376 rm -rf "${TOOL_BUILD_DIR}"
377 mkdir -p "${TOOL_BUILD_DIR}"
378 cp "${TOOL_SRC_DIR}/Makefile" "${TOOL_BUILD_DIR}"
379 MACOSX_DEPLOYMENT_TARGET=10.5 ${MAKE} -j"${NUM_JOBS}" -C "${TOOL_BUILD_DIR}"
382 if [[ -n "$run_tests" ]]; then
384 for CHROME_TOOL_DIR in ${chrome_tools}; do
385 TOOL_SRC_DIR="${THIS_DIR}/../${CHROME_TOOL_DIR}"
386 if [[ -f "${TOOL_SRC_DIR}/tests/test.sh" ]]; then
387 "${TOOL_SRC_DIR}/tests/test.sh" "${LLVM_BUILD_DIR}/Release+Asserts"
390 cd "${LLVM_BUILD_DIR}"
395 # After everything is done, log success for this revision.
396 echo "${CLANG_REVISION}" > "${STAMP_FILE}"