nednguyen | 4b719ca | 2018-09-07 08:51:29 -0400 | [diff] [blame] | 1 | #!/usr/bin/env python |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 2 | # Copyright 2018 The Chromium Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | """Generate BUILD.gn to define all data required to run telemetry test. |
| 7 | |
| 8 | If a file/folder of large size is added to catapult but is not needed to run |
| 9 | telemetry test, then it should be added to the EXCLUDED_PATHS below and rerun |
| 10 | this script. |
| 11 | |
| 12 | This script can also run with --check to see if it needs to rerun to update |
| 13 | BUILD.gn. |
| 14 | |
| 15 | This script can also run with --chromium and rewrite the chromium file |
| 16 | //tools/perf/chrome_telemetry_build/BUILD.gn |
| 17 | This is for the purpose of running try jobs in chromium. |
| 18 | |
| 19 | """ |
| 20 | |
| 21 | import difflib |
| 22 | import logging |
| 23 | import os |
| 24 | import optparse |
| 25 | import sys |
nednguyen | febcf87 | 2018-09-07 14:19:11 -0400 | [diff] [blame] | 26 | import subprocess |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 27 | import textwrap |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 28 | |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 29 | LICENSE = textwrap.dedent( |
| 30 | """\ |
| 31 | # Copyright 2018 The Chromium Authors. All rights reserved. |
| 32 | # Use of this source code is governed by a BSD-style license that can be |
| 33 | # found in the LICENSE file. |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 34 | |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 35 | """) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 36 | |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 37 | DO_NOT_EDIT_WARNING = textwrap.dedent( |
| 38 | """\ |
| 39 | # This file is auto-generated from |
| 40 | # //third_party/catapult/generated_telemetry_build.py |
| 41 | # DO NOT EDIT! |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 42 | |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 43 | """) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 44 | |
| 45 | TELEMETRY_SUPPORT_GROUP_NAME = 'telemetry_chrome_test_support' |
| 46 | |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 47 | EXCLUDED_PATHS = { |
| 48 | 'BUILD.gn', |
| 49 | 'TEMP.gn', |
| 50 | 'common/node_runner/', |
| 51 | 'docs/', |
| 52 | 'experimental/', |
| 53 | 'generate_telemetry_build.py', |
Juan Antonio Navarro Pérez | 9b046de | 2019-05-16 09:19:40 +0000 | [diff] [blame] | 54 | 'telemetry/telemetry/bin/', |
| 55 | 'telemetry/telemetry/data/', |
| 56 | 'telemetry/telemetry/internal/bin/', |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 57 | 'third_party/Paste/', |
| 58 | 'third_party/google-endpoints/', |
| 59 | 'third_party/polymer2/', |
| 60 | 'tracing/test_data/', |
| 61 | } |
| 62 | |
| 63 | |
| 64 | SEPARATE_TARGETS = { |
| 65 | 'third_party/vinn': 'third_party/vinn', |
| 66 | } |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 67 | |
nednguyen | febcf87 | 2018-09-07 14:19:11 -0400 | [diff] [blame] | 68 | |
| 69 | def GetUntrackedPaths(): |
| 70 | """Return directories/files in catapult/ that are not tracked by git.""" |
| 71 | output = subprocess.check_output([ |
| 72 | 'git', 'ls-files', '--others', '--exclude-standard', '--directory', |
| 73 | '--full-name']) |
| 74 | paths = output.split('\n') |
| 75 | return [os.path.abspath(p) for p in paths if p] |
| 76 | |
| 77 | |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 78 | def WriteLists(data, data_deps, build_file, path_prefix): |
| 79 | if data: |
| 80 | build_file.write(' data += [\n') |
| 81 | for path in data: |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 82 | if path_prefix: |
| 83 | path = path_prefix + path |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 84 | build_file.write(' "%s",\n' % path) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 85 | build_file.write(' ]\n\n') |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 86 | |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 87 | if data_deps: |
| 88 | build_file.write(' data_deps += [\n') |
| 89 | for data_dep in data_deps: |
| 90 | build_file.write(' "%s",\n' % data_dep) |
| 91 | build_file.write(' ]\n\n') |
| 92 | |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 93 | |
| 94 | def ProcessDir(root_path, path, build_file, path_prefix): |
| 95 | # Write all dirs and files directly under |path| unless they are excluded |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 96 | # or need to be processed further because some of their children are excluded. |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 97 | # Return a list of dirs that needs to processed further. |
| 98 | logging.debug('GenerateList for ' + path) |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 99 | entries = os.listdir(path) |
| 100 | entries.sort() |
| 101 | files = [] |
| 102 | dirs = [] |
| 103 | data_deps = [] |
| 104 | dirs_to_expand = [] |
nednguyen | febcf87 | 2018-09-07 14:19:11 -0400 | [diff] [blame] | 105 | untracked_paths = GetUntrackedPaths() |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 106 | for entry in entries: |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 107 | full_path = os.path.join(path, entry) |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 108 | rel_path = os.path.relpath(full_path, root_path).replace('\\', '/') |
nednguyen | febcf87 | 2018-09-07 14:19:11 -0400 | [diff] [blame] | 109 | if (any(full_path.startswith(p) for p in untracked_paths) or |
| 110 | entry.startswith('.') or entry.endswith('~') or |
Zhenyao Mo | 074cebc | 2018-08-27 11:31:05 -0700 | [diff] [blame] | 111 | entry.endswith('.pyc') or entry.endswith('#')): |
nednguyen | febcf87 | 2018-09-07 14:19:11 -0400 | [diff] [blame] | 112 | logging.debug('ignored %s', rel_path) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 113 | continue |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 114 | if rel_path in SEPARATE_TARGETS: |
| 115 | data_deps.append(SEPARATE_TARGETS[rel_path]) |
| 116 | elif os.path.isfile(full_path): |
| 117 | if rel_path in EXCLUDED_PATHS: |
nednguyen | febcf87 | 2018-09-07 14:19:11 -0400 | [diff] [blame] | 118 | logging.debug('excluded %s', rel_path) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 119 | else: |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 120 | files.append(rel_path) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 121 | elif os.path.isdir(full_path): |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 122 | rel_path = rel_path + '/' |
| 123 | if rel_path in EXCLUDED_PATHS: |
nednguyen | febcf87 | 2018-09-07 14:19:11 -0400 | [diff] [blame] | 124 | logging.debug('excluded %s', rel_path) |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 125 | elif any(e.startswith(rel_path) for e in EXCLUDED_PATHS): |
| 126 | dirs_to_expand.append(full_path) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 127 | else: |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 128 | dirs.append(rel_path) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 129 | else: |
| 130 | assert False |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 131 | WriteLists(files + dirs, |
| 132 | data_deps, |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 133 | build_file, path_prefix) |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 134 | return dirs_to_expand |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 135 | |
| 136 | def WriteBuildFileHeader(build_file): |
| 137 | build_file.write(LICENSE) |
| 138 | build_file.write(DO_NOT_EDIT_WARNING) |
| 139 | build_file.write('import("//build/config/compiler/compiler.gni")\n\n') |
| 140 | |
| 141 | def WriteBuildFileBody(build_file, root_path, path_prefix): |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 142 | build_file.write(textwrap.dedent( |
| 143 | """\ |
| 144 | group("%s") { |
| 145 | testonly = true |
| 146 | data = [] |
| 147 | data_deps = [] |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 148 | |
John Budorick | a9c4beb | 2019-04-24 10:45:35 -0700 | [diff] [blame] | 149 | """ % TELEMETRY_SUPPORT_GROUP_NAME)) |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 150 | |
| 151 | candidates = [root_path] |
| 152 | while len(candidates) > 0: |
| 153 | candidate = candidates.pop(0) |
| 154 | more = ProcessDir(root_path, candidate, build_file, path_prefix) |
| 155 | candidates.extend(more) |
| 156 | |
| 157 | build_file.write("}") |
| 158 | |
| 159 | def GenerateBuildFile(root_path, output_path, chromium): |
| 160 | CHROMIUM_GROUP = 'group("telemetry_chrome_test_without_chrome")' |
| 161 | CATAPULT_PREFIX = '//third_party/catapult' |
| 162 | CATAPULT_GROUP_NAME = CATAPULT_PREFIX + ':' + TELEMETRY_SUPPORT_GROUP_NAME |
| 163 | TELEMETRY_SUPPORT_GROUP = 'group("%s")' % TELEMETRY_SUPPORT_GROUP_NAME |
| 164 | if chromium: |
| 165 | build_file = open(output_path, 'r+') |
| 166 | contents = build_file.readlines() |
| 167 | build_file.seek(0) |
| 168 | remove_telemetry_support_group = False |
| 169 | for line in contents: |
| 170 | if TELEMETRY_SUPPORT_GROUP in line: |
| 171 | # --chromium has already run once, so remove the previously inserted |
| 172 | # TELEMETRY_SUPPORT_GROUP so we could add an updated one. |
| 173 | remove_telemetry_support_group = True |
| 174 | continue |
| 175 | if remove_telemetry_support_group: |
| 176 | if line == '}\n': |
| 177 | remove_telemetry_support_group = False |
| 178 | continue |
| 179 | if CHROMIUM_GROUP in line: |
| 180 | WriteBuildFileBody(build_file, root_path, CATAPULT_PREFIX + '/') |
| 181 | build_file.write('\n') |
| 182 | elif CATAPULT_GROUP_NAME in line: |
| 183 | line = line.replace(CATAPULT_GROUP_NAME, |
| 184 | ':' + TELEMETRY_SUPPORT_GROUP_NAME) |
| 185 | build_file.write(line) |
| 186 | build_file.close() |
| 187 | else: |
| 188 | build_file = open(output_path, 'w') |
| 189 | WriteBuildFileHeader(build_file) |
| 190 | WriteBuildFileBody(build_file, root_path, None) |
| 191 | build_file.close() |
| 192 | |
| 193 | def CheckForChanges(): |
Zhenyao Mo | 074cebc | 2018-08-27 11:31:05 -0700 | [diff] [blame] | 194 | # Return 0 if no changes are detected; return 1 otherwise. |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 195 | root_path = os.path.dirname(os.path.realpath(__file__)) |
| 196 | temp_path = os.path.join(root_path, "TEMP.gn") |
| 197 | GenerateBuildFile(root_path, temp_path, chromium=False) |
| 198 | |
| 199 | ref_path = os.path.join(root_path, "BUILD.gn") |
| 200 | if not os.path.exists(ref_path): |
| 201 | logging.error("Can't localte BUILD.gn!") |
Zhenyao Mo | 074cebc | 2018-08-27 11:31:05 -0700 | [diff] [blame] | 202 | return 1 |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 203 | |
| 204 | temp_file = open(temp_path, 'r') |
| 205 | temp_content = temp_file.readlines() |
| 206 | temp_file.close() |
| 207 | os.remove(temp_path) |
| 208 | ref_file = open(ref_path, 'r') |
| 209 | ref_content = ref_file.readlines() |
| 210 | ref_file.close() |
| 211 | |
| 212 | diff = difflib.unified_diff(temp_content, ref_content, fromfile=temp_path, |
| 213 | tofile=ref_path, lineterm='') |
| 214 | diff_data = [] |
| 215 | for line in diff: |
| 216 | diff_data.append(line) |
| 217 | if len(diff_data) > 0: |
| 218 | logging.error('Diff found. Please rerun generate_telemetry_build.py.') |
| 219 | logging.debug('\n' + ''.join(diff_data)) |
Zhenyao Mo | 074cebc | 2018-08-27 11:31:05 -0700 | [diff] [blame] | 220 | return 1 |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 221 | logging.debug('No diff found. Everything is good.') |
Zhenyao Mo | 074cebc | 2018-08-27 11:31:05 -0700 | [diff] [blame] | 222 | return 0 |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 223 | |
| 224 | |
| 225 | def main(argv): |
| 226 | parser = optparse.OptionParser() |
| 227 | parser.add_option("-v", "--verbose", action="store_true", default=False, |
| 228 | help="print out debug information") |
| 229 | parser.add_option("-c", "--check", action="store_true", default=False, |
| 230 | help="generate a temporary build file and compare if it " |
| 231 | "is the same as the current BUILD.gn") |
| 232 | parser.add_option("--chromium", action="store_true", default=False, |
| 233 | help="generate the build file into chromium workspace. " |
| 234 | "This is for the purpose of running try jobs in Chrome.") |
| 235 | (options, _) = parser.parse_args(args=argv) |
| 236 | if options.verbose: |
| 237 | logging.basicConfig(level=logging.DEBUG) |
| 238 | |
| 239 | if options.check: |
Zhenyao Mo | 074cebc | 2018-08-27 11:31:05 -0700 | [diff] [blame] | 240 | return CheckForChanges() |
| 241 | if options.chromium: |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 242 | root_path = os.path.dirname(os.path.realpath(__file__)) |
| 243 | output_path = os.path.join( |
| 244 | root_path, "../../tools/perf/chrome_telemetry_build/BUILD.gn") |
| 245 | GenerateBuildFile(root_path, output_path, chromium=True) |
| 246 | else: |
| 247 | root_path = os.path.dirname(os.path.realpath(__file__)) |
| 248 | output_path = os.path.join(root_path, "BUILD.gn") |
| 249 | GenerateBuildFile(root_path, output_path, chromium=False) |
Zhenyao Mo | 074cebc | 2018-08-27 11:31:05 -0700 | [diff] [blame] | 250 | return 0 |
Zhenyao Mo | 72712b0 | 2018-08-23 15:55:12 -0700 | [diff] [blame] | 251 | |
| 252 | if __name__ == '__main__': |
| 253 | sys.exit(main(sys.argv[1:])) |