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 """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."""
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
= '245965'
33 use_head_revision
= 'LLVM_FORCE_HEAD_REVISION' in os
.environ
35 LLVM_WIN_REVISION
= 'HEAD'
37 # This is incremented when pushing a new build of Clang at the same revision.
40 PACKAGE_VERSION
= "%s-%s" % (LLVM_WIN_REVISION
, CLANG_SUB_REVISION
)
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',
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')
65 # URL for pre-built binaries.
66 CDS_URL
= 'https://commondatastorage.googleapis.com/chromium-browser-clang'
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']
73 def DownloadUrl(url
, output_file
):
74 """Download url into output_file."""
77 sys
.stdout
.write('Downloading %s ' % url
)
79 response
= urllib2
.urlopen(url
)
80 total_size
= int(response
.info().getheader('Content-Length').strip())
84 chunk
= response
.read(CHUNK_SIZE
)
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
))
92 dots_printed
= num_dots
97 """Return the contents of the stamp file, or '' if it doesn't exist."""
99 with
open(STAMP_FILE
, 'r') as f
:
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
:
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
)
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
)
129 shutil
.rmtree(dir, onerror
=ChmodAndRetry
)
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."""
137 if msvc_arch
and sys
.platform
== 'win32':
138 command
= GetVSVersion().SetupScript(msvc_arch
) + ['&&'] + command
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
145 # Popen(['/bin/sh', '-c', args[0], args[1], ...])"
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:
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
)
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
):
175 for root
, _
, files
in os
.walk(src
):
177 if filename_filter
and not re
.match(filename_filter
, f
):
179 CopyFile(os
.path
.join(root
, f
), dst
)
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)
186 command
= ['svn', 'checkout', '--force', url
+ '@' + LLVM_WIN_REVISION
, dir]
187 if RunCommand(command
, fail_hard
=False):
190 if os
.path
.isdir(dir):
191 print "Removing %s." % (dir)
198 def RevertPreviouslyPatchedFiles():
199 print 'Reverting previously patched 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.cc',
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',
230 'compiler_rt': COMPILER_RT_DIR
,
233 if os
.path
.exists(f
):
234 os
.remove(f
) # For unversioned files.
235 RunCommand(['svn', 'revert', f
])
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'
247 def DeleteChromeToolsShim():
248 OLD_SHIM_DIR
= os
.path
.join(LLVM_DIR
, 'tools', 'zzz-chrometools')
249 shutil
.rmtree(OLD_SHIM_DIR
, ignore_errors
=True)
250 shutil
.rmtree(CHROME_TOOLS_SHIM_DIR
, ignore_errors
=True)
253 def CreateChromeToolsShim():
254 """Hooks the Chrome tools into the LLVM build.
256 Several Chrome tools have dependencies on LLVM/Clang libraries. The LLVM build
257 detects implicit tools in the tools subdirectory, so this helper install a
258 shim CMakeLists.txt that forwards to the real directory for the Chrome tools.
260 Note that the shim directory name intentionally has no - or _. The implicit
261 tool detection logic munges them in a weird way."""
262 assert not any(i
in os
.path
.basename(CHROME_TOOLS_SHIM_DIR
) for i
in '-_')
263 os
.mkdir(CHROME_TOOLS_SHIM_DIR
)
264 with
file(os
.path
.join(CHROME_TOOLS_SHIM_DIR
, 'CMakeLists.txt'), 'w') as f
:
265 f
.write('# Automatically generated by tools/clang/scripts/update.py. ' +
267 f
.write('# Since tools/clang is located in another directory, use the \n')
268 f
.write('# two arg version to specify where build artifacts go. CMake\n')
269 f
.write('# disallows reuse of the same binary dir for multiple source\n')
270 f
.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
271 f
.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
272 f
.write('if (CHROMIUM_TOOLS_SRC)\n')
273 f
.write(' add_subdirectory(${CHROMIUM_TOOLS_SRC} ' +
274 '${CMAKE_CURRENT_BINARY_DIR}/a)\n')
275 f
.write('endif (CHROMIUM_TOOLS_SRC)\n')
278 def AddCMakeToPath():
279 """Download CMake and add it to PATH."""
280 if sys
.platform
== 'win32':
281 zip_name
= 'cmake-3.2.2-win32-x86.zip'
282 cmake_dir
= os
.path
.join(LLVM_BUILD_TOOLS_DIR
,
283 'cmake-3.2.2-win32-x86', 'bin')
285 suffix
= 'Darwin' if sys
.platform
== 'darwin' else 'Linux'
286 zip_name
= 'cmake310_%s.tgz' % suffix
287 cmake_dir
= os
.path
.join(LLVM_BUILD_TOOLS_DIR
, 'cmake310', 'bin')
288 if not os
.path
.exists(cmake_dir
):
289 if not os
.path
.exists(LLVM_BUILD_TOOLS_DIR
):
290 os
.makedirs(LLVM_BUILD_TOOLS_DIR
)
291 # The cmake archive is smaller than 20 MB, small enough to keep in memory:
292 with contextlib
.closing(cStringIO
.StringIO()) as f
:
293 DownloadUrl(CDS_URL
+ '/tools/' + zip_name
, f
)
295 if zip_name
.endswith('.zip'):
296 zipfile
.ZipFile(f
).extractall(path
=LLVM_BUILD_TOOLS_DIR
)
298 tarfile
.open(mode
='r:gz', fileobj
=f
).extractall(path
=
299 LLVM_BUILD_TOOLS_DIR
)
300 os
.environ
['PATH'] = cmake_dir
+ os
.pathsep
+ os
.environ
.get('PATH', '')
308 # Try using the toolchain in depot_tools.
309 # This sets environment variables used by SelectVisualStudioVersion below.
310 sys
.path
.append(os
.path
.join(CHROMIUM_DIR
, 'build'))
312 vs_toolchain
.SetEnvironmentAndGetRuntimeDllDirs()
314 # Use gyp to find the MSVS installation, either in depot_tools as per above,
315 # or a system-wide installation otherwise.
316 sys
.path
.append(os
.path
.join(CHROMIUM_DIR
, 'tools', 'gyp', 'pylib'))
317 import gyp
.MSVSVersion
318 vs_version
= gyp
.MSVSVersion
.SelectVisualStudioVersion('2013')
322 def UpdateClang(args
):
323 print 'Updating Clang to %s...' % PACKAGE_VERSION
324 if ReadStampFile() == PACKAGE_VERSION
:
325 print 'Already up to date.'
328 # Reset the stamp file in case the build is unsuccessful.
331 if not args
.force_local_build
:
332 cds_file
= "clang-%s.tgz" % PACKAGE_VERSION
333 cds_full_url
= CDS_URL
+ '/Win/' + cds_file
335 # Check if there's a prebuilt binary and if so just fetch that. That's
336 # faster, and goma relies on having matching binary hashes on client and
338 print 'Trying to download prebuilt clang'
340 # clang packages are smaller than 50 MB, small enough to keep in memory.
341 with contextlib
.closing(cStringIO
.StringIO()) as f
:
343 DownloadUrl(cds_full_url
, f
)
345 # TODO(thakis): Delete LLVM_BUILD_DIR before extracting.
346 tarfile
.open(mode
='r:gz', fileobj
=f
).extractall(path
=LLVM_BUILD_DIR
)
347 print 'clang %s unpacked' % PACKAGE_VERSION
348 # Download the gold plugin if requested to by an environment variable.
349 # This is used by the CFI ClusterFuzz bot.
350 if 'LLVM_DOWNLOAD_GOLD_PLUGIN' in os
.environ
:
351 RunCommand(['python', CHROMIUM_DIR
+'/build/download_gold_plugin.py'])
352 WriteStampFile(PACKAGE_VERSION
)
354 except urllib2
.HTTPError
:
355 print 'Did not find prebuilt clang %s, building locally' % cds_file
359 RevertPreviouslyPatchedFiles()
360 DeleteChromeToolsShim()
362 Checkout('LLVM', LLVM_REPO_URL
+ '/llvm/trunk', LLVM_DIR
)
363 Checkout('Clang', LLVM_REPO_URL
+ '/cfe/trunk', CLANG_DIR
)
364 if sys
.platform
== 'win32':
365 Checkout('LLD', LLVM_REPO_URL
+ '/lld/trunk', LLD_DIR
)
366 Checkout('compiler-rt', LLVM_REPO_URL
+ '/compiler-rt/trunk', COMPILER_RT_DIR
)
367 if sys
.platform
== 'darwin':
368 # clang needs a libc++ checkout, else -stdlib=libc++ won't find includes
369 # (i.e. this is needed for bootstrap builds).
370 Checkout('libcxx', LLVM_REPO_URL
+ '/libcxx/trunk', LIBCXX_DIR
)
371 # While we're bundling our own libc++ on OS X, we need to compile libc++abi
372 # into it too (since OS X 10.6 doesn't have libc++abi.dylib either).
373 Checkout('libcxxabi', LLVM_REPO_URL
+ '/libcxxabi/trunk', LIBCXXABI_DIR
)
375 if args
.with_patches
and sys
.platform
!= 'win32':
380 if args
.gcc_toolchain
: # This option is only used on Linux.
381 # Use the specified gcc installation for building.
382 cc
= os
.path
.join(args
.gcc_toolchain
, 'bin', 'gcc')
383 cxx
= os
.path
.join(args
.gcc_toolchain
, 'bin', 'g++')
385 if not os
.access(cc
, os
.X_OK
):
386 print 'Invalid --gcc-toolchain: "%s"' % args
.gcc_toolchain
387 print '"%s" does not appear to be valid.' % cc
390 # Set LD_LIBRARY_PATH to make auxiliary targets (tablegen, bootstrap
391 # compiler, etc.) find the .so.
392 libstdcpp
= subprocess
.check_output(
393 [cxx
, '-print-file-name=libstdc++.so.6']).rstrip()
394 os
.environ
['LD_LIBRARY_PATH'] = os
.path
.dirname(libstdcpp
)
396 cflags
= cxxflags
= ldflags
= []
398 # LLVM uses C++11 starting in llvm 3.5. On Linux, this means libstdc++4.7+ is
399 # needed, on OS X it requires libc++. clang only automatically links to libc++
400 # when targeting OS X 10.9+, so add stdlib=libc++ explicitly so clang can run
401 # on OS X versions as old as 10.7.
402 # TODO(thakis): Some bots are still on 10.6 (nacl...), so for now bundle
403 # libc++.dylib. Remove this once all bots are on 10.7+, then use
404 # -DLLVM_ENABLE_LIBCXX=ON and change deployment_target to 10.7.
405 deployment_target
= ''
407 if sys
.platform
== 'darwin':
408 # When building on 10.9, /usr/include usually doesn't exist, and while
409 # Xcode's clang automatically sets a sysroot, self-built clangs don't.
410 cflags
= ['-isysroot', subprocess
.check_output(
411 ['xcrun', '--show-sdk-path']).rstrip()]
412 cxxflags
= ['-stdlib=libc++', '-nostdinc++',
413 '-I' + os
.path
.join(LIBCXX_DIR
, 'include')] + cflags
415 deployment_target
= '10.6'
417 base_cmake_args
= ['-GNinja',
418 '-DCMAKE_BUILD_TYPE=Release',
419 '-DLLVM_ENABLE_ASSERTIONS=ON',
420 '-DLLVM_ENABLE_THREADS=OFF',
424 print 'Building bootstrap compiler'
425 if not os
.path
.exists(LLVM_BOOTSTRAP_DIR
):
426 os
.makedirs(LLVM_BOOTSTRAP_DIR
)
427 os
.chdir(LLVM_BOOTSTRAP_DIR
)
428 bootstrap_args
= base_cmake_args
+ [
429 '-DLLVM_TARGETS_TO_BUILD=host',
430 '-DCMAKE_INSTALL_PREFIX=' + LLVM_BOOTSTRAP_INSTALL_DIR
,
431 '-DCMAKE_C_FLAGS=' + ' '.join(cflags
),
432 '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags
),
434 if cc
is not None: bootstrap_args
.append('-DCMAKE_C_COMPILER=' + cc
)
435 if cxx
is not None: bootstrap_args
.append('-DCMAKE_CXX_COMPILER=' + cxx
)
436 RunCommand(['cmake'] + bootstrap_args
+ [LLVM_DIR
], msvc_arch
='x64')
437 RunCommand(['ninja'], msvc_arch
='x64')
439 RunCommand(['ninja', 'check-all'], msvc_arch
='x64')
440 RunCommand(['ninja', 'install'], msvc_arch
='x64')
441 if args
.gcc_toolchain
:
442 # Copy that gcc's stdlibc++.so.6 to the build dir, so the bootstrap
443 # compiler can start.
444 CopyFile(libstdcpp
, os
.path
.join(LLVM_BOOTSTRAP_INSTALL_DIR
, 'lib'))
446 if sys
.platform
== 'win32':
447 cc
= os
.path
.join(LLVM_BOOTSTRAP_INSTALL_DIR
, 'bin', 'clang-cl.exe')
448 cxx
= os
.path
.join(LLVM_BOOTSTRAP_INSTALL_DIR
, 'bin', 'clang-cl.exe')
449 # CMake has a hard time with backslashes in compiler paths:
450 # https://stackoverflow.com/questions/13050827
451 cc
= cc
.replace('\\', '/')
452 cxx
= cxx
.replace('\\', '/')
454 cc
= os
.path
.join(LLVM_BOOTSTRAP_INSTALL_DIR
, 'bin', 'clang')
455 cxx
= os
.path
.join(LLVM_BOOTSTRAP_INSTALL_DIR
, 'bin', 'clang++')
457 if args
.gcc_toolchain
:
458 # Tell the bootstrap compiler to use a specific gcc prefix to search
459 # for standard library headers and shared object files.
460 cflags
= ['--gcc-toolchain=' + args
.gcc_toolchain
]
461 cxxflags
= ['--gcc-toolchain=' + args
.gcc_toolchain
]
462 print 'Building final compiler'
464 if sys
.platform
== 'darwin':
465 # Build libc++.dylib while some bots are still on OS X 10.6.
466 libcxxbuild
= os
.path
.join(LLVM_BUILD_DIR
, 'libcxxbuild')
467 if os
.path
.isdir(libcxxbuild
):
469 libcxxflags
= ['-O3', '-std=c++11', '-fstrict-aliasing']
471 # libcxx and libcxxabi both have a file stdexcept.cpp, so put their .o files
472 # into different subdirectories.
473 os
.makedirs(os
.path
.join(libcxxbuild
, 'libcxx'))
474 os
.chdir(os
.path
.join(libcxxbuild
, 'libcxx'))
475 RunCommand(['c++', '-c'] + cxxflags
+ libcxxflags
+
476 glob
.glob(os
.path
.join(LIBCXX_DIR
, 'src', '*.cpp')))
478 os
.makedirs(os
.path
.join(libcxxbuild
, 'libcxxabi'))
479 os
.chdir(os
.path
.join(libcxxbuild
, 'libcxxabi'))
480 RunCommand(['c++', '-c'] + cxxflags
+ libcxxflags
+
481 glob
.glob(os
.path
.join(LIBCXXABI_DIR
, 'src', '*.cpp')) +
482 ['-I' + os
.path
.join(LIBCXXABI_DIR
, 'include')])
484 os
.chdir(libcxxbuild
)
485 libdir
= os
.path
.join(LIBCXX_DIR
, 'lib')
486 RunCommand(['cc'] + glob
.glob('libcxx/*.o') + glob
.glob('libcxxabi/*.o') +
487 ['-o', 'libc++.1.dylib', '-dynamiclib', '-nodefaultlibs',
488 '-current_version', '1', '-compatibility_version', '1', '-lSystem',
489 '-install_name', '@executable_path/libc++.dylib',
490 '-Wl,-unexported_symbols_list,' + libdir
+ '/libc++unexp.exp',
491 '-Wl,-force_symbols_not_weak_list,' + libdir
+ '/notweak.exp',
492 '-Wl,-force_symbols_weak_list,' + libdir
+ '/weak.exp'])
493 if os
.path
.exists('libc++.dylib'):
494 os
.remove('libc++.dylib')
495 os
.symlink('libc++.1.dylib', 'libc++.dylib')
496 ldflags
+= ['-stdlib=libc++', '-L' + libcxxbuild
]
499 # Now that the libc++ headers have been installed and libc++.dylib is
500 # built, delete the libc++ checkout again so that it's not part of the
501 # main build below -- the libc++(abi) tests don't pass on OS X in
502 # bootstrap builds (http://llvm.org/PR24068)
504 RmTree(LIBCXXABI_DIR
)
505 cxxflags
= ['-stdlib=libc++', '-nostdinc++',
506 '-I' + os
.path
.join(LLVM_BOOTSTRAP_INSTALL_DIR
,
512 if sys
.platform
.startswith('linux'):
513 binutils_incdir
= os
.path
.join(BINUTILS_DIR
, 'Linux_x64/Release/include')
515 # If building at head, define a macro that plugins can use for #ifdefing
516 # out code that builds at head, but not at LLVM_WIN_REVISION or vice versa.
517 if use_head_revision
:
518 cflags
+= ['-DLLVM_FORCE_HEAD_REVISION']
519 cxxflags
+= ['-DLLVM_FORCE_HEAD_REVISION']
521 CreateChromeToolsShim()
523 deployment_env
= None
524 if deployment_target
:
525 deployment_env
= os
.environ
.copy()
526 deployment_env
['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
528 cmake_args
= base_cmake_args
+ [
529 '-DLLVM_BINUTILS_INCDIR=' + binutils_incdir
,
530 '-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly',
531 '-DCMAKE_C_FLAGS=' + ' '.join(cflags
),
532 '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags
),
533 '-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(ldflags
),
534 '-DCMAKE_SHARED_LINKER_FLAGS=' + ' '.join(ldflags
),
535 '-DCMAKE_MODULE_LINKER_FLAGS=' + ' '.join(ldflags
),
536 '-DCMAKE_INSTALL_PREFIX=' + LLVM_BUILD_DIR
,
537 '-DCHROMIUM_TOOLS_SRC=%s' % os
.path
.join(CHROMIUM_DIR
, 'tools', 'clang'),
538 '-DCHROMIUM_TOOLS=%s' % ';'.join(args
.tools
)]
539 # TODO(thakis): Unconditionally append this to base_cmake_args instead once
540 # compiler-rt can build with clang-cl on Windows (http://llvm.org/PR23698)
541 cc_args
= base_cmake_args
if sys
.platform
!= 'win32' else cmake_args
542 if cc
is not None: cc_args
.append('-DCMAKE_C_COMPILER=' + cc
)
543 if cxx
is not None: cc_args
.append('-DCMAKE_CXX_COMPILER=' + cxx
)
545 if not os
.path
.exists(LLVM_BUILD_DIR
):
546 os
.makedirs(LLVM_BUILD_DIR
)
547 os
.chdir(LLVM_BUILD_DIR
)
548 RunCommand(['cmake'] + cmake_args
+ [LLVM_DIR
],
549 msvc_arch
='x64', env
=deployment_env
)
551 if args
.gcc_toolchain
:
552 # Copy in the right stdlibc++.so.6 so clang can start.
553 if not os
.path
.exists(os
.path
.join(LLVM_BUILD_DIR
, 'lib')):
554 os
.mkdir(os
.path
.join(LLVM_BUILD_DIR
, 'lib'))
555 libstdcpp
= subprocess
.check_output(
556 [cxx
] + cxxflags
+ ['-print-file-name=libstdc++.so.6']).rstrip()
557 CopyFile(libstdcpp
, os
.path
.join(LLVM_BUILD_DIR
, 'lib'))
559 RunCommand(['ninja'], msvc_arch
='x64')
562 # If any Chromium tools were built, install those now.
563 RunCommand(['ninja', 'cr-install'], msvc_arch
='x64')
565 if sys
.platform
== 'darwin':
566 CopyFile(os
.path
.join(LLVM_BUILD_DIR
, 'libc++.1.dylib'),
567 os
.path
.join(LLVM_BUILD_DIR
, 'bin'))
568 # See http://crbug.com/256342
569 RunCommand(['strip', '-x', os
.path
.join(LLVM_BUILD_DIR
, 'bin', 'clang')])
570 elif sys
.platform
.startswith('linux'):
571 RunCommand(['strip', os
.path
.join(LLVM_BUILD_DIR
, 'bin', 'clang')])
573 # Do an x86 build of compiler-rt to get the 32-bit ASan run-time.
574 # TODO(hans): Remove once the regular build above produces this.
575 if not os
.path
.exists(COMPILER_RT_BUILD_DIR
):
576 os
.makedirs(COMPILER_RT_BUILD_DIR
)
577 os
.chdir(COMPILER_RT_BUILD_DIR
)
578 # TODO(thakis): Add this once compiler-rt can build with clang-cl (see
580 #if args.bootstrap and sys.platform == 'win32':
581 # The bootstrap compiler produces 64-bit binaries by default.
583 #cxxflags += ['-m32']
584 compiler_rt_args
= base_cmake_args
+ [
585 '-DCMAKE_C_FLAGS=' + ' '.join(cflags
),
586 '-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags
)]
587 if sys
.platform
!= 'win32':
588 compiler_rt_args
+= ['-DLLVM_CONFIG_PATH=' +
589 os
.path
.join(LLVM_BUILD_DIR
, 'bin', 'llvm-config'),
590 '-DSANITIZER_MIN_OSX_VERSION="10.7"']
591 RunCommand(['cmake'] + compiler_rt_args
+ [LLVM_DIR
],
592 msvc_arch
='x86', env
=deployment_env
)
593 RunCommand(['ninja', 'compiler-rt'], msvc_arch
='x86')
595 # TODO(hans): Make this (and the .gypi and .isolate files) version number
597 if sys
.platform
== 'win32':
599 elif sys
.platform
== 'darwin':
602 assert sys
.platform
.startswith('linux')
604 asan_rt_lib_src_dir
= os
.path
.join(COMPILER_RT_BUILD_DIR
, 'lib', 'clang',
605 VERSION
, 'lib', platform
)
606 asan_rt_lib_dst_dir
= os
.path
.join(LLVM_BUILD_DIR
, 'lib', 'clang',
607 VERSION
, 'lib', platform
)
608 CopyDirectoryContents(asan_rt_lib_src_dir
, asan_rt_lib_dst_dir
,
610 CopyDirectoryContents(asan_rt_lib_src_dir
, asan_rt_lib_dst_dir
,
613 CopyFile(os
.path
.join(asan_rt_lib_src_dir
, '..', '..', 'asan_blacklist.txt'),
614 os
.path
.join(asan_rt_lib_dst_dir
, '..', '..'))
616 if sys
.platform
== 'win32':
617 # Make an extra copy of the sanitizer headers, to be put on the include path
618 # of the fallback compiler.
619 sanitizer_include_dir
= os
.path
.join(LLVM_BUILD_DIR
, 'lib', 'clang',
620 VERSION
, 'include', 'sanitizer')
621 aux_sanitizer_include_dir
= os
.path
.join(LLVM_BUILD_DIR
, 'lib', 'clang',
622 VERSION
, 'include_sanitizer',
624 if not os
.path
.exists(aux_sanitizer_include_dir
):
625 os
.makedirs(aux_sanitizer_include_dir
)
626 for _
, _
, files
in os
.walk(sanitizer_include_dir
):
628 CopyFile(os
.path
.join(sanitizer_include_dir
, f
),
629 aux_sanitizer_include_dir
)
632 if args
.run_tests
or use_head_revision
:
633 os
.chdir(LLVM_BUILD_DIR
)
634 RunCommand(GetVSVersion().SetupScript('x64') +
635 ['&&', 'ninja', 'cr-check-all'])
637 os
.chdir(LLVM_BUILD_DIR
)
638 RunCommand(GetVSVersion().SetupScript('x64') +
639 ['&&', 'ninja', 'check-all'])
641 WriteStampFile(PACKAGE_VERSION
)
642 print 'Clang update was successful.'
647 if not sys
.platform
in ['win32', 'cygwin']:
648 # For non-Windows, fall back to update.sh.
649 # TODO(hans): Make update.py replace update.sh completely.
651 # This script is called by gclient. gclient opens its hooks subprocesses
652 # with (stdout=subprocess.PIPE, stderr=subprocess.STDOUT) and then does
653 # custom output processing that breaks printing '\r' characters for
654 # single-line updating status messages as printed by curl and wget.
655 # Work around this by setting stderr of the update.sh process to stdin (!):
656 # gclient doesn't redirect stdin, and while stdin itself is read-only, a
657 # dup()ed sys.stdin is writable, try
658 # fd2 = os.dup(sys.stdin.fileno()); os.write(fd2, 'hi')
659 # TODO: Fix gclient instead, http://crbug.com/95350
660 if '--no-stdin-hack' in sys
.argv
:
661 sys
.argv
.remove('--no-stdin-hack')
665 stderr
= os
.fdopen(os
.dup(sys
.stdin
.fileno()))
668 return subprocess
.call(
669 [os
.path
.join(os
.path
.dirname(__file__
), 'update.sh')] + sys
.argv
[1:],
672 parser
= argparse
.ArgumentParser(description
='Build Clang.')
673 parser
.add_argument('--bootstrap', action
='store_true',
674 help='first build clang with CC, then with itself.')
675 parser
.add_argument('--if-needed', action
='store_true',
676 help="run only if the script thinks clang is needed")
677 parser
.add_argument('--force-local-build', action
='store_true',
678 help="don't try to download prebuild binaries")
679 parser
.add_argument('--gcc-toolchain', help='set the version for which gcc '
680 'version be used for building; --gcc-toolchain=/opt/foo '
681 'picks /opt/foo/bin/gcc')
682 parser
.add_argument('--print-revision', action
='store_true',
683 help='print current clang revision and exit.')
684 parser
.add_argument('--print-clang-version', action
='store_true',
685 help='print current clang version (e.g. x.y.z) and exit.')
686 parser
.add_argument('--run-tests', action
='store_true',
687 help='run tests after building; only for local builds')
688 parser
.add_argument('--tools', nargs
='*',
689 help='select which chrome tools to build',
690 default
=['plugins', 'blink_gc_plugin'])
691 parser
.add_argument('--without-patches', action
='store_false',
692 help="don't apply patches (default)", dest
='with_patches',
695 # For now, these flags are only used for the non-Windows flow, but argparser
696 # gets mad if it sees a flag it doesn't recognize.
697 parser
.add_argument('--no-stdin-hack', action
='store_true')
699 args
= parser
.parse_args()
702 is_clang_required
= False
703 # clang is always used on Mac and Linux.
704 if sys
.platform
== 'darwin' or sys
.platform
.startswith('linux'):
705 is_clang_required
= True
706 # clang requested via $GYP_DEFINES.
707 if re
.search(r
'\b(clang|asan|lsan|msan|tsan)=1',
708 os
.environ
.get('GYP_DEFINES', '')):
709 is_clang_required
= True
710 # clang previously downloaded, keep it up-to-date.
711 # If you don't want this, delete third_party/llvm-build on your machine.
712 if os
.path
.isdir(LLVM_BUILD_DIR
):
713 is_clang_required
= True
714 if not is_clang_required
:
716 if re
.search(r
'\b(make_clang_dir)=', os
.environ
.get('GYP_DEFINES', '')):
717 print 'Skipping Clang update (make_clang_dir= was set in GYP_DEFINES).'
720 global LLVM_WIN_REVISION
, PACKAGE_VERSION
721 if args
.print_revision
:
722 if use_head_revision
:
723 print GetSvnRevision(LLVM_DIR
)
725 print PACKAGE_VERSION
728 if args
.print_clang_version
:
729 sys
.stdout
.write(VERSION
)
732 # Don't buffer stdout, so that print statements are immediately flushed.
733 # Do this only after --print-revision has been handled, else we'll get
734 # an error message when this script is run from gn for some reason.
735 sys
.stdout
= os
.fdopen(sys
.stdout
.fileno(), 'w', 0)
737 if use_head_revision
:
738 # Use a real revision number rather than HEAD to make sure that the stamp
740 LLVM_WIN_REVISION
= GetSvnRevision(LLVM_REPO_URL
)
741 PACKAGE_VERSION
= LLVM_WIN_REVISION
+ '-0'
743 args
.force_local_build
= True
744 # Skip local patches when using HEAD: they probably don't apply anymore.
745 args
.with_patches
= False
747 return UpdateClang(args
)
750 if __name__
== '__main__':