Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: tools/clang/scripts/update.py

Issue 2350583002: Starting work on full GN build (Closed)
Patch Set: Fixes for Fuchsia and Flutter. Cleanup. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/BUILD.gn ('k') | tools/clang/scripts/update.sh » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
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 """Windows can't run .sh files, so this is a Python implementation of
7 update.sh. This script should replace update.sh on all platforms eventually."""
8
9 import argparse
10 import contextlib
11 import cStringIO
12 import glob
13 import os
14 import pipes
15 import re
16 import shutil
17 import subprocess
18 import stat
19 import sys
20 import tarfile
21 import time
22 import urllib2
23 import zipfile
24
25 # Do NOT CHANGE this if you don't know what you're doing -- see
26 # https://code.google.com/p/chromium/wiki/UpdatingClang
27 # Reverting problematic clang rolls is safe, though.
28 # Note: this revision is only used for Windows. Other platforms use update.sh.
29 # TODO(thakis): Use the same revision on Windows and non-Windows.
30 # TODO(thakis): Remove update.sh, use update.py everywhere.
31 LLVM_WIN_REVISION = '242415'
32
33 use_head_revision = 'LLVM_FORCE_HEAD_REVISION' in os.environ
34 if use_head_revision:
35 LLVM_WIN_REVISION = 'HEAD'
36
37 # This is incremented when pushing a new build of Clang at the same revision.
38 CLANG_SUB_REVISION=1
39
40 PACKAGE_VERSION = "%s-%s" % (LLVM_WIN_REVISION, CLANG_SUB_REVISION)
41
42 # Path constants. (All of these should be absolute paths.)
43 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
44 CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
45 THIRD_PARTY_DIR = os.path.join(CHROMIUM_DIR, 'third_party')
46 LLVM_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm')
47 LLVM_BOOTSTRAP_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm-bootstrap')
48 LLVM_BOOTSTRAP_INSTALL_DIR = os.path.join(THIRD_PARTY_DIR,
49 'llvm-bootstrap-install')
50 CHROME_TOOLS_SHIM_DIR = os.path.join(LLVM_DIR, 'tools', 'chrometools')
51 LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build',
52 'Release+Asserts')
53 COMPILER_RT_BUILD_DIR = os.path.join(LLVM_BUILD_DIR, '32bit-compiler-rt')
54 CLANG_DIR = os.path.join(LLVM_DIR, 'tools', 'clang')
55 LLD_DIR = os.path.join(LLVM_DIR, 'tools', 'lld')
56 COMPILER_RT_DIR = os.path.join(LLVM_DIR, 'projects', 'compiler-rt')
57 LIBCXX_DIR = os.path.join(LLVM_DIR, 'projects', 'libcxx')
58 LIBCXXABI_DIR = os.path.join(LLVM_DIR, 'projects', 'libcxxabi')
59 LLVM_BUILD_TOOLS_DIR = os.path.abspath(
60 os.path.join(LLVM_DIR, '..', 'llvm-build-tools'))
61 STAMP_FILE = os.path.join(LLVM_DIR, '..', 'llvm-build', 'cr_build_revision')
62 BINUTILS_DIR = os.path.join(THIRD_PARTY_DIR, 'binutils')
63 VERSION = '3.8.0'
64
65 # URL for pre-built binaries.
66 CDS_URL = 'https://commondatastorage.googleapis.com/chromium-browser-clang'
67
68 LLVM_REPO_URL='https://llvm.org/svn/llvm-project'
69 if 'LLVM_REPO_URL' in os.environ:
70 LLVM_REPO_URL = os.environ['LLVM_REPO_URL']
71
72
73 def DownloadUrl(url, output_file):
74 """Download url into output_file."""
75 CHUNK_SIZE = 4096
76 TOTAL_DOTS = 10
77 sys.stdout.write('Downloading %s ' % url)
78 sys.stdout.flush()
79 response = urllib2.urlopen(url)
80 total_size = int(response.info().getheader('Content-Length').strip())
81 bytes_done = 0
82 dots_printed = 0
83 while True:
84 chunk = response.read(CHUNK_SIZE)
85 if not chunk:
86 break
87 output_file.write(chunk)
88 bytes_done += len(chunk)
89 num_dots = TOTAL_DOTS * bytes_done / total_size
90 sys.stdout.write('.' * (num_dots - dots_printed))
91 sys.stdout.flush()
92 dots_printed = num_dots
93 print ' Done.'
94
95
96 def ReadStampFile():
97 """Return the contents of the stamp file, or '' if it doesn't exist."""
98 try:
99 with open(STAMP_FILE, 'r') as f:
100 return f.read()
101 except IOError:
102 return ''
103
104
105 def WriteStampFile(s):
106 """Write s to the stamp file."""
107 if not os.path.exists(os.path.dirname(STAMP_FILE)):
108 os.makedirs(os.path.dirname(STAMP_FILE))
109 with open(STAMP_FILE, 'w') as f:
110 f.write(s)
111
112
113 def GetSvnRevision(svn_repo):
114 """Returns current revision of the svn repo at svn_repo."""
115 svn_info = subprocess.check_output('svn info ' + svn_repo, shell=True)
116 m = re.search(r'Revision: (\d+)', svn_info)
117 return m.group(1)
118
119
120 def RmTree(dir):
121 """Delete dir."""
122 def ChmodAndRetry(func, path, _):
123 # Subversion can leave read-only files around.
124 if not os.access(path, os.W_OK):
125 os.chmod(path, stat.S_IWUSR)
126 return func(path)
127 raise
128
129 shutil.rmtree(dir, onerror=ChmodAndRetry)
130
131
132 def RunCommand(command, msvc_arch=None, env=None, fail_hard=True):
133 """Run command and return success (True) or failure; or if fail_hard is
134 True, exit on failure. If msvc_arch is set, runs the command in a
135 shell with the msvc tools for that architecture."""
136
137 if msvc_arch and sys.platform == 'win32':
138 command = GetVSVersion().SetupScript(msvc_arch) + ['&&'] + command
139
140 # https://docs.python.org/2/library/subprocess.html:
141 # "On Unix with shell=True [...] if args is a sequence, the first item
142 # specifies the command string, and any additional items will be treated as
143 # additional arguments to the shell itself. That is to say, Popen does the
144 # equivalent of:
145 # Popen(['/bin/sh', '-c', args[0], args[1], ...])"
146 #
147 # We want to pass additional arguments to command[0], not to the shell,
148 # so manually join everything into a single string.
149 # Annoyingly, for "svn co url c:\path", pipes.quote() thinks that it should
150 # quote c:\path but svn can't handle quoted paths on Windows. Since on
151 # Windows follow-on args are passed to args[0] instead of the shell, don't
152 # do the single-string transformation there.
153 if sys.platform != 'win32':
154 command = ' '.join([pipes.quote(c) for c in command])
155 print 'Running', command
156 if subprocess.call(command, env=env, shell=True) == 0:
157 return True
158 print 'Failed.'
159 if fail_hard:
160 sys.exit(1)
161 return False
162
163
164 def CopyFile(src, dst):
165 """Copy a file from src to dst."""
166 shutil.copy(src, dst)
167 print "Copying %s to %s" % (src, dst)
168
169
170 def CopyDirectoryContents(src, dst, filename_filter=None):
171 """Copy the files from directory src to dst
172 with an optional filename filter."""
173 if not os.path.exists(dst):
174 os.makedirs(dst)
175 for root, _, files in os.walk(src):
176 for f in files:
177 if filename_filter and not re.match(filename_filter, f):
178 continue
179 CopyFile(os.path.join(root, f), dst)
180
181
182 def Checkout(name, url, dir):
183 """Checkout the SVN module at url into dir. Use name for the log message."""
184 print "Checking out %s r%s into '%s'" % (name, LLVM_WIN_REVISION, dir)
185
186 command = ['svn', 'checkout', '--force', url + '@' + LLVM_WIN_REVISION, dir]
187 if RunCommand(command, fail_hard=False):
188 return
189
190 if os.path.isdir(dir):
191 print "Removing %s." % (dir)
192 RmTree(dir)
193
194 print "Retrying."
195 RunCommand(command)
196
197
198 def RevertPreviouslyPatchedFiles():
199 print 'Reverting previously patched files'
200 files = [
201 '%(clang)s/test/Index/crash-recovery-modules.m',
202 '%(clang)s/unittests/libclang/LibclangTest.cpp',
203 '%(compiler_rt)s/lib/asan/asan_rtl.cc',
204 '%(compiler_rt)s/test/asan/TestCases/Linux/new_array_cookie_test.cc',
205 '%(llvm)s/test/DebugInfo/gmlt.ll',
206 '%(llvm)s/lib/CodeGen/SpillPlacement.cpp',
207 '%(llvm)s/lib/CodeGen/SpillPlacement.h',
208 '%(llvm)s/lib/Transforms/Instrumentation/MemorySanitizer.cpp',
209 '%(clang)s/test/Driver/env.c',
210 '%(clang)s/lib/Frontend/InitPreprocessor.cpp',
211 '%(clang)s/test/Frontend/exceptions.c',
212 '%(clang)s/test/Preprocessor/predefined-exceptions.m',
213 '%(llvm)s/test/Bindings/Go/go.test',
214 '%(clang)s/lib/Parse/ParseExpr.cpp',
215 '%(clang)s/lib/Parse/ParseTemplate.cpp',
216 '%(clang)s/lib/Sema/SemaDeclCXX.cpp',
217 '%(clang)s/lib/Sema/SemaExprCXX.cpp',
218 '%(clang)s/test/SemaCXX/default2.cpp',
219 '%(clang)s/test/SemaCXX/typo-correction-delayed.cpp',
220 '%(compiler_rt)s/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.c c',
221 '%(compiler_rt)s/test/tsan/signal_segv_handler.cc',
222 '%(compiler_rt)s/lib/sanitizer_common/sanitizer_coverage_libcdep.cc',
223 '%(compiler_rt)s/cmake/config-ix.cmake',
224 '%(compiler_rt)s/CMakeLists.txt',
225 '%(compiler_rt)s/lib/ubsan/ubsan_platform.h',
226 ]
227 for f in files:
228 f = f % {
229 'clang': CLANG_DIR,
230 'compiler_rt': COMPILER_RT_DIR,
231 'llvm': LLVM_DIR,
232 }
233 if os.path.exists(f):
234 os.remove(f) # For unversioned files.
235 RunCommand(['svn', 'revert', f])
236
237
238 def ApplyLocalPatches():
239 # There's no patch program on Windows by default. We don't need patches on
240 # Windows yet, and maybe this not working on Windows will motivate us to
241 # remove patches over time.
242 assert sys.platform != 'win32'
243
244 # Apply patch for tests failing with --disable-pthreads (llvm.org/PR11974)
245 clang_patches = [ r"""\
246 --- test/Index/crash-recovery-modules.m (revision 202554)
247 +++ test/Index/crash-recovery-modules.m (working copy)
248 @@ -12,6 +12,8 @@
249
250 // REQUIRES: crash-recovery
251 // REQUIRES: shell
252 +// XFAIL: *
253 +// (PR11974)
254
255 @import Crash;
256 """, r"""\
257 --- unittests/libclang/LibclangTest.cpp (revision 215949)
258 +++ unittests/libclang/LibclangTest.cpp (working copy)
259 @@ -431,7 +431,7 @@
260 EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
261 }
262
263 -TEST_F(LibclangReparseTest, ReparseWithModule) {
264 +TEST_F(LibclangReparseTest, DISABLED_ReparseWithModule) {
265 const char *HeaderTop = "#ifndef H\n#define H\nstruct Foo { int bar;";
266 const char *HeaderBottom = "\n};\n#endif\n";
267 const char *MFile = "#include \"HeaderFile.h\"\nint main() {"
268 """
269 ]
270
271 # This Go bindings test doesn't work after bootstrap on Linux, PR21552.
272 llvm_patches = [ r"""\
273 --- test/Bindings/Go/go.test (revision 223109)
274 +++ test/Bindings/Go/go.test (working copy)
275 @@ -1,3 +1,3 @@
276 -; RUN: llvm-go test llvm.org/llvm/bindings/go/llvm
277 +; RUN: true
278
279 ; REQUIRES: shell
280 """
281 ]
282
283 # The UBSan run-time, which is now bundled with the ASan run-time, doesn't
284 # work on Mac OS X 10.8 (PR23539).
285 compiler_rt_patches = [ r"""\
286 --- CMakeLists.txt (revision 241602)
287 +++ CMakeLists.txt (working copy)
288 @@ -305,6 +305,7 @@
289 list(APPEND SANITIZER_COMMON_SUPPORTED_OS iossim)
290 endif()
291 endif()
292 + set(SANITIZER_MIN_OSX_VERSION "10.7")
293 if(SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.7")
294 message(FATAL_ERROR "Too old OS X version: ${SANITIZER_MIN_OSX_VERSION}")
295 endif()
296 """
297 ]
298
299 for path, patches in [(LLVM_DIR, llvm_patches),
300 (CLANG_DIR, clang_patches),
301 (COMPILER_RT_DIR, compiler_rt_patches)]:
302 print 'Applying patches in', path
303 for patch in patches:
304 print patch
305 p = subprocess.Popen( ['patch', '-p0', '-d', path], stdin=subprocess.PIPE)
306 (stdout, stderr) = p.communicate(input=patch)
307 if p.returncode != 0:
308 raise RuntimeError('stdout %s, stderr %s' % (stdout, stderr))
309
310
311 def DeleteChromeToolsShim():
312 shutil.rmtree(CHROME_TOOLS_SHIM_DIR, ignore_errors=True)
313
314
315 def CreateChromeToolsShim():
316 """Hooks the Chrome tools into the LLVM build.
317
318 Several Chrome tools have dependencies on LLVM/Clang libraries. The LLVM build
319 detects implicit tools in the tools subdirectory, so this helper install a
320 shim CMakeLists.txt that forwards to the real directory for the Chrome tools.
321
322 Note that the shim directory name intentionally has no - or _. The implicit
323 tool detection logic munges them in a weird way."""
324 assert not any(i in os.path.basename(CHROME_TOOLS_SHIM_DIR) for i in '-_')
325 os.mkdir(CHROME_TOOLS_SHIM_DIR)
326 with file(os.path.join(CHROME_TOOLS_SHIM_DIR, 'CMakeLists.txt'), 'w') as f:
327 f.write('# Automatically generated by tools/clang/scripts/update.py. ' +
328 'Do not edit.\n')
329 f.write('# Since tools/clang is located in another directory, use the \n')
330 f.write('# two arg version to specify where build artifacts go. CMake\n')
331 f.write('# disallows reuse of the same binary dir for multiple source\n')
332 f.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
333 f.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
334 f.write('if (CHROMIUM_TOOLS_SRC)\n')
335 f.write(' add_subdirectory(${CHROMIUM_TOOLS_SRC} ' +
336 '${CMAKE_CURRENT_BINARY_DIR}/a)\n')
337 f.write('endif (CHROMIUM_TOOLS_SRC)\n')
338
339
340 def AddCMakeToPath():
341 """Download CMake and add it to PATH."""
342 if sys.platform == 'win32':
343 zip_name = 'cmake-3.2.2-win32-x86.zip'
344 cmake_dir = os.path.join(LLVM_BUILD_TOOLS_DIR,
345 'cmake-3.2.2-win32-x86', 'bin')
346 else:
347 suffix = 'Darwin' if sys.platform == 'darwin' else 'Linux'
348 zip_name = 'cmake310_%s.tgz' % suffix
349 cmake_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'cmake310', 'bin')
350 if not os.path.exists(cmake_dir):
351 if not os.path.exists(LLVM_BUILD_TOOLS_DIR):
352 os.makedirs(LLVM_BUILD_TOOLS_DIR)
353 # The cmake archive is smaller than 20 MB, small enough to keep in memory:
354 with contextlib.closing(cStringIO.StringIO()) as f:
355 DownloadUrl(CDS_URL + '/tools/' + zip_name, f)
356 f.seek(0)
357 if zip_name.endswith('.zip'):
358 zipfile.ZipFile(f).extractall(path=LLVM_BUILD_TOOLS_DIR)
359 else:
360 tarfile.open(mode='r:gz', fileobj=f).extractall(path=
361 LLVM_BUILD_TOOLS_DIR)
362 os.environ['PATH'] = cmake_dir + os.pathsep + os.environ.get('PATH', '')
363
364 vs_version = None
365 def GetVSVersion():
366 global vs_version
367 if vs_version:
368 return vs_version
369
370 # Try using the toolchain in depot_tools.
371 # This sets environment variables used by SelectVisualStudioVersion below.
372 sys.path.append(os.path.join(CHROMIUM_DIR, 'build'))
373 import vs_toolchain
374 vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
375
376 # Use gyp to find the MSVS installation, either in depot_tools as per above,
377 # or a system-wide installation otherwise.
378 sys.path.append(os.path.join(CHROMIUM_DIR, 'tools', 'gyp', 'pylib'))
379 import gyp.MSVSVersion
380 vs_version = gyp.MSVSVersion.SelectVisualStudioVersion('2013')
381 return vs_version
382
383
384 def UpdateClang(args):
385 print 'Updating Clang to %s...' % PACKAGE_VERSION
386 if ReadStampFile() == PACKAGE_VERSION:
387 print 'Already up to date.'
388 return 0
389
390 # Reset the stamp file in case the build is unsuccessful.
391 WriteStampFile('')
392
393 if not args.force_local_build:
394 cds_file = "clang-%s.tgz" % PACKAGE_VERSION
395 cds_full_url = CDS_URL + '/Win/' + cds_file
396
397 # Check if there's a prebuilt binary and if so just fetch that. That's
398 # faster, and goma relies on having matching binary hashes on client and
399 # server too.
400 print 'Trying to download prebuilt clang'
401
402 # clang packages are smaller than 50 MB, small enough to keep in memory.
403 with contextlib.closing(cStringIO.StringIO()) as f:
404 try:
405 DownloadUrl(cds_full_url, f)
406 f.seek(0)
407 tarfile.open(mode='r:gz', fileobj=f).extractall(path=LLVM_BUILD_DIR)
408 print 'clang %s unpacked' % PACKAGE_VERSION
409 # Download the gold plugin if requested to by an environment variable.
410 # This is used by the CFI ClusterFuzz bot.
411 if 'LLVM_DOWNLOAD_GOLD_PLUGIN' in os.environ:
412 RunCommand(['python', CHROMIUM_DIR+'/build/download_gold_plugin.py'])
413 WriteStampFile(PACKAGE_VERSION)
414 return 0
415 except urllib2.HTTPError:
416 print 'Did not find prebuilt clang %s, building locally' % cds_file
417
418 AddCMakeToPath()
419
420 RevertPreviouslyPatchedFiles()
421 DeleteChromeToolsShim()
422
423 Checkout('LLVM', LLVM_REPO_URL + '/llvm/trunk', LLVM_DIR)
424 Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR)
425 if sys.platform == 'win32':
426 Checkout('LLD', LLVM_REPO_URL + '/lld/trunk', LLD_DIR)
427 Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR)
428 if sys.platform == 'darwin':
429 # clang needs a libc++ checkout, else -stdlib=libc++ won't find includes
430 # (i.e. this is needed for bootstrap builds).
431 Checkout('libcxx', LLVM_REPO_URL + '/libcxx/trunk', LIBCXX_DIR)
432 # While we're bundling our own libc++ on OS X, we need to compile libc++abi
433 # into it too (since OS X 10.6 doesn't have libc++abi.dylib either).
434 Checkout('libcxxabi', LLVM_REPO_URL + '/libcxxabi/trunk', LIBCXXABI_DIR)
435
436 if args.with_patches and sys.platform != 'win32':
437 ApplyLocalPatches()
438
439 cc, cxx = None, None
440 cflags = cxxflags = ldflags = []
441
442 # LLVM uses C++11 starting in llvm 3.5. On Linux, this means libstdc++4.7+ is
443 # needed, on OS X it requires libc++. clang only automatically links to libc++
444 # when targeting OS X 10.9+, so add stdlib=libc++ explicitly so clang can run
445 # on OS X versions as old as 10.7.
446 # TODO(thakis): Some bots are still on 10.6 (nacl...), so for now bundle
447 # libc++.dylib. Remove this once all bots are on 10.7+, then use
448 # -DLLVM_ENABLE_LIBCXX=ON and change deployment_target to 10.7.
449 deployment_target = ''
450
451 if sys.platform == 'darwin':
452 # When building on 10.9, /usr/include usually doesn't exist, and while
453 # Xcode's clang automatically sets a sysroot, self-built clangs don't.
454 cflags = ['-isysroot', subprocess.check_output(
455 ['xcrun', '--show-sdk-path']).rstrip()]
456 cxxflags = ['-stdlib=libc++', '-nostdinc++',
457 '-I' + os.path.join(LIBCXX_DIR, 'include')] + cflags
458 if args.bootstrap:
459 deployment_target = '10.6'
460
461 base_cmake_args = ['-GNinja',
462 '-DCMAKE_BUILD_TYPE=Release',
463 '-DLLVM_ENABLE_ASSERTIONS=ON',
464 '-DLLVM_ENABLE_THREADS=OFF',
465 ]
466
467 if args.bootstrap:
468 print 'Building bootstrap compiler'
469 if not os.path.exists(LLVM_BOOTSTRAP_DIR):
470 os.makedirs(LLVM_BOOTSTRAP_DIR)
471 os.chdir(LLVM_BOOTSTRAP_DIR)
472 bootstrap_args = base_cmake_args + [
473 '-DLLVM_TARGETS_TO_BUILD=host',
474 '-DCMAKE_INSTALL_PREFIX=' + LLVM_BOOTSTRAP_INSTALL_DIR,
475 '-DCMAKE_C_FLAGS=' + ' '.join(cflags),
476 '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
477 ]
478 if cc is not None: bootstrap_args.append('-DCMAKE_C_COMPILER=' + cc)
479 if cxx is not None: bootstrap_args.append('-DCMAKE_CXX_COMPILER=' + cxx)
480 RunCommand(['cmake'] + bootstrap_args + [LLVM_DIR], msvc_arch='x64')
481 RunCommand(['ninja'], msvc_arch='x64')
482 if args.run_tests:
483 RunCommand(['ninja', 'check-all'], msvc_arch='x64')
484 RunCommand(['ninja', 'install'], msvc_arch='x64')
485
486 if sys.platform == 'win32':
487 cc = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang-cl.exe')
488 cxx = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang-cl.exe')
489 # CMake has a hard time with backslashes in compiler paths:
490 # https://stackoverflow.com/questions/13050827
491 cc = cc.replace('\\', '/')
492 cxx = cxx.replace('\\', '/')
493 else:
494 cc = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang')
495 cxx = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang++')
496 print 'Building final compiler'
497
498 if sys.platform == 'darwin':
499 # Build libc++.dylib while some bots are still on OS X 10.6.
500 libcxxbuild = os.path.join(LLVM_BUILD_DIR, 'libcxxbuild')
501 if os.path.isdir(libcxxbuild):
502 RmTree(libcxxbuild)
503 libcxxflags = ['-O3', '-std=c++11', '-fstrict-aliasing']
504
505 # libcxx and libcxxabi both have a file stdexcept.cpp, so put their .o files
506 # into different subdirectories.
507 os.makedirs(os.path.join(libcxxbuild, 'libcxx'))
508 os.chdir(os.path.join(libcxxbuild, 'libcxx'))
509 RunCommand(['c++', '-c'] + cxxflags + libcxxflags +
510 glob.glob(os.path.join(LIBCXX_DIR, 'src', '*.cpp')))
511
512 os.makedirs(os.path.join(libcxxbuild, 'libcxxabi'))
513 os.chdir(os.path.join(libcxxbuild, 'libcxxabi'))
514 RunCommand(['c++', '-c'] + cxxflags + libcxxflags +
515 glob.glob(os.path.join(LIBCXXABI_DIR, 'src', '*.cpp')) +
516 ['-I' + os.path.join(LIBCXXABI_DIR, 'include')])
517
518 os.chdir(libcxxbuild)
519 libdir = os.path.join(LIBCXX_DIR, 'lib')
520 RunCommand(['cc'] + glob.glob('libcxx/*.o') + glob.glob('libcxxabi/*.o') +
521 ['-o', 'libc++.1.dylib', '-dynamiclib', '-nodefaultlibs',
522 '-current_version', '1', '-compatibility_version', '1', '-lSystem',
523 '-install_name', '@executable_path/libc++.dylib',
524 '-Wl,-unexported_symbols_list,' + libdir + '/libc++unexp.exp',
525 '-Wl,-force_symbols_not_weak_list,' + libdir + '/notweak.exp',
526 '-Wl,-force_symbols_weak_list,' + libdir + '/weak.exp'])
527 if os.path.exists('libc++.dylib'):
528 os.remove('libc++.dylib')
529 os.symlink('libc++.1.dylib', 'libc++.dylib')
530 ldflags += ['-stdlib=libc++', '-L' + libcxxbuild]
531
532 if args.bootstrap:
533 # Now that the libc++ headers have been installed and libc++.dylib is
534 # built, delete the libc++ checkout again so that it's not part of the
535 # main build below -- the libc++(abi) tests don't pass on OS X in
536 # bootstrap builds (http://llvm.org/PR24068)
537 RmTree(LIBCXX_DIR)
538 RmTree(LIBCXXABI_DIR)
539 cxxflags = ['-stdlib=libc++', '-nostdinc++',
540 '-I' + os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR,
541 'include/c++/v1')
542 ] + cflags
543
544 # Build clang.
545 binutils_incdir = ''
546 if sys.platform.startswith('linux'):
547 binutils_incdir = os.path.join(BINUTILS_DIR, 'Linux_x64/Release/include')
548
549 # If building at head, define a macro that plugins can use for #ifdefing
550 # out code that builds at head, but not at LLVM_WIN_REVISION or vice versa.
551 if use_head_revision:
552 cflags += ['-DLLVM_FORCE_HEAD_REVISION']
553 cxxflags += ['-DLLVM_FORCE_HEAD_REVISION']
554
555 CreateChromeToolsShim()
556
557 deployment_env = None
558 if deployment_target:
559 deployment_env = os.environ.copy()
560 deployment_env['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
561
562 cmake_args = base_cmake_args + [
563 '-DLLVM_BINUTILS_INCDIR=' + binutils_incdir,
564 '-DCMAKE_C_FLAGS=' + ' '.join(cflags),
565 '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
566 '-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(ldflags),
567 '-DCMAKE_SHARED_LINKER_FLAGS=' + ' '.join(ldflags),
568 '-DCMAKE_MODULE_LINKER_FLAGS=' + ' '.join(ldflags),
569 '-DCMAKE_INSTALL_PREFIX=' + LLVM_BUILD_DIR,
570 '-DCHROMIUM_TOOLS_SRC=%s' % os.path.join(CHROMIUM_DIR, 'tools', 'clang'),
571 '-DCHROMIUM_TOOLS=%s' % ';'.join(args.tools)]
572 # TODO(thakis): Unconditionally append this to base_cmake_args instead once
573 # compiler-rt can build with clang-cl on Windows (http://llvm.org/PR23698)
574 cc_args = base_cmake_args if sys.platform != 'win32' else cmake_args
575 if cc is not None: cc_args.append('-DCMAKE_C_COMPILER=' + cc)
576 if cxx is not None: cc_args.append('-DCMAKE_CXX_COMPILER=' + cxx)
577
578 if not os.path.exists(LLVM_BUILD_DIR):
579 os.makedirs(LLVM_BUILD_DIR)
580 os.chdir(LLVM_BUILD_DIR)
581 RunCommand(['cmake'] + cmake_args + [LLVM_DIR],
582 msvc_arch='x64', env=deployment_env)
583 RunCommand(['ninja'], msvc_arch='x64')
584
585 if args.tools:
586 # If any Chromium tools were built, install those now.
587 RunCommand(['ninja', 'cr-install'], msvc_arch='x64')
588
589 if sys.platform == 'darwin':
590 CopyFile(os.path.join(LLVM_BUILD_DIR, 'libc++.1.dylib'),
591 os.path.join(LLVM_BUILD_DIR, 'bin'))
592 # See http://crbug.com/256342
593 RunCommand(['strip', '-x', os.path.join(LLVM_BUILD_DIR, 'bin', 'clang')])
594 elif sys.platform.startswith('linux'):
595 RunCommand(['strip', os.path.join(LLVM_BUILD_DIR, 'bin', 'clang')])
596
597 # Do an x86 build of compiler-rt to get the 32-bit ASan run-time.
598 # TODO(hans): Remove once the regular build above produces this.
599 if not os.path.exists(COMPILER_RT_BUILD_DIR):
600 os.makedirs(COMPILER_RT_BUILD_DIR)
601 os.chdir(COMPILER_RT_BUILD_DIR)
602 # TODO(thakis): Add this once compiler-rt can build with clang-cl (see
603 # above).
604 #if args.bootstrap and sys.platform == 'win32':
605 # The bootstrap compiler produces 64-bit binaries by default.
606 #cflags += ['-m32']
607 #cxxflags += ['-m32']
608 compiler_rt_args = base_cmake_args + [
609 '-DCMAKE_C_FLAGS=' + ' '.join(cflags),
610 '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags)]
611 if sys.platform != 'win32':
612 compiler_rt_args += ['-DLLVM_CONFIG_PATH=' +
613 os.path.join(LLVM_BUILD_DIR, 'bin', 'llvm-config')]
614 RunCommand(['cmake'] + compiler_rt_args + [LLVM_DIR],
615 msvc_arch='x86', env=deployment_env)
616 RunCommand(['ninja', 'compiler-rt'], msvc_arch='x86')
617
618 # TODO(hans): Make this (and the .gypi and .isolate files) version number
619 # independent.
620 if sys.platform == 'win32':
621 platform = 'windows'
622 elif sys.platform == 'darwin':
623 platform = 'darwin'
624 else:
625 assert sys.platform.startswith('linux')
626 platform = 'linux'
627 asan_rt_lib_src_dir = os.path.join(COMPILER_RT_BUILD_DIR, 'lib', 'clang',
628 VERSION, 'lib', platform)
629 asan_rt_lib_dst_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
630 VERSION, 'lib', platform)
631 CopyDirectoryContents(asan_rt_lib_src_dir, asan_rt_lib_dst_dir,
632 r'^.*-i386\.lib$')
633 CopyDirectoryContents(asan_rt_lib_src_dir, asan_rt_lib_dst_dir,
634 r'^.*-i386\.dll$')
635
636 CopyFile(os.path.join(asan_rt_lib_src_dir, '..', '..', 'asan_blacklist.txt'),
637 os.path.join(asan_rt_lib_dst_dir, '..', '..'))
638
639 if sys.platform == 'win32':
640 # Make an extra copy of the sanitizer headers, to be put on the include path
641 # of the fallback compiler.
642 sanitizer_include_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
643 VERSION, 'include', 'sanitizer')
644 aux_sanitizer_include_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
645 VERSION, 'include_sanitizer',
646 'sanitizer')
647 if not os.path.exists(aux_sanitizer_include_dir):
648 os.makedirs(aux_sanitizer_include_dir)
649 for _, _, files in os.walk(sanitizer_include_dir):
650 for f in files:
651 CopyFile(os.path.join(sanitizer_include_dir, f),
652 aux_sanitizer_include_dir)
653
654 # Run tests.
655 if args.run_tests or use_head_revision:
656 os.chdir(LLVM_BUILD_DIR)
657 RunCommand(GetVSVersion().SetupScript('x64') +
658 ['&&', 'ninja', 'cr-check-all'])
659 if args.run_tests:
660 os.chdir(LLVM_BUILD_DIR)
661 RunCommand(GetVSVersion().SetupScript('x64') +
662 ['&&', 'ninja', 'check-all'])
663
664 WriteStampFile(PACKAGE_VERSION)
665 print 'Clang update was successful.'
666 return 0
667
668
669 def main():
670 if not sys.platform in ['win32', 'cygwin']:
671 # For non-Windows, fall back to update.sh.
672 # TODO(hans): Make update.py replace update.sh completely.
673
674 # This script is called by gclient. gclient opens its hooks subprocesses
675 # with (stdout=subprocess.PIPE, stderr=subprocess.STDOUT) and then does
676 # custom output processing that breaks printing '\r' characters for
677 # single-line updating status messages as printed by curl and wget.
678 # Work around this by setting stderr of the update.sh process to stdin (!):
679 # gclient doesn't redirect stdin, and while stdin itself is read-only, a
680 # dup()ed sys.stdin is writable, try
681 # fd2 = os.dup(sys.stdin.fileno()); os.write(fd2, 'hi')
682 # TODO: Fix gclient instead, http://crbug.com/95350
683 if '--no-stdin-hack' in sys.argv:
684 sys.argv.remove('--no-stdin-hack')
685 stderr = None
686 else:
687 try:
688 stderr = os.fdopen(os.dup(sys.stdin.fileno()))
689 except:
690 stderr = sys.stderr
691 return subprocess.call(
692 [os.path.join(os.path.dirname(__file__), 'update.sh')] + sys.argv[1:],
693 stderr=stderr)
694
695 parser = argparse.ArgumentParser(description='Build Clang.')
696 parser.add_argument('--bootstrap', action='store_true',
697 help='first build clang with CC, then with itself.')
698 parser.add_argument('--if-needed', action='store_true',
699 help="run only if the script thinks clang is needed")
700 parser.add_argument('--force-local-build', action='store_true',
701 help="don't try to download prebuild binaries")
702 parser.add_argument('--print-revision', action='store_true',
703 help='print current clang revision and exit.')
704 parser.add_argument('--print-clang-version', action='store_true',
705 help='print current clang version (e.g. x.y.z) and exit.')
706 parser.add_argument('--run-tests', action='store_true',
707 help='run tests after building; only for local builds')
708 parser.add_argument('--tools', nargs='*',
709 help='select which chrome tools to build',
710 default=['plugins', 'blink_gc_plugin'])
711 parser.add_argument('--without-patches', action='store_false',
712 help="don't apply patches (default)", dest='with_patches',
713 default=True)
714
715 # For now, these flags are only used for the non-Windows flow, but argparser
716 # gets mad if it sees a flag it doesn't recognize.
717 parser.add_argument('--no-stdin-hack', action='store_true')
718
719 args = parser.parse_args()
720
721 if args.if_needed:
722 is_clang_required = False
723 # clang is always used on Mac and Linux.
724 if sys.platform == 'darwin' or sys.platform.startswith('linux'):
725 is_clang_required = True
726 # clang requested via $GYP_DEFINES.
727 if re.search(r'\b(clang|asan|lsan|msan|tsan)=1',
728 os.environ.get('GYP_DEFINES', '')):
729 is_clang_required = True
730 # clang previously downloaded, keep it up-to-date.
731 # If you don't want this, delete third_party/llvm-build on your machine.
732 if os.path.isdir(LLVM_BUILD_DIR):
733 is_clang_required = True
734 if not is_clang_required:
735 return 0
736 if re.search(r'\b(make_clang_dir)=', os.environ.get('GYP_DEFINES', '')):
737 print 'Skipping Clang update (make_clang_dir= was set in GYP_DEFINES).'
738 return 0
739
740 global LLVM_WIN_REVISION, PACKAGE_VERSION
741 if args.print_revision:
742 if use_head_revision:
743 print GetSvnRevision(LLVM_DIR)
744 else:
745 print PACKAGE_VERSION
746 return 0
747
748 if args.print_clang_version:
749 sys.stdout.write(VERSION)
750 return 0
751
752 # Don't buffer stdout, so that print statements are immediately flushed.
753 # Do this only after --print-revision has been handled, else we'll get
754 # an error message when this script is run from gn for some reason.
755 sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
756
757 if use_head_revision:
758 # Use a real revision number rather than HEAD to make sure that the stamp
759 # file logic works.
760 LLVM_WIN_REVISION = GetSvnRevision(LLVM_REPO_URL)
761 PACKAGE_VERSION = LLVM_WIN_REVISION + '-0'
762
763 args.force_local_build = True
764 # Skip local patches when using HEAD: they probably don't apply anymore.
765 args.with_patches = False
766
767 return UpdateClang(args)
768
769
770 if __name__ == '__main__':
771 sys.exit(main())
OLDNEW
« no previous file with comments | « runtime/vm/BUILD.gn ('k') | tools/clang/scripts/update.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698