Commit 10118bff authored by dpranke's avatar dpranke Committed by Commit bot

Revert of Update MB to use `gn analyze`. (patchset #9 id:160001 of...

Revert of Update MB to use `gn analyze`. (patchset #9 id:160001 of https://codereview.chromium.org/2298403002/ )

Reason for revert:
Need to add "aura_builder", probably others ...

Original issue's description:
> Update MB to use `gn analyze`.
>
> Now that GN supports a form of `analyze` directly, this patch
> updates //tools/mb to use it rather than working awkwardly through
> `gn refs`. The MB implementation now is mostly responsible for
> mapping ninja targets to labels, calling GN, and then mapping returned
> labels back to ninja targets. Eventually we should update the
> recipes to just pass labels around instead.
>
> One significant change is that now we need entries in gn_isolate_map.pyl
> for every target listed in 'additional_compile_targets' and
> 'isolated_scripts' as well as in 'gtest_tests', because we have to remap
> everything to the GN labels, not just tests for swarming.
>
> We should switch everything to using GN labels directly, but that'll require
> follow-on CLs.
>
> R=brettw@chromium.org
> BUG=555273
>
> Committed: https://crrev.com/9aba8b21177df3ed3e897d5c500d845fbf5523e6
> Cr-Commit-Position: refs/heads/master@{#419315}

TBR=phajdan.jr@chromium.org,brettw@chromium.org,kbr@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=555273

Review-Url: https://codereview.chromium.org/2341403004
Cr-Commit-Position: refs/heads/master@{#419321}
parent c39cece9
...@@ -27,9 +27,6 @@ ...@@ -27,9 +27,6 @@
# "gpu_browser_test" # "gpu_browser_test"
# : the test is a subset of the browser_tests that will be run against # : the test is a subset of the browser_tests that will be run against
# a real GPU. # a real GPU.
# "additional_compile_target"
# : this isn't actually a test, but we still need a mapping from the
# ninja target to the GN label in order to analyze it.
# "raw" # "raw"
# : the test is a standalone executable; it may take an optional list of # : the test is a standalone executable; it may take an optional list of
# command line arguments in the "args" field, but otherwise needs no # command line arguments in the "args" field, but otherwise needs no
...@@ -64,10 +61,6 @@ ...@@ -64,10 +61,6 @@
# "//testing/scripts/foo.py". # "//testing/scripts/foo.py".
{ {
"All": {
"label": "//:All",
"type": "additional_compile_target",
},
"accessibility_unittests": { "accessibility_unittests": {
"label": "//ui/accessibility:accessibility_unittests", "label": "//ui/accessibility:accessibility_unittests",
"type": "raw", "type": "raw",
...@@ -198,18 +191,10 @@ ...@@ -198,18 +191,10 @@
"label": "//chromecast/crash:cast_crash_unittests", "label": "//chromecast/crash:cast_crash_unittests",
"type": "console_test_launcher", "type": "console_test_launcher",
}, },
"cast_media_unittests": {
"label": "//chromecast/media:cast_media_unittests",
"type": "console_test_launcher",
},
"cast_shell_unittests": { "cast_shell_unittests": {
"label": "//chromecast/app:cast_shell_unittests", "label": "//chromecast/app:cast_shell_unittests",
"type": "console_test_launcher", "type": "console_test_launcher",
}, },
"cast_shell_browser_test": {
"label": "//chromecast/browser:cast_shell_browser_test",
"type": "console_test_launcher",
},
"cast_unittests": { "cast_unittests": {
"label": "//media/cast:cast_unittests", "label": "//media/cast:cast_unittests",
"type": "windowed_test_launcher", "type": "windowed_test_launcher",
...@@ -218,10 +203,6 @@ ...@@ -218,10 +203,6 @@
"label": "//cc:cc_unittests", "label": "//cc:cc_unittests",
"type": "windowed_test_launcher", "type": "windowed_test_launcher",
}, },
"chrome": {
"label": "//chrome",
"type": "additional_compile_target",
},
"chrome_app_unittests": { "chrome_app_unittests": {
"label": "//chrome/test:chrome_app_unittests", "label": "//chrome/test:chrome_app_unittests",
"type": "console_test_launcher", "type": "console_test_launcher",
...@@ -230,22 +211,10 @@ ...@@ -230,22 +211,10 @@
"label": "//chrome_elf:chrome_elf_unittests", "label": "//chrome_elf:chrome_elf_unittests",
"type": "raw", "type": "raw",
}, },
"chrome_official_builder": {
"label": "//:chrome_official_builder",
"type": "additional_compile_target",
},
"chrome_public_apk": {
"label": "//chrome/android:chrome_public_apk",
"type": "additional_compile_target",
},
"chrome_public_test_apk": { "chrome_public_test_apk": {
"label": "//chrome/android:chrome_public_test_apk", "label": "//chrome/android:chrome_public_test_apk",
"type": "console_test_launcher", "type": "console_test_launcher",
}, },
"chromium_swarm_tests": {
"label": "//:chromium_swarm_tests",
"type": "additional_compile_target",
},
"chrome_sync_shell_test_apk": { "chrome_sync_shell_test_apk": {
"label": "//chrome/android:chrome_sync_shell_test_apk", "label": "//chrome/android:chrome_sync_shell_test_apk",
"type": "console_test_launcher", "type": "console_test_launcher",
...@@ -305,14 +274,6 @@ ...@@ -305,14 +274,6 @@
"label": "//courgette:courgette_unittests", "label": "//courgette:courgette_unittests",
"type": "console_test_launcher", "type": "console_test_launcher",
}, },
"cronet_package": {
"label": "//components/cronet/android:cronet_package",
"type": "additional_compile_target",
},
"cronet_test_instrumentation_apk": {
"label": "//cronet_test_instrumentation_apk",
"type": "additional_compile_target",
},
"crypto_unittests": { "crypto_unittests": {
"label": "//crypto:crypto_unittests", "label": "//crypto:crypto_unittests",
"type": "console_test_launcher", "type": "console_test_launcher",
...@@ -380,10 +341,6 @@ ...@@ -380,10 +341,6 @@
"type": "raw", "type": "raw",
"args": [], "args": [],
}, },
"gn_all": {
"label": "//:gn_all",
"type": "additional_compile_target",
},
"gn_unittests": { "gn_unittests": {
"label": "//tools/gn:gn_unittests", "label": "//tools/gn:gn_unittests",
"type": "raw", "type": "raw",
...@@ -401,22 +358,10 @@ ...@@ -401,22 +358,10 @@
"label": "//gpu:gpu_unittests", "label": "//gpu:gpu_unittests",
"type": "windowed_test_launcher", "type": "windowed_test_launcher",
}, },
"headless_lib": {
"label": "//headless:headless_lib",
"type": "additional_compile_target",
},
"headless_browsertests": { "headless_browsertests": {
"label": "//headless:headless_browsertests", "label": "//headless:headless_browsertests",
"type": "console_test_launcher", "type": "console_test_launcher",
}, },
"headless_shell": {
"label": "//headless:headless_shell",
"type": "additional_compile_target",
},
"headless_tests": {
"label": "//headless:headless_tests",
"type": "additional_compile_target",
},
"headless_unittests": { "headless_unittests": {
"label": "//headless:headless_unittests", "label": "//headless:headless_unittests",
"type": "console_test_launcher", "type": "console_test_launcher",
...@@ -454,23 +399,19 @@ ...@@ -454,23 +399,19 @@
"type": "console_test_launcher", "type": "console_test_launcher",
}, },
# See http://crbug.com/585151 # See http://crbug.com/585151
"libaddressinput_unittests": { #"libaddressinput_unittests": {
"label": "//third_party/libaddressinput:libaddressinput_unittests", #"label": "//third_party/libaddressinput:libaddressinput_unittests",
"type": "console_test_launcher", #"type": "console_test_launcher",
}, #},
# See http://crbug.com/585151 # See http://crbug.com/585151
"libphonenumber_unittests": { #"libphonenumber_unittests": {
"label": "//third_party/libphonenumber:libphonenumber_unittests", #"label": "//third_party/libphonenumber:libphonenumber_unittests",
"type": "console_test_launcher", #"type": "console_test_launcher",
}, #},
"mac_installer_unittests": { "mac_installer_unittests": {
"label": "//chrome/installer/mac/app:mac_installer_unittests", "label": "//chrome/installer/mac/app:mac_installer_unittests",
"type": "console_test_launcher", "type": "console_test_launcher",
}, },
"mash:all" : {
"label": "//mash:all",
"type": "additional_compile_target",
},
"media_unittests": { "media_unittests": {
"label": "//media:media_unittests", "label": "//media:media_unittests",
"type": "windowed_test_launcher", "type": "windowed_test_launcher",
...@@ -658,10 +599,6 @@ ...@@ -658,10 +599,6 @@
"label": "//chrome/test:sync_integration_tests", "label": "//chrome/test:sync_integration_tests",
"type": "windowed_test_launcher", "type": "windowed_test_launcher",
}, },
"system_webview_apk": {
"label": "//android_webview:system_webview_apk",
"type": "additional_compile_target",
},
"system_wrappers_unittests": { "system_wrappers_unittests": {
"label": "//webrtc/system_wrappers:system_wrappers_unittests", "label": "//webrtc/system_wrappers:system_wrappers_unittests",
"type": "console_test_launcher", "type": "console_test_launcher",
......
...@@ -132,14 +132,28 @@ SKIP = { ...@@ -132,14 +132,28 @@ SKIP = {
SKIP_GN_ISOLATE_MAP_TARGETS = { SKIP_GN_ISOLATE_MAP_TARGETS = {
'all', # TODO(GYP): These targets have not been ported to GN yet.
'chromium_swarm_tests', 'android_webview_unittests',
'angle_deqp_gles2_tests',
'angle_deqp_gles3_tests',
'cast_media_unittests',
'cast_shell_browser_test',
'chromevox_tests',
'nacl_helper_nonsfi_unittests',
# TODO(kbr): teach this script about isolated_scripts tests.
# crbug.com/620531
'telemetry_gpu_integration_test',
'telemetry_gpu_test',
'telemetry_gpu_unittests',
'telemetry_perf_tests',
'telemetry_perf_unittests',
'telemetry_unittests',
# These tests are only run on WebRTC CI. # These tests are only run on WebRTC CI.
'audio_decoder_unittests', 'audio_decoder_unittests',
'common_audio_unittests', 'common_audio_unittests',
'common_video_unittests', 'common_video_unittests',
'frame_analyzer',
'modules_tests', 'modules_tests',
'modules_unittests', 'modules_unittests',
'peerconnection_unittests', 'peerconnection_unittests',
...@@ -219,36 +233,23 @@ def process_file(mode, test_name, tests_location, filepath, ninja_targets, ...@@ -219,36 +233,23 @@ def process_file(mode, test_name, tests_location, filepath, ninja_targets,
continue continue
if not isinstance(data, dict): if not isinstance(data, dict):
raise Error('%s: %s is broken: %s' % (filename, builder, data)) raise Error('%s: %s is broken: %s' % (filename, builder, data))
if ('gtest_tests' not in data and if 'gtest_tests' not in data:
'isolated_scripts' not in data and
'additional_compile_targets' not in data):
continue continue
if not isinstance(data['gtest_tests'], list):
for target in data.get('additional_compile_targets', []):
if (target not in ninja_targets and
target not in SKIP_GN_ISOLATE_MAP_TARGETS):
raise Error('%s: %s / %s is not listed in gn_isolate_map.pyl' %
(filename, builder, target))
elif target in ninja_targets:
ninja_targets_seen.add(target)
gtest_tests = data.get('gtest_tests', [])
if not isinstance(gtest_tests, list):
raise Error( raise Error(
'%s: %s is broken: %s' % (filename, builder, gtest_tests)) '%s: %s is broken: %s' % (filename, builder, data['gtest_tests']))
if not all(isinstance(g, dict) for g in gtest_tests): if not all(isinstance(g, dict) for g in data['gtest_tests']):
raise Error( raise Error(
'%s: %s is broken: %s' % (filename, builder, gtest_tests)) '%s: %s is broken: %s' % (filename, builder, data['gtest_tests']))
seen = set() seen = set()
for d in gtest_tests: for d in data['gtest_tests']:
test = d['test'] if (d['test'] not in ninja_targets and
if (test not in ninja_targets and d['test'] not in SKIP_GN_ISOLATE_MAP_TARGETS):
test not in SKIP_GN_ISOLATE_MAP_TARGETS):
raise Error('%s: %s / %s is not listed in gn_isolate_map.pyl.' % raise Error('%s: %s / %s is not listed in gn_isolate_map.pyl.' %
(filename, builder, test)) (filename, builder, d['test']))
elif test in ninja_targets: elif d['test'] in ninja_targets:
ninja_targets_seen.add(test) ninja_targets_seen.add(d['test'])
name = d.get('name', d['test']) name = d.get('name', d['test'])
if name in seen: if name in seen:
...@@ -258,18 +259,8 @@ def process_file(mode, test_name, tests_location, filepath, ninja_targets, ...@@ -258,18 +259,8 @@ def process_file(mode, test_name, tests_location, filepath, ninja_targets,
d.setdefault('swarming', {}).setdefault( d.setdefault('swarming', {}).setdefault(
'can_use_on_swarming_builders', False) 'can_use_on_swarming_builders', False)
if gtest_tests: config[builder]['gtest_tests'] = sorted(
config[builder]['gtest_tests'] = sorted( data['gtest_tests'], key=lambda x: x['test'])
gtest_tests, key=lambda x: x['test'])
for d in data.get('isolated_scripts', []):
name = d['isolate_name']
if (name not in ninja_targets and
name not in SKIP_GN_ISOLATE_MAP_TARGETS):
raise Error('%s: %s / %s is not listed in gn_isolate_map.pyl.' %
(filename, builder, name))
elif name in ninja_targets:
ninja_targets_seen.add(name)
# The trick here is that process_builder_remaining() is called before # The trick here is that process_builder_remaining() is called before
# process_builder_convert() so tests_location can be used to know how many # process_builder_convert() so tests_location can be used to know how many
......
...@@ -61,7 +61,7 @@ class MetaBuildWrapper(object): ...@@ -61,7 +61,7 @@ class MetaBuildWrapper(object):
self.DumpInputFiles() self.DumpInputFiles()
return ret return ret
except KeyboardInterrupt: except KeyboardInterrupt:
self.Print('interrupted, exiting') self.Print('interrupted, exiting', stream=sys.stderr)
return 130 return 130
except Exception: except Exception:
self.DumpInputFiles() self.DumpInputFiles()
...@@ -229,7 +229,7 @@ class MetaBuildWrapper(object): ...@@ -229,7 +229,7 @@ class MetaBuildWrapper(object):
def DumpContentsOfFilePassedTo(arg_name, path): def DumpContentsOfFilePassedTo(arg_name, path):
if path and self.Exists(path): if path and self.Exists(path):
self.Print("\n# To recreate the file passed to %s:" % arg_name) self.Print("\n# To recreate the file passed to %s:" % arg_name)
self.Print("%% cat > %s <<EOF" % path) self.Print("%% cat > %s <<EOF)" % path)
contents = self.ReadFile(path) contents = self.ReadFile(path)
self.Print(contents) self.Print(contents)
self.Print("EOF\n%\n") self.Print("EOF\n%\n")
...@@ -643,10 +643,6 @@ class MetaBuildWrapper(object): ...@@ -643,10 +643,6 @@ class MetaBuildWrapper(object):
self.masters = contents['masters'] self.masters = contents['masters']
self.mixins = contents['mixins'] self.mixins = contents['mixins']
def ReadIsolateMap(self):
return ast.literal_eval(self.ReadFile(self.PathJoin(
self.chromium_src_dir, 'testing', 'buildbot', 'gn_isolate_map.pyl')))
def ConfigFromArgs(self): def ConfigFromArgs(self):
if self.args.config: if self.args.config:
if self.args.master or self.args.builder: if self.args.master or self.args.builder:
...@@ -774,7 +770,7 @@ class MetaBuildWrapper(object): ...@@ -774,7 +770,7 @@ class MetaBuildWrapper(object):
if getattr(self.args, 'swarming_targets_file', None): if getattr(self.args, 'swarming_targets_file', None):
# We need GN to generate the list of runtime dependencies for # We need GN to generate the list of runtime dependencies for
# the compile targets listed (one per line) in the file so # the compile targets listed (one per line) in the file so
# we can run them via swarming. We use gn_isolate_map.pyl to convert # we can run them via swarming. We use ninja_to_gn.pyl to convert
# the compile targets to the matching GN labels. # the compile targets to the matching GN labels.
path = self.args.swarming_targets_file path = self.args.swarming_targets_file
if not self.Exists(path): if not self.Exists(path):
...@@ -782,14 +778,25 @@ class MetaBuildWrapper(object): ...@@ -782,14 +778,25 @@ class MetaBuildWrapper(object):
output_path=None) output_path=None)
contents = self.ReadFile(path) contents = self.ReadFile(path)
swarming_targets = set(contents.splitlines()) swarming_targets = set(contents.splitlines())
gn_isolate_map = ast.literal_eval(self.ReadFile(self.PathJoin(
self.chromium_src_dir, 'testing', 'buildbot', 'gn_isolate_map.pyl')))
gn_labels = []
err = ''
for target in swarming_targets:
target_name = self.GNTargetName(target)
if not target_name in gn_isolate_map:
err += ('test target "%s" not found\n' % target_name)
elif gn_isolate_map[target_name]['type'] == 'unknown':
err += ('test target "%s" type is unknown\n' % target_name)
else:
gn_labels.append(gn_isolate_map[target_name]['label'])
isolate_map = self.ReadIsolateMap()
err, labels = self.MapTargetsToLabels(isolate_map, swarming_targets)
if err: if err:
raise MBErr(err) raise MBErr('Error: Failed to match swarming targets to %s:\n%s' %
('//testing/buildbot/gn_isolate_map.pyl', err))
gn_runtime_deps_path = self.ToAbsPath(build_dir, 'runtime_deps') gn_runtime_deps_path = self.ToAbsPath(build_dir, 'runtime_deps')
self.WriteFile(gn_runtime_deps_path, '\n'.join(labels) + '\n') self.WriteFile(gn_runtime_deps_path, '\n'.join(gn_labels) + '\n')
cmd.append('--runtime-deps-list-file=%s' % gn_runtime_deps_path) cmd.append('--runtime-deps-list-file=%s' % gn_runtime_deps_path)
ret, _, _ = self.Run(cmd) ret, _, _ = self.Run(cmd)
...@@ -805,21 +812,22 @@ class MetaBuildWrapper(object): ...@@ -805,21 +812,22 @@ class MetaBuildWrapper(object):
# Android targets may be either android_apk or executable. The former # Android targets may be either android_apk or executable. The former
# will result in runtime_deps associated with the stamp file, while the # will result in runtime_deps associated with the stamp file, while the
# latter will result in runtime_deps associated with the executable. # latter will result in runtime_deps associated with the executable.
label = isolate_map[target]['label'] target_name = self.GNTargetName(target)
label = gn_isolate_map[target_name]['label']
runtime_deps_targets = [ runtime_deps_targets = [
target + '.runtime_deps', target_name + '.runtime_deps',
'obj/%s.stamp.runtime_deps' % label.replace(':', '/')] 'obj/%s.stamp.runtime_deps' % label.replace(':', '/')]
elif isolate_map[target]['type'] == 'gpu_browser_test': elif gn_isolate_map[target]['type'] == 'gpu_browser_test':
if self.platform == 'win32': if self.platform == 'win32':
runtime_deps_targets = ['browser_tests.exe.runtime_deps'] runtime_deps_targets = ['browser_tests.exe.runtime_deps']
else: else:
runtime_deps_targets = ['browser_tests.runtime_deps'] runtime_deps_targets = ['browser_tests.runtime_deps']
elif (isolate_map[target]['type'] == 'script' or elif (gn_isolate_map[target]['type'] == 'script' or
isolate_map[target].get('label_type') == 'group'): gn_isolate_map[target].get('label_type') == 'group'):
# For script targets, the build target is usually a group, # For script targets, the build target is usually a group,
# for which gn generates the runtime_deps next to the stamp file # for which gn generates the runtime_deps next to the stamp file
# for the label, which lives under the obj/ directory. # for the label, which lives under the obj/ directory.
label = isolate_map[target]['label'] label = gn_isolate_map[target]['label']
runtime_deps_targets = [ runtime_deps_targets = [
'obj/%s.stamp.runtime_deps' % label.replace(':', '/')] 'obj/%s.stamp.runtime_deps' % label.replace(':', '/')]
elif self.platform == 'win32': elif self.platform == 'win32':
...@@ -835,7 +843,8 @@ class MetaBuildWrapper(object): ...@@ -835,7 +843,8 @@ class MetaBuildWrapper(object):
raise MBErr('did not generate any of %s' % raise MBErr('did not generate any of %s' %
', '.join(runtime_deps_targets)) ', '.join(runtime_deps_targets))
command, extra_files = self.GetIsolateCommand(target, vals) command, extra_files = self.GetIsolateCommand(target, vals,
gn_isolate_map)
runtime_deps = self.ReadFile(runtime_deps_path).splitlines() runtime_deps = self.ReadFile(runtime_deps_path).splitlines()
...@@ -845,16 +854,15 @@ class MetaBuildWrapper(object): ...@@ -845,16 +854,15 @@ class MetaBuildWrapper(object):
return 0 return 0
def RunGNIsolate(self, vals): def RunGNIsolate(self, vals):
target = self.args.target[0] gn_isolate_map = ast.literal_eval(self.ReadFile(self.PathJoin(
isolate_map = self.ReadIsolateMap() self.chromium_src_dir, 'testing', 'buildbot', 'gn_isolate_map.pyl')))
err, labels = self.MapTargetsToLabels(isolate_map, [target])
if err:
raise MBErr(err)
label = labels[0]
build_dir = self.args.path[0] build_dir = self.args.path[0]
command, extra_files = self.GetIsolateCommand(target, vals) target = self.args.target[0]
target_name = self.GNTargetName(target)
command, extra_files = self.GetIsolateCommand(target, vals, gn_isolate_map)
label = gn_isolate_map[target_name]['label']
cmd = self.GNCmd('desc', build_dir, label, 'runtime_deps') cmd = self.GNCmd('desc', build_dir, label, 'runtime_deps')
ret, out, _ = self.Call(cmd) ret, out, _ = self.Call(cmd)
if ret: if ret:
...@@ -904,27 +912,6 @@ class MetaBuildWrapper(object): ...@@ -904,27 +912,6 @@ class MetaBuildWrapper(object):
isolate_path + 'd.gen.json', isolate_path + 'd.gen.json',
) )
def MapTargetsToLabels(self, isolate_map, targets):
labels = []
err = ''
for target in targets:
if target == 'all':
labels.append(target)
elif not target in isolate_map:
non_run_target = target[:-4]
if target.endswith('_run') and non_run_target in isolate_map:
labels.append(isolate_map[non_run_target]['label'] + '_run')
elif target.startswith('//'):
labels.append(target)
else:
err += ('target "%s" not found in '
'//testing/buildbot/gn_isolate_map.pyl\n' % target)
elif isolate_map[target]['type'] == 'unknown':
err += ('test target "%s" type is unknown\n' % target)
else:
labels.append(isolate_map[target]['label'])
return err, labels
def GNCmd(self, subcommand, path, *args): def GNCmd(self, subcommand, path, *args):
if self.platform == 'linux2': if self.platform == 'linux2':
subdir, exe = 'linux64', 'gn' subdir, exe = 'linux64', 'gn'
...@@ -934,8 +921,8 @@ class MetaBuildWrapper(object): ...@@ -934,8 +921,8 @@ class MetaBuildWrapper(object):
subdir, exe = 'win', 'gn.exe' subdir, exe = 'win', 'gn.exe'
gn_path = self.PathJoin(self.chromium_src_dir, 'buildtools', subdir, exe) gn_path = self.PathJoin(self.chromium_src_dir, 'buildtools', subdir, exe)
return [gn_path, subcommand, path] + list(args)
return [gn_path, subcommand, path] + list(args)
def GNArgs(self, vals): def GNArgs(self, vals):
if vals['cros_passthrough']: if vals['cros_passthrough']:
...@@ -1001,7 +988,7 @@ class MetaBuildWrapper(object): ...@@ -1001,7 +988,7 @@ class MetaBuildWrapper(object):
return ret return ret
def GetIsolateCommand(self, target, vals): def GetIsolateCommand(self, target, vals, gn_isolate_map):
android = 'target_os="android"' in vals['gn_args'] android = 'target_os="android"' in vals['gn_args']
# This needs to mirror the settings in //build/config/ui.gni: # This needs to mirror the settings in //build/config/ui.gni:
...@@ -1014,19 +1001,15 @@ class MetaBuildWrapper(object): ...@@ -1014,19 +1001,15 @@ class MetaBuildWrapper(object):
msan = 'is_msan=true' in vals['gn_args'] msan = 'is_msan=true' in vals['gn_args']
tsan = 'is_tsan=true' in vals['gn_args'] tsan = 'is_tsan=true' in vals['gn_args']
isolate_map = self.ReadIsolateMap() target_name = self.GNTargetName(target)
test_type = isolate_map[target]['type'] test_type = gn_isolate_map[target_name]['type']
executable = isolate_map[target].get('executable', target) executable = gn_isolate_map[target_name].get('executable', target_name)
executable_suffix = '.exe' if self.platform == 'win32' else '' executable_suffix = '.exe' if self.platform == 'win32' else ''
cmdline = [] cmdline = []
extra_files = [] extra_files = []
if test_type == 'nontest':
self.WriteFailureAndRaise('We should not be isolating %s.' % target,
output_path=None)
if android and test_type != "script": if android and test_type != "script":
logdog_command = [ logdog_command = [
'--logdog-bin-cmd', './../../bin/logdog_butler', '--logdog-bin-cmd', './../../bin/logdog_butler',
...@@ -1038,7 +1021,7 @@ class MetaBuildWrapper(object): ...@@ -1038,7 +1021,7 @@ class MetaBuildWrapper(object):
'--name', 'unified_logcats', '--name', 'unified_logcats',
] ]
test_cmdline = [ test_cmdline = [
self.PathJoin('bin', 'run_%s' % target), self.PathJoin('bin', 'run_%s' % target_name),
'--logcat-output-file', '${ISOLATED_OUTDIR}/logcats', '--logcat-output-file', '${ISOLATED_OUTDIR}/logcats',
'--target-devices-file', '${SWARMING_BOT_FILE}', '--target-devices-file', '${SWARMING_BOT_FILE}',
'-v' '-v'
...@@ -1078,7 +1061,7 @@ class MetaBuildWrapper(object): ...@@ -1078,7 +1061,7 @@ class MetaBuildWrapper(object):
extra_files = [ extra_files = [
'../../testing/test_env.py' '../../testing/test_env.py'
] ]
gtest_filter = isolate_map[target]['gtest_filter'] gtest_filter = gn_isolate_map[target]['gtest_filter']
cmdline = [ cmdline = [
'../../testing/test_env.py', '../../testing/test_env.py',
'./browser_tests' + executable_suffix, './browser_tests' + executable_suffix,
...@@ -1093,7 +1076,7 @@ class MetaBuildWrapper(object): ...@@ -1093,7 +1076,7 @@ class MetaBuildWrapper(object):
] ]
cmdline = [ cmdline = [
'../../testing/test_env.py', '../../testing/test_env.py',
'../../' + self.ToSrcRelPath(isolate_map[target]['script']) '../../' + self.ToSrcRelPath(gn_isolate_map[target]['script'])
] ]
elif test_type in ('raw'): elif test_type in ('raw'):
extra_files = [] extra_files = []
...@@ -1105,7 +1088,7 @@ class MetaBuildWrapper(object): ...@@ -1105,7 +1088,7 @@ class MetaBuildWrapper(object):
self.WriteFailureAndRaise('No command line for %s found (test type %s).' self.WriteFailureAndRaise('No command line for %s found (test type %s).'
% (target, test_type), output_path=None) % (target, test_type), output_path=None)
cmdline += isolate_map[target].get('args', []) cmdline += gn_isolate_map[target_name].get('args', [])
return cmdline, extra_files return cmdline, extra_files
...@@ -1201,18 +1184,12 @@ class MetaBuildWrapper(object): ...@@ -1201,18 +1184,12 @@ class MetaBuildWrapper(object):
return cmd, env return cmd, env
def RunGNAnalyze(self, vals): def RunGNAnalyze(self, vals):
# Analyze runs before 'gn gen' now, so we need to run gn gen # analyze runs before 'gn gen' now, so we need to run gn gen
# in order to ensure that we have a build directory. # in order to ensure that we have a build directory.
ret = self.RunGNGen(vals) ret = self.RunGNGen(vals)
if ret: if ret:
return ret return ret
build_path = self.args.path[0]
input_path = self.args.input_path[0]
gn_input_path = input_path + '.gn'
output_path = self.args.output_path[0]
gn_output_path = output_path + '.gn'
inp = self.ReadInputJSON(['files', 'test_targets', inp = self.ReadInputJSON(['files', 'test_targets',
'additional_compile_targets']) 'additional_compile_targets'])
if self.args.verbose: if self.args.verbose:
...@@ -1221,6 +1198,26 @@ class MetaBuildWrapper(object): ...@@ -1221,6 +1198,26 @@ class MetaBuildWrapper(object):
self.PrintJSON(inp) self.PrintJSON(inp)
self.Print() self.Print()
# TODO(crbug.com/555273) - currently GN treats targets and
# additional_compile_targets identically since we can't tell the
# difference between a target that is a group in GN and one that isn't.
# We should eventually fix this and treat the two types differently.
targets = (set(inp['test_targets']) |
set(inp['additional_compile_targets']))
output_path = self.args.output_path[0]
# Bail out early if a GN file was modified, since 'gn refs' won't know
# what to do about it. Also, bail out early if 'all' was asked for,
# since we can't deal with it yet.
if (any(f.endswith('.gn') or f.endswith('.gni') for f in inp['files']) or
'all' in targets):
self.WriteJSON({
'status': 'Found dependency (all)',
'compile_targets': sorted(targets),
'test_targets': sorted(targets & set(inp['test_targets'])),
}, output_path)
return 0
# This shouldn't normally happen, but could due to unusual race conditions, # This shouldn't normally happen, but could due to unusual race conditions,
# like a try job that gets scheduled before a patch lands but runs after # like a try job that gets scheduled before a patch lands but runs after
...@@ -1234,65 +1231,68 @@ class MetaBuildWrapper(object): ...@@ -1234,65 +1231,68 @@ class MetaBuildWrapper(object):
}, output_path) }, output_path)
return 0 return 0
gn_inp = {} ret = 0
gn_inp['files'] = ['//' + f for f in inp['files'] if not f.startswith('//')] response_file = self.TempFile()
response_file.write('\n'.join(inp['files']) + '\n')
isolate_map = self.ReadIsolateMap() response_file.close()
err, gn_inp['additional_compile_targets'] = self.MapTargetsToLabels(
isolate_map, inp['additional_compile_targets'])
if err:
raise MBErr(err)
err, gn_inp['test_targets'] = self.MapTargetsToLabels(
isolate_map, inp['test_targets'])
if err:
raise MBErr(err)
labels_to_targets = {}
for i, label in enumerate(gn_inp['test_targets']):
labels_to_targets[label] = inp['test_targets'][i]
matching_targets = set()
try: try:
self.WriteJSON(gn_inp, gn_input_path) cmd = self.GNCmd('refs',
cmd = self.GNCmd('analyze', build_path, gn_input_path, gn_output_path) self.args.path[0],
ret, _, _ = self.Run(cmd, force_verbose=True) '@%s' % response_file.name,
if ret: '--all',
return ret '--as=output')
ret, out, _ = self.Run(cmd, force_verbose=False)
gn_outp_str = self.ReadFile(gn_output_path) if ret and not 'The input matches no targets' in out:
try: self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out),
gn_outp = json.loads(gn_outp_str) output_path)
except Exception as e: build_dir = self.ToSrcRelPath(self.args.path[0]) + self.sep
self.Print("Failed to parse the JSON string GN returned: %s\n%s" for output in out.splitlines():
% (repr(gn_outp_str), str(e))) build_output = output.replace(build_dir, '')
raise if build_output in targets:
matching_targets.add(build_output)
cmd = self.GNCmd('refs',
self.args.path[0],
'@%s' % response_file.name,
'--all')
ret, out, _ = self.Run(cmd, force_verbose=False)
if ret and not 'The input matches no targets' in out:
self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out),
output_path)
for label in out.splitlines():
build_target = label[2:]
# We want to accept 'chrome/android:chrome_public_apk' and
# just 'chrome_public_apk'. This may result in too many targets
# getting built, but we can adjust that later if need be.
for input_target in targets:
if (input_target == build_target or
build_target.endswith(':' + input_target)):
matching_targets.add(input_target)
finally:
self.RemoveFile(response_file.name)
outp = {} if matching_targets:
if 'status' in gn_outp: self.WriteJSON({
outp['status'] = gn_outp['status'] 'status': 'Found dependency',
if 'error' in gn_outp: 'compile_targets': sorted(matching_targets),
outp['error'] = gn_outp['error'] 'test_targets': sorted(matching_targets &
if 'invalid_targets' in gn_outp: set(inp['test_targets'])),
outp['invalid_targets'] = gn_outp['invalid_targets'] }, output_path)
if 'compile_targets' in gn_outp: else:
outp['compile_targets'] = [ self.WriteJSON({
label.replace('//', '') for label in gn_outp['compile_targets']] 'status': 'No dependency',
if 'test_targets' in gn_outp: 'compile_targets': [],
outp['test_targets'] = [ 'test_targets': [],
labels_to_targets[label] for label in gn_outp['test_targets']] }, output_path)
if self.args.verbose:
self.Print()
self.Print('analyze output:')
self.PrintJSON(outp)
self.Print()
self.WriteJSON(outp, output_path)
finally: if self.args.verbose:
if self.Exists(gn_input_path): outp = json.loads(self.ReadFile(output_path))
self.RemoveFile(gn_input_path) self.Print()
if self.Exists(gn_output_path): self.Print('analyze output:')
self.RemoveFile(gn_output_path) self.PrintJSON(outp)
self.Print()
return 0 return 0
...@@ -1375,6 +1375,9 @@ class MetaBuildWrapper(object): ...@@ -1375,6 +1375,9 @@ class MetaBuildWrapper(object):
def PrintJSON(self, obj): def PrintJSON(self, obj):
self.Print(json.dumps(obj, indent=2, sort_keys=True)) self.Print(json.dumps(obj, indent=2, sort_keys=True))
def GNTargetName(self, target):
return target
def Build(self, target): def Build(self, target):
build_dir = self.ToSrcRelPath(self.args.path[0]) build_dir = self.ToSrcRelPath(self.args.path[0])
ninja_cmd = ['ninja', '-C', build_dir] ninja_cmd = ['ninja', '-C', build_dir]
......
...@@ -215,15 +215,6 @@ class UnitTest(unittest.TestCase): ...@@ -215,15 +215,6 @@ class UnitTest(unittest.TestCase):
def fake_mbw(self, files=None, win32=False): def fake_mbw(self, files=None, win32=False):
mbw = FakeMBW(win32=win32) mbw = FakeMBW(win32=win32)
mbw.files.setdefault(mbw.default_config, TEST_CONFIG) mbw.files.setdefault(mbw.default_config, TEST_CONFIG)
mbw.files.setdefault(
mbw.ToAbsPath('//testing/buildbot/gn_isolate_map.pyl'),
'''{
"foo_unittests": {
"label": "//foo:foo_unittests",
"type": "console_test_launcher",
"args": [],
},
}''')
mbw.files.setdefault( mbw.files.setdefault(
mbw.ToAbsPath('//build/args/bots/fake_master/fake_gn_args_bot.gn'), mbw.ToAbsPath('//build/args/bots/fake_master/fake_gn_args_bot.gn'),
'is_debug = false\n') 'is_debug = false\n')
...@@ -277,29 +268,78 @@ class UnitTest(unittest.TestCase): ...@@ -277,29 +268,78 @@ class UnitTest(unittest.TestCase):
self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gyp') self.assertEqual(mbw.files['/fake_src/out/Debug/mb_type'], 'gyp')
def test_gn_analyze(self): def test_gn_analyze(self):
files = {'/tmp/in.json': '''{\ files = {'/tmp/in.json': """{\
"files": ["foo/foo_unittest.cc"], "files": ["foo/foo_unittest.cc"],
"test_targets": ["foo_unittests"], "test_targets": ["foo_unittests", "bar_unittests"],
"additional_compile_targets": ["all"] "additional_compile_targets": []
}''', }"""}
'/tmp/out.json.gn': '''{\
"status": "Found dependency",
"compile_targets": ["//foo:foo_unittests"],
"test_targets": ["//foo:foo_unittests"]
}'''}
mbw = self.fake_mbw(files) mbw = self.fake_mbw(files)
mbw.Call = lambda cmd, env=None, buffer_output=True: (0, '', '') mbw.Call = lambda cmd, env=None, buffer_output=True: (
0, 'out/Default/foo_unittests\n', '')
self.check(['analyze', '-c', 'gn_debug_goma', '//out/Default', self.check(['analyze', '-c', 'gn_debug_goma', '//out/Default',
'/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0) '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0)
out = json.loads(mbw.files['/tmp/out.json']) out = json.loads(mbw.files['/tmp/out.json'])
self.assertEqual(out, { self.assertEqual(out, {
'status': 'Found dependency', 'status': 'Found dependency',
'compile_targets': ['foo:foo_unittests'], 'compile_targets': ['foo_unittests'],
'test_targets': ['foo_unittests'] 'test_targets': ['foo_unittests']
}) })
def test_gn_analyze_fails(self):
files = {'/tmp/in.json': """{\
"files": ["foo/foo_unittest.cc"],
"test_targets": ["foo_unittests", "bar_unittests"],
"additional_compile_targets": []
}"""}
mbw = self.fake_mbw(files)
mbw.Call = lambda cmd, env=None, buffer_output=True: (1, '', '')
self.check(['analyze', '-c', 'gn_debug_goma', '//out/Default',
'/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=1)
def test_gn_analyze_all(self):
files = {'/tmp/in.json': """{\
"files": ["foo/foo_unittest.cc"],
"test_targets": ["bar_unittests"],
"additional_compile_targets": ["all"]
}"""}
mbw = self.fake_mbw(files)
mbw.Call = lambda cmd, env=None, buffer_output=True: (
0, 'out/Default/foo_unittests\n', '')
self.check(['analyze', '-c', 'gn_debug_goma', '//out/Default',
'/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0)
out = json.loads(mbw.files['/tmp/out.json'])
self.assertEqual(out, {
'status': 'Found dependency (all)',
'compile_targets': ['all', 'bar_unittests'],
'test_targets': ['bar_unittests'],
})
def test_gn_analyze_missing_file(self):
files = {'/tmp/in.json': """{\
"files": ["foo/foo_unittest.cc"],
"test_targets": ["bar_unittests"],
"additional_compile_targets": []
}"""}
mbw = self.fake_mbw(files)
mbw.cmds = [
(0, '', ''),
(1, 'The input matches no targets, configs, or files\n', ''),
(1, 'The input matches no targets, configs, or files\n', ''),
]
self.check(['analyze', '-c', 'gn_debug_goma', '//out/Default',
'/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0)
out = json.loads(mbw.files['/tmp/out.json'])
self.assertEqual(out, {
'status': 'No dependency',
'compile_targets': [],
'test_targets': [],
})
def test_gn_gen(self): def test_gn_gen(self):
mbw = self.fake_mbw() mbw = self.fake_mbw()
self.check(['gen', '-c', 'gn_debug_goma', '//out/Default', '-g', '/goma'], self.check(['gen', '-c', 'gn_debug_goma', '//out/Default', '-g', '/goma'],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment