|
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=163674 |
|
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 COMPILER_RT_DIR="${LLVM_DIR}/projects/compiler-rt" |
|
19 STAMP_FILE="${LLVM_BUILD_DIR}/cr_build_revision" |
|
20 |
|
21 # ${A:-a} returns $A if it's set, a else. |
|
22 LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project} |
|
23 |
|
24 # Die if any command dies. |
|
25 set -e |
|
26 |
|
27 OS="$(uname -s)" |
|
28 |
|
29 # Parse command line options. |
|
30 force_local_build= |
|
31 mac_only= |
|
32 run_tests= |
|
33 bootstrap= |
|
34 while [[ $# > 0 ]]; do |
|
35 case $1 in |
|
36 --bootstrap) |
|
37 bootstrap=yes |
|
38 ;; |
|
39 --force-local-build) |
|
40 force_local_build=yes |
|
41 ;; |
|
42 --mac-only) |
|
43 mac_only=yes |
|
44 ;; |
|
45 --run-tests) |
|
46 run_tests=yes |
|
47 ;; |
|
48 --help) |
|
49 echo "usage: $0 [--force-local-build] [--mac-only] [--run-tests] " |
|
50 echo "--bootstrap: First build clang with CC, then with itself." |
|
51 echo "--force-local-build: Don't try to download prebuilt binaries." |
|
52 echo "--mac-only: Do initial download only on Mac systems." |
|
53 echo "--run-tests: Run tests after building. Only for local builds." |
|
54 exit 1 |
|
55 ;; |
|
56 esac |
|
57 shift |
|
58 done |
|
59 |
|
60 # --mac-only prevents the initial download on non-mac systems, but if clang has |
|
61 # already been downloaded in the past, this script keeps it up to date even if |
|
62 # --mac-only is passed in and the system isn't a mac. People who don't like this |
|
63 # can just delete their third_party/llvm-build directory. |
|
64 if [[ -n "$mac_only" ]] && [[ "${OS}" != "Darwin" ]] && |
|
65 [[ "$GYP_DEFINES" != *clang=1* ]] && ! [[ -d "${LLVM_BUILD_DIR}" ]]; then |
|
66 exit 0 |
|
67 fi |
|
68 |
|
69 # Xcode and clang don't get along when predictive compilation is enabled. |
|
70 # http://crbug.com/96315 |
|
71 if [[ "${OS}" = "Darwin" ]] && xcodebuild -version | grep -q 'Xcode 3.2' ; then |
|
72 XCONF=com.apple.Xcode |
|
73 if [[ "${GYP_GENERATORS}" != "make" ]] && \ |
|
74 [ "$(defaults read "${XCONF}" EnablePredictiveCompilation)" != "0" ]; then |
|
75 echo |
|
76 echo " HEARKEN!" |
|
77 echo "You're using Xcode3 and you have 'Predictive Compilation' enabled." |
|
78 echo "This does not work well with clang (http://crbug.com/96315)." |
|
79 echo "Disable it in Preferences->Building (lower right), or run" |
|
80 echo " defaults write ${XCONF} EnablePredictiveCompilation -boolean NO" |
|
81 echo "while Xcode is not running." |
|
82 echo |
|
83 fi |
|
84 |
|
85 SUB_VERSION=$(xcodebuild -version | sed -Ene 's/Xcode 3\.2\.([0-9]+)/\1/p') |
|
86 if [[ "${SUB_VERSION}" < 6 ]]; then |
|
87 echo |
|
88 echo " YOUR LD IS BUGGY!" |
|
89 echo "Please upgrade Xcode to at least 3.2.6." |
|
90 echo |
|
91 fi |
|
92 fi |
|
93 |
|
94 |
|
95 # Check if there's anything to be done, exit early if not. |
|
96 if [[ -f "${STAMP_FILE}" ]]; then |
|
97 PREVIOUSLY_BUILT_REVISON=$(cat "${STAMP_FILE}") |
|
98 if [[ -z "$force_local_build" ]] && \ |
|
99 [[ "${PREVIOUSLY_BUILT_REVISON}" = "${CLANG_REVISION}" ]]; then |
|
100 echo "Clang already at ${CLANG_REVISION}" |
|
101 exit 0 |
|
102 fi |
|
103 fi |
|
104 # To always force a new build if someone interrupts their build half way. |
|
105 rm -f "${STAMP_FILE}" |
|
106 |
|
107 # Clobber pch files, since they only work with the compiler version that |
|
108 # created them. Also clobber .o files, to make sure everything will be built |
|
109 # with the new compiler. |
|
110 if [[ "${OS}" = "Darwin" ]]; then |
|
111 XCODEBUILD_DIR="${THIS_DIR}/../../../xcodebuild" |
|
112 |
|
113 # Xcode groups .o files by project first, configuration second. |
|
114 if [[ -d "${XCODEBUILD_DIR}" ]]; then |
|
115 echo "Clobbering .o files for Xcode build" |
|
116 find "${XCODEBUILD_DIR}" -name '*.o' -exec rm {} + |
|
117 fi |
|
118 fi |
|
119 |
|
120 if [ -f "${THIS_DIR}/../../../WebKit.gyp" ]; then |
|
121 # We're inside a WebKit checkout. |
|
122 # TODO(thakis): try to unify the directory layout of the xcode- and |
|
123 # make-based builds. http://crbug.com/110455 |
|
124 MAKE_DIR="${THIS_DIR}/../../../../../../out" |
|
125 else |
|
126 # We're inside a Chromium checkout. |
|
127 MAKE_DIR="${THIS_DIR}/../../../out" |
|
128 fi |
|
129 |
|
130 for CONFIG in Debug Release; do |
|
131 if [[ -d "${MAKE_DIR}/${CONFIG}/obj.target" || |
|
132 -d "${MAKE_DIR}/${CONFIG}/obj.host" ]]; then |
|
133 echo "Clobbering ${CONFIG} PCH and .o files for make build" |
|
134 if [[ -d "${MAKE_DIR}/${CONFIG}/obj.target" ]]; then |
|
135 find "${MAKE_DIR}/${CONFIG}/obj.target" -name '*.gch' -exec rm {} + |
|
136 find "${MAKE_DIR}/${CONFIG}/obj.target" -name '*.o' -exec rm {} + |
|
137 fi |
|
138 if [[ -d "${MAKE_DIR}/${CONFIG}/obj.host" ]]; then |
|
139 find "${MAKE_DIR}/${CONFIG}/obj.host" -name '*.o' -exec rm {} + |
|
140 fi |
|
141 fi |
|
142 |
|
143 # ninja puts its output below ${MAKE_DIR} as well. |
|
144 if [[ -d "${MAKE_DIR}/${CONFIG}/obj" ]]; then |
|
145 echo "Clobbering ${CONFIG} PCH and .o files for ninja build" |
|
146 find "${MAKE_DIR}/${CONFIG}/obj" -name '*.gch' -exec rm {} + |
|
147 find "${MAKE_DIR}/${CONFIG}/obj" -name '*.o' -exec rm {} + |
|
148 find "${MAKE_DIR}/${CONFIG}/obj" -name '*.o.d' -exec rm {} + |
|
149 fi |
|
150 |
|
151 if [[ "${OS}" = "Darwin" ]]; then |
|
152 if [[ -d "${XCODEBUILD_DIR}/${CONFIG}/SharedPrecompiledHeaders" ]]; then |
|
153 echo "Clobbering ${CONFIG} PCH files for Xcode build" |
|
154 rm -rf "${XCODEBUILD_DIR}/${CONFIG}/SharedPrecompiledHeaders" |
|
155 fi |
|
156 fi |
|
157 done |
|
158 |
|
159 if [[ -z "$force_local_build" ]]; then |
|
160 # Check if there's a prebuilt binary and if so just fetch that. That's faster, |
|
161 # and goma relies on having matching binary hashes on client and server too. |
|
162 CDS_URL=https://commondatastorage.googleapis.com/chromium-browser-clang |
|
163 CDS_FILE="clang-${CLANG_REVISION}.tgz" |
|
164 CDS_OUT_DIR=$(mktemp -d -t clang_download.XXXXXX) |
|
165 CDS_OUTPUT="${CDS_OUT_DIR}/${CDS_FILE}" |
|
166 if [ "${OS}" = "Linux" ]; then |
|
167 CDS_FULL_URL="${CDS_URL}/Linux_x64/${CDS_FILE}" |
|
168 elif [ "${OS}" = "Darwin" ]; then |
|
169 CDS_FULL_URL="${CDS_URL}/Mac/${CDS_FILE}" |
|
170 fi |
|
171 echo Trying to download prebuilt clang |
|
172 if which curl > /dev/null; then |
|
173 curl -L --fail "${CDS_FULL_URL}" -o "${CDS_OUTPUT}" || \ |
|
174 rm -rf "${CDS_OUT_DIR}" |
|
175 elif which wget > /dev/null; then |
|
176 wget "${CDS_FULL_URL}" -O "${CDS_OUTPUT}" || rm -rf "${CDS_OUT_DIR}" |
|
177 else |
|
178 echo "Neither curl nor wget found. Please install one of these." |
|
179 exit 1 |
|
180 fi |
|
181 if [ -f "${CDS_OUTPUT}" ]; then |
|
182 rm -rf "${LLVM_BUILD_DIR}/Release+Asserts" |
|
183 mkdir -p "${LLVM_BUILD_DIR}/Release+Asserts" |
|
184 tar -xzf "${CDS_OUTPUT}" -C "${LLVM_BUILD_DIR}/Release+Asserts" |
|
185 echo clang "${CLANG_REVISION}" unpacked |
|
186 echo "${CLANG_REVISION}" > "${STAMP_FILE}" |
|
187 rm -rf "${CDS_OUT_DIR}" |
|
188 exit 0 |
|
189 else |
|
190 echo Did not find prebuilt clang at r"${CLANG_REVISION}", building |
|
191 fi |
|
192 fi |
|
193 |
|
194 echo Getting LLVM r"${CLANG_REVISION}" in "${LLVM_DIR}" |
|
195 if ! svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" \ |
|
196 "${LLVM_DIR}"; then |
|
197 echo Checkout failed, retrying |
|
198 rm -rf "${LLVM_DIR}" |
|
199 svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" "${LLVM_DIR}" |
|
200 fi |
|
201 |
|
202 echo Getting clang r"${CLANG_REVISION}" in "${CLANG_DIR}" |
|
203 svn co --force "${LLVM_REPO_URL}/cfe/trunk@${CLANG_REVISION}" "${CLANG_DIR}" |
|
204 |
|
205 echo Getting compiler-rt r"${CLANG_REVISION}" in "${COMPILER_RT_DIR}" |
|
206 svn co --force "${LLVM_REPO_URL}/compiler-rt/trunk@${CLANG_REVISION}" \ |
|
207 "${COMPILER_RT_DIR}" |
|
208 |
|
209 # Echo all commands. |
|
210 set -x |
|
211 |
|
212 NUM_JOBS=3 |
|
213 if [[ "${OS}" = "Linux" ]]; then |
|
214 NUM_JOBS="$(grep -c "^processor" /proc/cpuinfo)" |
|
215 elif [ "${OS}" = "Darwin" ]; then |
|
216 NUM_JOBS="$(sysctl -n hw.ncpu)" |
|
217 fi |
|
218 |
|
219 # Build bootstrap clang if requested. |
|
220 if [[ -n "${bootstrap}" ]]; then |
|
221 echo "Building bootstrap compiler" |
|
222 mkdir -p "${LLVM_BOOTSTRAP_DIR}" |
|
223 cd "${LLVM_BOOTSTRAP_DIR}" |
|
224 if [[ ! -f ./config.status ]]; then |
|
225 # The bootstrap compiler only needs to be able to build the real compiler, |
|
226 # so it needs no cross-compiler output support. In general, the host |
|
227 # compiler should be as similar to the final compiler as possible, so do |
|
228 # keep --disable-threads & co. |
|
229 ../llvm/configure \ |
|
230 --enable-optimized \ |
|
231 --enable-targets=host-only \ |
|
232 --disable-threads \ |
|
233 --disable-pthreads \ |
|
234 --without-llvmgcc \ |
|
235 --without-llvmgxx |
|
236 MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}" |
|
237 fi |
|
238 if [[ -n "${run_tests}" ]]; then |
|
239 make check-all |
|
240 fi |
|
241 cd - |
|
242 export CC="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang" |
|
243 export CXX="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang++" |
|
244 echo "Building final compiler" |
|
245 fi |
|
246 |
|
247 # Build clang (in a separate directory). |
|
248 # The clang bots have this path hardcoded in built/scripts/slave/compile.py, |
|
249 # so if you change it you also need to change these links. |
|
250 mkdir -p "${LLVM_BUILD_DIR}" |
|
251 cd "${LLVM_BUILD_DIR}" |
|
252 if [[ ! -f ./config.status ]]; then |
|
253 ../llvm/configure \ |
|
254 --enable-optimized \ |
|
255 --disable-threads \ |
|
256 --disable-pthreads \ |
|
257 --without-llvmgcc \ |
|
258 --without-llvmgxx |
|
259 fi |
|
260 |
|
261 MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}" |
|
262 cd - |
|
263 |
|
264 # Build plugin. |
|
265 # Copy it into the clang tree and use clang's build system to compile the |
|
266 # plugin. |
|
267 PLUGIN_SRC_DIR="${THIS_DIR}/../plugins" |
|
268 PLUGIN_DST_DIR="${LLVM_DIR}/tools/clang/tools/chrome-plugin" |
|
269 PLUGIN_BUILD_DIR="${LLVM_BUILD_DIR}/tools/clang/tools/chrome-plugin" |
|
270 rm -rf "${PLUGIN_DST_DIR}" |
|
271 cp -R "${PLUGIN_SRC_DIR}" "${PLUGIN_DST_DIR}" |
|
272 rm -rf "${PLUGIN_BUILD_DIR}" |
|
273 mkdir -p "${PLUGIN_BUILD_DIR}" |
|
274 cp "${PLUGIN_SRC_DIR}/Makefile" "${PLUGIN_BUILD_DIR}" |
|
275 MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}" -C "${PLUGIN_BUILD_DIR}" |
|
276 |
|
277 if [[ -n "$run_tests" ]]; then |
|
278 # Run a few tests. |
|
279 "${PLUGIN_SRC_DIR}/tests/test.sh" "${LLVM_BUILD_DIR}/Release+Asserts" |
|
280 cd "${LLVM_BUILD_DIR}" |
|
281 make check-all |
|
282 cd - |
|
283 fi |
|
284 |
|
285 # After everything is done, log success for this revision. |
|
286 echo "${CLANG_REVISION}" > "${STAMP_FILE}" |