summaryrefslogtreecommitdiff
path: root/chromium/tools/clang/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/tools/clang/scripts')
-rwxr-xr-xchromium/tools/clang/scripts/apply_edits.py26
-rwxr-xr-xchromium/tools/clang/scripts/apply_edits_test.py11
-rwxr-xr-xchromium/tools/clang/scripts/build.py102
-rwxr-xr-xchromium/tools/clang/scripts/clang_tidy_tool.py14
-rwxr-xr-xchromium/tools/clang/scripts/expand_thin_archives.py124
-rwxr-xr-xchromium/tools/clang/scripts/goma_ld.py2
-rwxr-xr-xchromium/tools/clang/scripts/goma_link.py89
-rwxr-xr-xchromium/tools/clang/scripts/goma_link_unit_tests.py78
-rwxr-xr-xchromium/tools/clang/scripts/update.py4
-rwxr-xr-xchromium/tools/clang/scripts/upload_revision.py3
10 files changed, 238 insertions, 215 deletions
diff --git a/chromium/tools/clang/scripts/apply_edits.py b/chromium/tools/clang/scripts/apply_edits.py
index f6e9dcb16c6..a49a739792b 100755
--- a/chromium/tools/clang/scripts/apply_edits.py
+++ b/chromium/tools/clang/scripts/apply_edits.py
@@ -76,7 +76,7 @@ def _ParseEditsFromStdin(build_directory):
if not os.path.isfile(path):
resolved_path = os.path.realpath(os.path.join(build_directory, path))
else:
- resolved_path = path
+ resolved_path = os.path.realpath(path)
if not os.path.isfile(resolved_path):
sys.stderr.write('Edit applies to a non-existent file: %s\n' % path)
@@ -197,12 +197,24 @@ def _InsertNonSystemIncludeHeader(filepath, header_line_to_add, contents):
def _ApplyReplacement(filepath, contents, edit, last_edit):
- if (last_edit is not None and edit.edit_type == last_edit.edit_type
- and edit.offset == last_edit.offset and edit.length == last_edit.length):
- raise ValueError(('Conflicting replacement text: ' +
- '%s at offset %d, length %d: "%s" != "%s"\n') %
- (filepath, edit.offset, edit.length, edit.replacement,
- last_edit.replacement))
+ assert (edit.edit_type == 'r')
+ assert ((last_edit is None) or (last_edit.edit_type == 'r'))
+
+ if last_edit is not None:
+ if edit.offset == last_edit.offset and edit.length == last_edit.length:
+ assert (edit.replacement != last_edit.replacement)
+ raise ValueError(('Conflicting replacement text: ' +
+ '%s at offset %d, length %d: "%s" != "%s"\n') %
+ (filepath, edit.offset, edit.length, edit.replacement,
+ last_edit.replacement))
+
+ if edit.offset + edit.length > last_edit.offset:
+ raise ValueError(
+ ('Overlapping replacements: ' +
+ '%s at offset %d, length %d: "%s" and ' +
+ 'offset %d, length %d: "%s"\n') %
+ (filepath, edit.offset, edit.length, edit.replacement,
+ last_edit.offset, last_edit.length, last_edit.replacement))
contents[edit.offset:edit.offset + edit.length] = edit.replacement
if not edit.replacement:
diff --git a/chromium/tools/clang/scripts/apply_edits_test.py b/chromium/tools/clang/scripts/apply_edits_test.py
index c6cb552860d..d8edd45f869 100755
--- a/chromium/tools/clang/scripts/apply_edits_test.py
+++ b/chromium/tools/clang/scripts/apply_edits_test.py
@@ -574,6 +574,17 @@ class ApplyReplacementTest(unittest.TestCase):
with self.assertRaisesRegexp(ValueError, expected_msg_regex):
_ApplyEdit(old_text, edit)
+ def testOverlappingReplacement(self):
+ old_text = "123 456 789"
+ last = _CreateReplacement(old_text, "456 789", "foo")
+ edit = _CreateReplacement(old_text, "123 456", "bar")
+ expected_msg_regex = 'Overlapping replacements'
+ expected_msg_regex += '.*some_file.cc'
+ expected_msg_regex += '.*offset 0, length 7.*"bar"'
+ expected_msg_regex += '.*offset 4, length 7.*"foo"'
+ with self.assertRaisesRegexp(ValueError, expected_msg_regex):
+ _ApplyEdit(old_text, edit, last_edit=last)
+
if __name__ == '__main__':
unittest.main()
diff --git a/chromium/tools/clang/scripts/build.py b/chromium/tools/clang/scripts/build.py
index 2425e0b705b..3f2af8b3cf9 100755
--- a/chromium/tools/clang/scripts/build.py
+++ b/chromium/tools/clang/scripts/build.py
@@ -14,6 +14,7 @@ from __future__ import print_function
import argparse
import glob
+import io
import json
import os
import pipes
@@ -215,7 +216,7 @@ def CreateChromeToolsShim():
tool detection logic munges them in a weird way."""
assert not any(i in os.path.basename(CHROME_TOOLS_SHIM_DIR) for i in '-_')
os.mkdir(CHROME_TOOLS_SHIM_DIR)
- with file(os.path.join(CHROME_TOOLS_SHIM_DIR, 'CMakeLists.txt'), 'w') as f:
+ with open(os.path.join(CHROME_TOOLS_SHIM_DIR, 'CMakeLists.txt'), 'w') as f:
f.write('# Automatically generated by tools/clang/scripts/update.py. ' +
'Do not edit.\n')
f.write('# Since tools/clang is located in another directory, use the \n')
@@ -326,7 +327,8 @@ def VerifyVersionOfBuiltClangMatchesVERSION():
clang = os.path.join(LLVM_BUILD_DIR, 'bin', 'clang')
if sys.platform == 'win32':
clang += '-cl.exe'
- version_out = subprocess.check_output([clang, '--version'])
+ version_out = subprocess.check_output([clang, '--version'],
+ universal_newlines=True)
version_out = re.match(r'clang version ([0-9.]+)', version_out).group(1)
if version_out != RELEASE_VERSION:
print(('unexpected clang version %s (not %s), '
@@ -339,33 +341,29 @@ def CopyLibstdcpp(args, build_dir):
if not args.gcc_toolchain:
return
# Find libstdc++.so.6
- libstdcpp = subprocess.check_output(
- [os.path.join(args.gcc_toolchain, 'bin', 'g++'),
- '-print-file-name=libstdc++.so.6']).rstrip()
+ libstdcpp = subprocess.check_output([
+ os.path.join(args.gcc_toolchain, 'bin', 'g++'),
+ '-print-file-name=libstdc++.so.6'
+ ],
+ universal_newlines=True).rstrip()
# Copy libstdc++.so.6 into the build dir so that the built binaries can find
# it. Binaries get their rpath set to $origin/../lib/. For clang, lld,
# etc. that live in the bin/ directory, this means they expect to find the .so
- # in their neighbouring lib/ dir. For other tools however, this doesn't work
- # since those exeuctables are spread out into different directories.
- # TODO(hans): Unit tests don't get rpath set at all, unittests/ copying
- # below doesn't help at the moment.
+ # in their neighbouring lib/ dir.
+ # For unit tests we pass -Wl,-rpath to the linker pointing to the lib64 dir
+ # in the gcc toolchain, via LLVM_LOCAL_RPATH below.
+ # The two fuzzer tests are weird in that they copy the fuzzer binary from bin/
+ # into the test tree under a different name. To make the relative rpath in
+ # them work, copy libstdc++ to the copied location for now.
+ # TODO(thakis): Instead, make the upstream lit.local.cfg.py for these 2 tests
+ # check if the binary contains an rpath and if so disable the tests.
for d in ['lib',
'test/tools/llvm-isel-fuzzer/lib',
- 'test/tools/llvm-opt-fuzzer/lib',
- 'unittests/CodeGen/lib',
- 'unittests/DebugInfo/lib',
- 'unittests/ExecutionEngine/lib',
- 'unittests/Support/lib',
- 'unittests/Target/lib',
- 'unittests/Transforms/lib',
- 'unittests/lib',
- 'unittests/tools/lib',
- 'unittests/tools/llvm-exegesis/lib']:
+ 'test/tools/llvm-opt-fuzzer/lib']:
EnsureDirExists(os.path.join(build_dir, d))
CopyFile(libstdcpp, os.path.join(build_dir, d))
-
def gn_arg(v):
if v == 'True':
return True
@@ -437,7 +435,16 @@ def main():
# Don't buffer stdout, so that print statements are immediately flushed.
- sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+ # LLVM tests print output without newlines, so with buffering they won't be
+ # immediately printed.
+ major, _, _, _, _ = sys.version_info
+ if major == 3:
+ # Python3 only allows unbuffered output for binary streams. This
+ # workaround comes from https://stackoverflow.com/a/181654/4052492.
+ sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0),
+ write_through=True)
+ else:
+ sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
# The gnuwin package also includes curl, which is needed to interact with the
# github API below.
@@ -478,14 +485,6 @@ def main():
# LLVM_ENABLE_LLD).
cc, cxx, lld = None, None, None
- if args.gcc_toolchain:
- # Use the specified gcc installation for building.
- cc = os.path.join(args.gcc_toolchain, 'bin', 'gcc')
- cxx = os.path.join(args.gcc_toolchain, 'bin', 'g++')
- if not os.access(cc, os.X_OK):
- print('Invalid --gcc-toolchain: ' + args.gcc_toolchain)
- return 1
-
cflags = []
cxxflags = []
ldflags = []
@@ -519,6 +518,18 @@ def main():
'-DLLVM_INCLUDE_GO_TESTS=OFF',
]
+ if args.gcc_toolchain:
+ # Use the specified gcc installation for building.
+ cc = os.path.join(args.gcc_toolchain, 'bin', 'gcc')
+ cxx = os.path.join(args.gcc_toolchain, 'bin', 'g++')
+ if not os.access(cc, os.X_OK):
+ print('Invalid --gcc-toolchain: ' + args.gcc_toolchain)
+ return 1
+ base_cmake_args += [
+ '-DLLVM_LOCAL_RPATH=' + os.path.join(args.gcc_toolchain, 'lib64')
+ ]
+
+
if sys.platform == 'darwin':
# For libc++, we only want the headers.
base_cmake_args.extend([
@@ -531,7 +542,7 @@ def main():
if args.gcc_toolchain:
# Don't use the custom gcc toolchain when building compiler-rt tests; those
# tests are built with the just-built Clang, and target both i386 and x86_64
- # for example, so should ust the system's libstdc++.
+ # for example, so should use the system's libstdc++.
base_cmake_args.append(
'-DCOMPILER_RT_TEST_COMPILER_CFLAGS=--gcc-toolchain=')
@@ -867,28 +878,10 @@ def main():
CopyDirectoryContents(rt_lib_src_dir, rt_lib_dst_dir)
if args.with_android:
- make_toolchain = os.path.join(
- ANDROID_NDK_DIR, 'build', 'tools', 'make_standalone_toolchain.py')
# TODO(thakis): Now that the NDK uses clang, try to build all archs in
- # one LLVM build instead of making 3 different toolchains and building
- # 3 times.
+ # one LLVM build instead of building 3 times.
+ toolchain_dir = ANDROID_NDK_DIR + '/toolchains/llvm/prebuilt/linux-x86_64'
for target_arch in ['aarch64', 'arm', 'i686']:
- # Make standalone Android toolchain for target_arch.
- toolchain_dir = os.path.join(
- LLVM_BUILD_DIR, 'android-toolchain-' + target_arch)
- api_level = '21' if target_arch == 'aarch64' else '19'
- RunCommand([
- make_toolchain,
- '--api=' + api_level,
- '--force',
- '--install-dir=%s' % toolchain_dir,
- '--stl=libc++',
- '--arch=' + {
- 'aarch64': 'arm64',
- 'arm': 'arm',
- 'i686': 'x86',
- }[target_arch]])
-
# Build compiler-rt runtimes needed for Android in a separate build tree.
build_dir = os.path.join(LLVM_BUILD_DIR, 'android-' + target_arch)
if not os.path.exists(build_dir):
@@ -897,10 +890,13 @@ def main():
target_triple = target_arch
if target_arch == 'arm':
target_triple = 'armv7'
+ api_level = '21' if target_arch == 'aarch64' else '19'
target_triple += '-linux-android' + api_level
- cflags = ['--target=%s' % target_triple,
- '--sysroot=%s/sysroot' % toolchain_dir,
- '-B%s' % toolchain_dir]
+ cflags = [
+ '--target=' + target_triple,
+ '--sysroot=%s/sysroot' % toolchain_dir,
+ '--gcc-toolchain=' + toolchain_dir,
+ ]
android_args = base_cmake_args + [
'-DCMAKE_C_COMPILER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang'),
'-DCMAKE_CXX_COMPILER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang++'),
diff --git a/chromium/tools/clang/scripts/clang_tidy_tool.py b/chromium/tools/clang/scripts/clang_tidy_tool.py
index 57e54f7049d..afbe12bb45d 100755
--- a/chromium/tools/clang/scripts/clang_tidy_tool.py
+++ b/chromium/tools/clang/scripts/clang_tidy_tool.py
@@ -107,8 +107,7 @@ def RunClangTidy(checks, header_filter, auto_fix, clang_src_dir,
subprocess.check_call(args)
-def RunClangTidyDiff(checks, header_filter, auto_fix, clang_src_dir,
- clang_build_dir, out_dir):
+def RunClangTidyDiff(checks, auto_fix, clang_src_dir, clang_build_dir, out_dir):
"""Invoke the |clang-tidy-diff.py| script over the diff from stdin."""
clang_tidy_diff_script = os.path.join(
clang_src_dir, 'clang-tools-extra', 'clang-tidy', 'tool',
@@ -129,9 +128,6 @@ def RunClangTidyDiff(checks, header_filter, auto_fix, clang_src_dir,
if checks:
args.append('-checks={}'.format(checks))
- if header_filter:
- args.append('-header-filter={}'.format(header_filter))
-
if auto_fix:
args.append('-fix')
@@ -202,11 +198,9 @@ def main():
]
if args.diff:
steps += [
- ('Running clang-tidy on diff',
- lambda: RunClangTidyDiff(args.checks, args.header_filter,
- args.auto_fix, args.clang_src_dir,
- args.clang_build_dir, args.OUT_DIR,
- args.NINJA_TARGET)),
+ ('Running clang-tidy on diff', lambda: RunClangTidyDiff(
+ args.checks, args.auto_fix, args.clang_src_dir, args.
+ clang_build_dir, args.OUT_DIR)),
]
else:
steps += [
diff --git a/chromium/tools/clang/scripts/expand_thin_archives.py b/chromium/tools/clang/scripts/expand_thin_archives.py
index ede95921f77..b51393587da 100755
--- a/chromium/tools/clang/scripts/expand_thin_archives.py
+++ b/chromium/tools/clang/scripts/expand_thin_archives.py
@@ -12,120 +12,10 @@ from __future__ import print_function
from __future__ import unicode_literals
import argparse
-import errno
-import io
-import os
-import re
import sys
-COMPILER_RE = re.compile('clang')
-LINKER_RE = re.compile('l(?:ld|ink)')
-LIB_RE = re.compile('.*\\.(?:a|lib)', re.IGNORECASE)
-OBJ_RE = re.compile(b'(.*)\\.(o(?:bj)?)', re.IGNORECASE)
-THIN_AR_LFN_RE = re.compile('/([0-9]+)')
-
-
-def ensure_dir(path):
- """
- Creates path as a directory if it does not already exist.
- """
- try:
- os.makedirs(path)
- except OSError as e:
- if e.errno != errno.EEXIST:
- raise
-
-
-def thin_archive(path):
- """
- Returns True if path refers to a thin archive (ar file), False if not.
- """
- with open(path, 'rb') as f:
- return f.read(8) == b'!<thin>\n'
-
-
-def write_rsp(path, params):
- """
- Writes params to a newly created response file at path.
- """
- ensure_dir(os.path.basename(path))
- with open(path, 'wb') as f:
- f.write(b'\n'.join(params))
-
-
-def names_in_archive(path):
- """
- Yields the member names in the archive file at path.
- """
- with open(path, 'rb') as f:
- long_names = None
- f.seek(8, io.SEEK_CUR)
- while True:
- file_id = f.read(16)
- if len(file_id) == 0:
- break
- f.seek(32, io.SEEK_CUR)
- m = THIN_AR_LFN_RE.match(file_id)
- if long_names and m:
- name_pos = long(m.group(1))
- name_end = long_names.find('/\n', name_pos)
- name = long_names[name_pos:name_end]
- else:
- name = file_id
- try:
- size = long(f.read(10))
- except:
- sys.stderr.write('While parsing %r, pos %r\n' % (path, f.tell()))
- raise
- # Two entries are special: '/' and '//'. The former is
- # the symbol table, which we skip. The latter is the long
- # file name table, which we read.
- # Anything else is a filename entry which we yield.
- # Every file record ends with two terminating characters
- # which we skip.
- seek_distance = 2
- if file_id == '/ ':
- # Skip symbol table.
- seek_distance += size + (size & 1)
- elif file_id == '// ':
- # Read long name table.
- f.seek(2, io.SEEK_CUR)
- long_names = f.read(size)
- seek_distance = size & 1
- else:
- yield name
- f.seek(seek_distance, io.SEEK_CUR)
-
-
-def expand_args(args, linker_prefix=''):
- """
- Yields the parameters in args, with thin archives replaced by a sequence of
- '-start-lib', the member names, and '-end-lib'. This is used to get a command
- line where members of thin archives are mentioned explicitly.
- """
- for arg in args:
- if len(arg) > 1 and arg[0] == '@':
- for x in expand_rsp(arg[1:], linker_prefix):
- yield x
- elif LIB_RE.match(arg) and os.path.exists(arg) and thin_archive(arg):
- yield(linker_prefix + '-start-lib')
- for name in names_in_archive(arg):
- yield(os.path.dirname(arg) + '/' + name)
- yield(linker_prefix + '-end-lib')
- else:
- yield(arg)
-
-
-def expand_rsp(rspname, linker_prefix=''):
- """
- Yields the parameters found in the response file at rspname, with thin
- archives replaced by a sequence of '-start-lib', the member names,
- and '-end-lib'. This is used to get a command line where members of
- thin archives are mentioned explicitly.
- """
- with open(rspname) as f:
- for x in expand_args(f.read().split(), linker_prefix):
- yield x
+from goma_link import GomaLinkWindows
+from goma_ld import GomaLinkUnix
def main(argv):
@@ -152,11 +42,19 @@ def main(argv):
cmdline = cmdline[1:]
linker_prefix = args.linker_prefix
+ if linker_prefix == '-Wl,':
+ linker = GomaLinkUnix()
+ else:
+ linker = GomaLinkWindows()
+
+ rsp_expanded = list(linker.expand_args_rsps(cmdline))
+ expanded_args = list(linker.expand_thin_archives(rsp_expanded))
+
if args.output:
output = open(args.output, 'w')
else:
output = sys.stdout
- for arg in expand_args(cmdline, linker_prefix=linker_prefix):
+ for arg in expanded_args:
output.write('%s\n' % (arg,))
if args.output:
output.close()
diff --git a/chromium/tools/clang/scripts/goma_ld.py b/chromium/tools/clang/scripts/goma_ld.py
index 9a7365bf90c..576dfa9f9d2 100755
--- a/chromium/tools/clang/scripts/goma_ld.py
+++ b/chromium/tools/clang/scripts/goma_ld.py
@@ -26,6 +26,8 @@ class GomaLinkUnix(goma_link.GomaLinkBase):
WL = '-Wl,'
TLTO = '-plugin-opt=thinlto'
SEP = '='
+ DATA_SECTIONS = '-fdata-sections'
+ FUNCTION_SECTIONS = '-ffunction-sections'
GROUP_RE = re.compile(WL + '--(?:end|start)-group')
MACHINE_RE = re.compile('-m([0-9]+)')
OBJ_PATH = '-plugin-opt=obj-path' + SEP
diff --git a/chromium/tools/clang/scripts/goma_link.py b/chromium/tools/clang/scripts/goma_link.py
index 7c4e5cd9534..8bf194e4bdb 100755
--- a/chromium/tools/clang/scripts/goma_link.py
+++ b/chromium/tools/clang/scripts/goma_link.py
@@ -218,6 +218,10 @@ class GomaLinkBase(object):
jobs = None
# These constants should work across platforms.
+ DATA_SECTIONS_RE = re.compile('-f(no-)?data-sections|[-/]Gw(-)?',
+ re.IGNORECASE)
+ FUNCTION_SECTIONS_RE = re.compile('-f(no-)?function-sections|[-/]Gy(-)?',
+ re.IGNORECASE)
LIB_RE = re.compile('.*\\.(?:a|lib)', re.IGNORECASE)
LTO_RE = re.compile('|'.join((
'-fsanitize=cfi.*',
@@ -227,8 +231,36 @@ class GomaLinkBase(object):
'-Wl,--lto.*',
'-Wl,--thin.*',
)))
+ MLLVM_RE = re.compile('(?:-Wl,)?([-/]mllvm)[:=]?(.*)', re.IGNORECASE)
OBJ_RE = re.compile('(.*)\\.(o(?:bj)?)', re.IGNORECASE)
+ def transform_codegen_param(self, param):
+ return self.transform_codegen_param_common(param)
+
+ def transform_codegen_param_common(self, param):
+ """
+ If param is a parameter relevant to code generation, returns the
+ parameter in a form that is suitable to pass to clang. For values
+ of param that are not relevant to code generation, returns None.
+ """
+ match = self.MACHINE_RE.match(param)
+ if match and match.group(1).lower() in ['x86', 'i386', 'arm', '32']:
+ return ['-m32']
+ match = self.MLLVM_RE.match(param)
+ if match:
+ if match.group(2):
+ return ['-mllvm', match.group(2)]
+ else:
+ return ['-mllvm']
+ if (param.startswith('-f') and not param.startswith('-flto')
+ and not param.startswith('-fsanitize')
+ and not param.startswith('-fthinlto')
+ and not param.startswith('-fwhole-program')):
+ return [param]
+ if param.startswith('-g'):
+ return [param]
+ return None
+
def output_path(self, args):
"""
Analyzes command line arguments in args and returns the output
@@ -354,33 +386,11 @@ class GomaLinkBase(object):
]
final_params = []
in_mllvm = [False]
- optlevel = [2]
-
- MLLVM_RE = re.compile('(?:-Wl,)?([-/]mllvm)[:=]?(.*)', re.IGNORECASE)
- def transform_codegen_param(param):
- """
- If param is a parameter relevant to code generation, returns the
- parameter in a form that is suitable to pass to clang. For values
- of param that are not relevant to code generation, returns None.
- """
- match = self.MACHINE_RE.match(param)
- if match and match.group(1).lower() in ['x86', 'i386', 'arm', '32']:
- return ['-m32']
- match = MLLVM_RE.match(param)
- if match:
- if match.group(2):
- return ['-mllvm', match.group(2)]
- else:
- return ['-mllvm']
- if (param.startswith('-f') and not param.startswith('-flto')
- and not param.startswith('-fsanitize')
- and not param.startswith('-fthinlto')
- and not param.startswith('-fwhole-program')):
- return [param]
- if param.startswith('-g'):
- return [param]
- return None
+ # Defaults that match those for local linking.
+ optlevel = [2]
+ data_sections = [True]
+ function_sections = [True]
def extract_opt_level(param):
"""
@@ -422,17 +432,24 @@ class GomaLinkBase(object):
return
# Check for params that affect code generation.
- cg_param = transform_codegen_param(param)
+ cg_param = self.transform_codegen_param(param)
if cg_param:
codegen_params.extend(cg_param)
# No return here, we still want to check for -mllvm.
# Check for -mllvm.
- match = MLLVM_RE.match(param)
+ match = self.MLLVM_RE.match(param)
if match and not match.group(2):
# Next parameter will be the thing to pass to LLVM.
in_mllvm[0] = True
+ # Parameters that override defaults disable the defaults; the
+ # final value is set by passing through the parameter.
+ if self.DATA_SECTIONS_RE.match(param):
+ data_sections[0] = False
+ if self.FUNCTION_SECTIONS_RE.match(param):
+ function_sections[0] = False
+
helper()
if self.GROUP_RE.match(param):
return
@@ -452,7 +469,7 @@ class GomaLinkBase(object):
elif not self.LTO_RE.match(param):
final_params.append(param)
- index_params.append(self.WL + self.PREFIX_REPLACE + ';' + obj_dir)
+ index_params.append(self.WL + self.PREFIX_REPLACE + ';' + obj_dir + '/')
i = 0
while i < len(args):
x = args[i]
@@ -471,6 +488,10 @@ class GomaLinkBase(object):
return None
codegen_params.append('-O' + str(optlevel[0]))
+ if data_sections[0]:
+ codegen_params.append(self.DATA_SECTIONS)
+ if function_sections[0]:
+ codegen_params.append(self.FUNCTION_SECTIONS)
if use_common_objects:
splitfile = None
@@ -623,6 +644,8 @@ class GomaLinkWindows(GomaLinkBase):
WL = ''
TLTO = '-thinlto'
SEP = ':'
+ DATA_SECTIONS = '-Gw'
+ FUNCTION_SECTIONS = '-Gy'
GROUP_RE = re.compile(WL + '--(?:end|start)-group')
MACHINE_RE = re.compile('[-/]machine:(.*)', re.IGNORECASE)
OBJ_PATH = '-lto-obj-path' + SEP
@@ -641,6 +664,14 @@ class GomaLinkWindows(GomaLinkBase):
'tls_edit.exe',
}
+ def transform_codegen_param(self, param):
+ # In addition to parameters handled by transform_codegen_param_common,
+ # we pass on parameters that start in 'G' or 'Q', which are
+ # MSVC-style parameters that affect code generation.
+ if len(param) >= 2 and param[0] in ['-', '/'] and param[1] in ['G', 'Q']:
+ return [param]
+ return self.transform_codegen_param_common(param)
+
def process_output_param(self, args, i):
"""
If args[i] is a parameter that specifies the output file,
diff --git a/chromium/tools/clang/scripts/goma_link_unit_tests.py b/chromium/tools/clang/scripts/goma_link_unit_tests.py
index e35179d36fb..255ff6ad1f6 100755
--- a/chromium/tools/clang/scripts/goma_link_unit_tests.py
+++ b/chromium/tools/clang/scripts/goma_link_unit_tests.py
@@ -125,6 +125,84 @@ class GomaLinkUnitTest(unittest.TestCase):
self.assertNotIn('-flto=thin', result.final_params)
+ def test_codegen_params_default(self):
+ with FakeFs(bitcode_files=['foo.o'], other_files=['bar.o']):
+ result = goma_ld.GomaLinkUnix().analyze_expanded_args(
+ ['clang', 'foo.o', 'bar.o', '-o', 'foo'], 'foo', 'clang', 'lto.foo',
+ 'common', False)
+ # Codegen optimization level should default to 2.
+ self.assertIn('-O2', result.codegen_params)
+ # -fdata-sections and -ffunction-sections default to on to match the
+ # behavior of local linking.
+ self.assertIn('-fdata-sections', result.codegen_params)
+ self.assertIn('-ffunction-sections', result.codegen_params)
+
+ def test_codegen_params_default_cl(self):
+ with FakeFs(bitcode_files=['foo.obj'], other_files=['bar.obj']):
+ result = goma_link.GomaLinkWindows().analyze_expanded_args(
+ ['clang-cl', 'foo.obj', 'bar.obj', '-Fefoo.exe'], 'foo.exe',
+ 'clang-cl', 'lto.foo', 'common', False)
+ # Codegen optimization level should default to 2.
+ self.assertIn('-O2', result.codegen_params)
+ # -Gw and -Gy default to on to match the behavior of local linking.
+ self.assertIn('-Gw', result.codegen_params)
+ self.assertIn('-Gy', result.codegen_params)
+
+ def test_codegen_params_no_data_sections(self):
+ with FakeFs(bitcode_files=['foo.o'], other_files=['bar.o']):
+ result = goma_ld.GomaLinkUnix().analyze_expanded_args(
+ ['clang', '-fno-data-sections', 'foo.o', 'bar.o', '-o', 'foo'], 'foo',
+ 'clang', 'lto.foo', 'common', False)
+ self.assertNotIn('-fdata-sections', result.codegen_params)
+ self.assertIn('-ffunction-sections', result.codegen_params)
+
+ def test_codegen_params_no_function_sections(self):
+ with FakeFs(bitcode_files=['foo.o'], other_files=['bar.o']):
+ result = goma_ld.GomaLinkUnix().analyze_expanded_args(
+ ['clang', '-fno-function-sections', 'foo.o', 'bar.o', '-o', 'foo'],
+ 'foo', 'clang', 'lto.foo', 'common', False)
+ self.assertIn('-fdata-sections', result.codegen_params)
+ self.assertNotIn('-ffunction-sections', result.codegen_params)
+
+ def test_codegen_params_no_data_sections_cl(self):
+ with FakeFs(bitcode_files=['foo.obj'], other_files=['bar.obj']):
+ result = goma_link.GomaLinkWindows().analyze_expanded_args(
+ ['clang-cl', '/Gw-', 'foo.obj', 'bar.obj', '/Fefoo.exe'], 'foo.exe',
+ 'clang-cl', 'lto.foo', 'common', False)
+ self.assertNotIn('-fdata-sections', result.codegen_params)
+ self.assertNotIn('-Gw', result.codegen_params)
+ self.assertNotIn('/Gw', result.codegen_params)
+ self.assertIn('-Gy', result.codegen_params)
+
+ def test_codegen_params_no_function_sections_cl(self):
+ with FakeFs(bitcode_files=['foo.obj'], other_files=['bar.obj']):
+ result = goma_link.GomaLinkWindows().analyze_expanded_args(
+ ['clang-cl', '/Gy-', 'foo.obj', 'bar.obj', '/Fefoo.exe'], 'foo.exe',
+ 'clang-cl', 'lto.foo', 'common', False)
+ self.assertIn('-Gw', result.codegen_params)
+ self.assertNotIn('-ffunction-sections', result.codegen_params)
+ self.assertNotIn('-Gy', result.codegen_params)
+ self.assertNotIn('/Gy', result.codegen_params)
+
+ def test_codegen_params_explicit_data_and_function_sections(self):
+ with FakeFs(bitcode_files=['foo.o'], other_files=['bar.o']):
+ result = goma_ld.GomaLinkUnix().analyze_expanded_args([
+ 'clang', '-ffunction-sections', '-fdata-sections', 'foo.o', 'bar.o',
+ '-o', 'foo'
+ ], 'foo', 'clang', 'lto.foo', 'common', False)
+ self.assertIn('-fdata-sections', result.codegen_params)
+ self.assertIn('-ffunction-sections', result.codegen_params)
+
+ def test_codegen_params_explicit_data_and_function_sections_cl(self):
+ with FakeFs(bitcode_files=['foo.obj'], other_files=['bar.obj']):
+ result = goma_link.GomaLinkWindows().analyze_expanded_args(
+ ['clang-cl', '/Gy', '-Gw', 'foo.obj', 'bar.obj', '/Fefoo.exe'],
+ 'foo.exe', 'clang-cl', 'lto.foo', 'common', False)
+ self.assertIn('-Gw', result.codegen_params)
+ self.assertIn('/Gy', result.codegen_params)
+ self.assertNotIn('-fdata-sections', result.codegen_params)
+ self.assertNotIn('-ffunction-sections', result.codegen_params)
+
def test_ensure_file_no_dir(self):
with named_directory() as d, working_directory(d):
self.assertFalse(os.path.exists('test'))
diff --git a/chromium/tools/clang/scripts/update.py b/chromium/tools/clang/scripts/update.py
index 83e0ede51fb..c9bdcf3ae20 100755
--- a/chromium/tools/clang/scripts/update.py
+++ b/chromium/tools/clang/scripts/update.py
@@ -37,8 +37,8 @@ import zipfile
# Do NOT CHANGE this if you don't know what you're doing -- see
# https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
# Reverting problematic clang rolls is safe, though.
-CLANG_REVISION = '99ac9ce7016d701b43b8f0c308dc3463da57d983'
-CLANG_SVN_REVISION = 'n353803'
+CLANG_REVISION = '4e813bbdf'
+CLANG_SVN_REVISION = 'n356902'
CLANG_SUB_REVISION = 1
PACKAGE_VERSION = '%s-%s-%s' % (CLANG_SVN_REVISION, CLANG_REVISION[:8],
diff --git a/chromium/tools/clang/scripts/upload_revision.py b/chromium/tools/clang/scripts/upload_revision.py
index cbe0c8b961b..9cd4484cd2b 100755
--- a/chromium/tools/clang/scripts/upload_revision.py
+++ b/chromium/tools/clang/scripts/upload_revision.py
@@ -29,6 +29,7 @@ CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
# Keep lines in here at <= 72 columns, else they wrap in gerrit.
COMMIT_FOOTER = \
'''
+TODO: Add bug number.
Cq-Include-Trybots: chromium/try:mac_chromium_asan_rel_ng
Cq-Include-Trybots: chromium/try:linux_chromium_cfi_rel_ng
@@ -39,7 +40,7 @@ Cq-Include-Trybots: chromium/try:linux-chromeos-dbg,win-asan
Cq-Include-Trybots: chromium/try:chromeos-amd64-generic-cfi-thin-lto-rel
Cq-Include-Trybots: chromium/try:linux_chromium_compile_dbg_32_ng
Cq-Include-Trybots: chromium/try:win7-rel,win-angle-deqp-rel-32
-Cq-Include-Trybots: chromium/try:win-angle-deqp-rel-64
+Cq-Include-Trybots: chromium/try:win-angle-deqp-rel-64,linux_angle_deqp_rel_ng
Cq-Include-Trybots: chromium/try:dawn-win10-x86-deps-rel
Cq-Include-Trybots: chrome/try:iphone-device,ipad-device
Cq-Include-Trybots: chrome/try:linux-chromeos-chrome