You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

update_clang.py 5.5 KiB

Update tools. Unfortunately, this requires partially reverting https://boringssl-review.googlesource.com/31324. This is a mess. While clang proper includes a fuzzer driver, Chromium doesn't use it. Chromium builds exclusively with fuzzer-no-link and links to its own copy of the fuzzer runtime[1]. As of [2], Chromium's clang (which we use on bots) no longer includes the driver, so we must mimic them. However, Chromium's setup is somewhat questionable because fuzzer-no-link pulls in libclang_rt.fuzzer_no_main which still includes most of libclang_rt.fuzzer, just not the one main function[3]. It appears Chromium is actually linking two copies of libclang_rt.fuzzer_no_main. Hopefully this mostly works out as Chromium's clang and libFuzzer should be relatively aligned, but it's not a good assumption for our build, which can take other Clangs too. Thus, if you pass -DFUZZ=1 as-is, we will assume you are using a "normal" Clang with all its relevant runtimes intact. If, however, you are using Chromium clang, you must drop the matching libFuzzer where the bots expected it and build with -DLIBFUZZER_FROM_DEPS=1. This involves no changes to the bots because we never actually unwound all the LIBFUZZER_FROM_DEPS bits before. [1] https://cs.chromium.org/chromium/src/testing/libfuzzer/BUILD.gn?rcl=d21c49585f262e851e2984f96f52905782706325&l=14 [2] https://chromium.googlesource.com/chromium/src/+/c79bf2ea4cf65431dccb57cb2a44528c284645a1 [3] https://github.com/llvm-mirror/compiler-rt/blob/8ebc3668b07fc5cca6010265cd4795443f1c1bea/lib/fuzzer/CMakeLists.txt#L93-L107 https://github.com/llvm-mirror/compiler-rt/blob/8ebc3668b07fc5cca6010265cd4795443f1c1bea/lib/fuzzer/FuzzerMain.cpp Change-Id: I946b3c821c3d7e6def7e07f1381f58241611ba3d Reviewed-on: https://boringssl-review.googlesource.com/c/34184 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. """This script is used to download prebuilt clang binaries."""
  6. import os
  7. import shutil
  8. import subprocess
  9. import stat
  10. import sys
  11. import tarfile
  12. import tempfile
  13. import time
  14. import urllib2
  15. # CLANG_REVISION and CLANG_SUB_REVISION determine the build of clang
  16. # to use. These should be synced with tools/clang/scripts/update.py in
  17. # Chromium.
  18. CLANG_REVISION = '349417'
  19. CLANG_SUB_REVISION=2
  20. PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION)
  21. # Path constants. (All of these should be absolute paths.)
  22. THIS_DIR = os.path.abspath(os.path.dirname(__file__))
  23. LLVM_BUILD_DIR = os.path.join(THIS_DIR, 'llvm-build')
  24. STAMP_FILE = os.path.join(LLVM_BUILD_DIR, 'cr_build_revision')
  25. # URL for pre-built binaries.
  26. CDS_URL = os.environ.get('CDS_CLANG_BUCKET_OVERRIDE',
  27. 'https://commondatastorage.googleapis.com/chromium-browser-clang')
  28. # Bump after VC updates.
  29. DIA_DLL = {
  30. '2013': 'msdia120.dll',
  31. '2015': 'msdia140.dll',
  32. '2017': 'msdia140.dll',
  33. }
  34. def DownloadUrl(url, output_file):
  35. """Download url into output_file."""
  36. CHUNK_SIZE = 4096
  37. TOTAL_DOTS = 10
  38. num_retries = 3
  39. retry_wait_s = 5 # Doubled at each retry.
  40. while True:
  41. try:
  42. sys.stdout.write('Downloading %s ' % url)
  43. sys.stdout.flush()
  44. response = urllib2.urlopen(url)
  45. total_size = int(response.info().getheader('Content-Length').strip())
  46. bytes_done = 0
  47. dots_printed = 0
  48. while True:
  49. chunk = response.read(CHUNK_SIZE)
  50. if not chunk:
  51. break
  52. output_file.write(chunk)
  53. bytes_done += len(chunk)
  54. num_dots = TOTAL_DOTS * bytes_done / total_size
  55. sys.stdout.write('.' * (num_dots - dots_printed))
  56. sys.stdout.flush()
  57. dots_printed = num_dots
  58. if bytes_done != total_size:
  59. raise urllib2.URLError("only got %d of %d bytes" %
  60. (bytes_done, total_size))
  61. print ' Done.'
  62. return
  63. except urllib2.URLError as e:
  64. sys.stdout.write('\n')
  65. print e
  66. if num_retries == 0 or isinstance(e, urllib2.HTTPError) and e.code == 404:
  67. raise e
  68. num_retries -= 1
  69. print 'Retrying in %d s ...' % retry_wait_s
  70. time.sleep(retry_wait_s)
  71. retry_wait_s *= 2
  72. def EnsureDirExists(path):
  73. if not os.path.exists(path):
  74. print "Creating directory %s" % path
  75. os.makedirs(path)
  76. def DownloadAndUnpack(url, output_dir):
  77. with tempfile.TemporaryFile() as f:
  78. DownloadUrl(url, f)
  79. f.seek(0)
  80. EnsureDirExists(output_dir)
  81. tarfile.open(mode='r:gz', fileobj=f).extractall(path=output_dir)
  82. def ReadStampFile(path=STAMP_FILE):
  83. """Return the contents of the stamp file, or '' if it doesn't exist."""
  84. try:
  85. with open(path, 'r') as f:
  86. return f.read().rstrip()
  87. except IOError:
  88. return ''
  89. def WriteStampFile(s, path=STAMP_FILE):
  90. """Write s to the stamp file."""
  91. EnsureDirExists(os.path.dirname(path))
  92. with open(path, 'w') as f:
  93. f.write(s)
  94. f.write('\n')
  95. def RmTree(dir):
  96. """Delete dir."""
  97. def ChmodAndRetry(func, path, _):
  98. # Subversion can leave read-only files around.
  99. if not os.access(path, os.W_OK):
  100. os.chmod(path, stat.S_IWUSR)
  101. return func(path)
  102. raise
  103. shutil.rmtree(dir, onerror=ChmodAndRetry)
  104. def CopyFile(src, dst):
  105. """Copy a file from src to dst."""
  106. print "Copying %s to %s" % (src, dst)
  107. shutil.copy(src, dst)
  108. vs_version = None
  109. def GetVSVersion():
  110. global vs_version
  111. if vs_version:
  112. return vs_version
  113. # Try using the toolchain in depot_tools.
  114. # This sets environment variables used by SelectVisualStudioVersion below.
  115. sys.path.append(THIS_DIR)
  116. import vs_toolchain
  117. vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
  118. # Use gyp to find the MSVS installation, either in depot_tools as per above,
  119. # or a system-wide installation otherwise.
  120. sys.path.append(os.path.join(THIS_DIR, 'gyp', 'pylib'))
  121. import gyp.MSVSVersion
  122. vs_version = gyp.MSVSVersion.SelectVisualStudioVersion(
  123. vs_toolchain.GetVisualStudioVersion())
  124. return vs_version
  125. def CopyDiaDllTo(target_dir):
  126. # This script always wants to use the 64-bit msdia*.dll.
  127. dia_path = os.path.join(GetVSVersion().Path(), 'DIA SDK', 'bin', 'amd64')
  128. dia_dll = os.path.join(dia_path, DIA_DLL[GetVSVersion().ShortName()])
  129. CopyFile(dia_dll, target_dir)
  130. def UpdateClang():
  131. cds_file = "clang-%s.tgz" % PACKAGE_VERSION
  132. if sys.platform == 'win32' or sys.platform == 'cygwin':
  133. cds_full_url = CDS_URL + '/Win/' + cds_file
  134. elif sys.platform.startswith('linux'):
  135. cds_full_url = CDS_URL + '/Linux_x64/' + cds_file
  136. else:
  137. return 0
  138. print 'Updating Clang to %s...' % PACKAGE_VERSION
  139. if ReadStampFile() == PACKAGE_VERSION:
  140. print 'Clang is already up to date.'
  141. return 0
  142. # Reset the stamp file in case the build is unsuccessful.
  143. WriteStampFile('')
  144. print 'Downloading prebuilt clang'
  145. if os.path.exists(LLVM_BUILD_DIR):
  146. RmTree(LLVM_BUILD_DIR)
  147. try:
  148. DownloadAndUnpack(cds_full_url, LLVM_BUILD_DIR)
  149. print 'clang %s unpacked' % PACKAGE_VERSION
  150. if sys.platform == 'win32':
  151. CopyDiaDllTo(os.path.join(LLVM_BUILD_DIR, 'bin'))
  152. WriteStampFile(PACKAGE_VERSION)
  153. return 0
  154. except urllib2.URLError:
  155. print 'Failed to download prebuilt clang %s' % cds_file
  156. print 'Exiting.'
  157. return 1
  158. def main():
  159. # Don't buffer stdout, so that print statements are immediately flushed.
  160. sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
  161. return UpdateClang()
  162. if __name__ == '__main__':
  163. sys.exit(main())