blob: fe38e8fb1ccb82cbd445edee62c31e68cb54d634 [file] [log] [blame]
nednguyen4b719ca2018-09-07 08:51:29 -04001#!/usr/bin/env python
Zhenyao Mo72712b02018-08-23 15:55:12 -07002# 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
8If a file/folder of large size is added to catapult but is not needed to run
9telemetry test, then it should be added to the EXCLUDED_PATHS below and rerun
10this script.
11
12This script can also run with --check to see if it needs to rerun to update
13BUILD.gn.
14
15This script can also run with --chromium and rewrite the chromium file
16 //tools/perf/chrome_telemetry_build/BUILD.gn
17This is for the purpose of running try jobs in chromium.
18
19"""
20
21import difflib
22import logging
23import os
24import optparse
25import sys
nednguyenfebcf872018-09-07 14:19:11 -040026import subprocess
John Budoricka9c4beb2019-04-24 10:45:35 -070027import textwrap
Zhenyao Mo72712b02018-08-23 15:55:12 -070028
John Budoricka9c4beb2019-04-24 10:45:35 -070029LICENSE = 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 Mo72712b02018-08-23 15:55:12 -070034
John Budoricka9c4beb2019-04-24 10:45:35 -070035 """)
Zhenyao Mo72712b02018-08-23 15:55:12 -070036
John Budoricka9c4beb2019-04-24 10:45:35 -070037DO_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 Mo72712b02018-08-23 15:55:12 -070042
John Budoricka9c4beb2019-04-24 10:45:35 -070043 """)
Zhenyao Mo72712b02018-08-23 15:55:12 -070044
45TELEMETRY_SUPPORT_GROUP_NAME = 'telemetry_chrome_test_support'
46
John Budoricka9c4beb2019-04-24 10:45:35 -070047EXCLUDED_PATHS = {
48 'BUILD.gn',
49 'TEMP.gn',
50 'common/node_runner/',
51 'docs/',
52 'experimental/',
53 'generate_telemetry_build.py',
Juan Antonio Navarro Pérez9b046de2019-05-16 09:19:40 +000054 'telemetry/telemetry/bin/',
55 'telemetry/telemetry/data/',
56 'telemetry/telemetry/internal/bin/',
John Budoricka9c4beb2019-04-24 10:45:35 -070057 'third_party/Paste/',
58 'third_party/google-endpoints/',
59 'third_party/polymer2/',
60 'tracing/test_data/',
61}
62
63
64SEPARATE_TARGETS = {
65 'third_party/vinn': 'third_party/vinn',
66}
Zhenyao Mo72712b02018-08-23 15:55:12 -070067
nednguyenfebcf872018-09-07 14:19:11 -040068
69def 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 Budoricka9c4beb2019-04-24 10:45:35 -070078def WriteLists(data, data_deps, build_file, path_prefix):
79 if data:
80 build_file.write(' data += [\n')
81 for path in data:
Zhenyao Mo72712b02018-08-23 15:55:12 -070082 if path_prefix:
83 path = path_prefix + path
Zhenyao Mo72712b02018-08-23 15:55:12 -070084 build_file.write(' "%s",\n' % path)
Zhenyao Mo72712b02018-08-23 15:55:12 -070085 build_file.write(' ]\n\n')
Zhenyao Mo72712b02018-08-23 15:55:12 -070086
John Budoricka9c4beb2019-04-24 10:45:35 -070087 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 Mo72712b02018-08-23 15:55:12 -070093
94def ProcessDir(root_path, path, build_file, path_prefix):
95 # Write all dirs and files directly under |path| unless they are excluded
John Budoricka9c4beb2019-04-24 10:45:35 -070096 # or need to be processed further because some of their children are excluded.
Zhenyao Mo72712b02018-08-23 15:55:12 -070097 # Return a list of dirs that needs to processed further.
98 logging.debug('GenerateList for ' + path)
John Budoricka9c4beb2019-04-24 10:45:35 -070099 entries = os.listdir(path)
100 entries.sort()
101 files = []
102 dirs = []
103 data_deps = []
104 dirs_to_expand = []
nednguyenfebcf872018-09-07 14:19:11 -0400105 untracked_paths = GetUntrackedPaths()
John Budoricka9c4beb2019-04-24 10:45:35 -0700106 for entry in entries:
Zhenyao Mo72712b02018-08-23 15:55:12 -0700107 full_path = os.path.join(path, entry)
John Budoricka9c4beb2019-04-24 10:45:35 -0700108 rel_path = os.path.relpath(full_path, root_path).replace('\\', '/')
nednguyenfebcf872018-09-07 14:19:11 -0400109 if (any(full_path.startswith(p) for p in untracked_paths) or
110 entry.startswith('.') or entry.endswith('~') or
Zhenyao Mo074cebc2018-08-27 11:31:05 -0700111 entry.endswith('.pyc') or entry.endswith('#')):
nednguyenfebcf872018-09-07 14:19:11 -0400112 logging.debug('ignored %s', rel_path)
Zhenyao Mo72712b02018-08-23 15:55:12 -0700113 continue
John Budoricka9c4beb2019-04-24 10:45:35 -0700114 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:
nednguyenfebcf872018-09-07 14:19:11 -0400118 logging.debug('excluded %s', rel_path)
Zhenyao Mo72712b02018-08-23 15:55:12 -0700119 else:
John Budoricka9c4beb2019-04-24 10:45:35 -0700120 files.append(rel_path)
Zhenyao Mo72712b02018-08-23 15:55:12 -0700121 elif os.path.isdir(full_path):
John Budoricka9c4beb2019-04-24 10:45:35 -0700122 rel_path = rel_path + '/'
123 if rel_path in EXCLUDED_PATHS:
nednguyenfebcf872018-09-07 14:19:11 -0400124 logging.debug('excluded %s', rel_path)
John Budoricka9c4beb2019-04-24 10:45:35 -0700125 elif any(e.startswith(rel_path) for e in EXCLUDED_PATHS):
126 dirs_to_expand.append(full_path)
Zhenyao Mo72712b02018-08-23 15:55:12 -0700127 else:
John Budoricka9c4beb2019-04-24 10:45:35 -0700128 dirs.append(rel_path)
Zhenyao Mo72712b02018-08-23 15:55:12 -0700129 else:
130 assert False
John Budoricka9c4beb2019-04-24 10:45:35 -0700131 WriteLists(files + dirs,
132 data_deps,
Zhenyao Mo72712b02018-08-23 15:55:12 -0700133 build_file, path_prefix)
John Budoricka9c4beb2019-04-24 10:45:35 -0700134 return dirs_to_expand
Zhenyao Mo72712b02018-08-23 15:55:12 -0700135
136def 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
141def WriteBuildFileBody(build_file, root_path, path_prefix):
John Budoricka9c4beb2019-04-24 10:45:35 -0700142 build_file.write(textwrap.dedent(
143 """\
144 group("%s") {
145 testonly = true
146 data = []
147 data_deps = []
Zhenyao Mo72712b02018-08-23 15:55:12 -0700148
John Budoricka9c4beb2019-04-24 10:45:35 -0700149 """ % TELEMETRY_SUPPORT_GROUP_NAME))
Zhenyao Mo72712b02018-08-23 15:55:12 -0700150
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
159def 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
193def CheckForChanges():
Zhenyao Mo074cebc2018-08-27 11:31:05 -0700194 # Return 0 if no changes are detected; return 1 otherwise.
Zhenyao Mo72712b02018-08-23 15:55:12 -0700195 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 Mo074cebc2018-08-27 11:31:05 -0700202 return 1
Zhenyao Mo72712b02018-08-23 15:55:12 -0700203
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 Mo074cebc2018-08-27 11:31:05 -0700220 return 1
Zhenyao Mo72712b02018-08-23 15:55:12 -0700221 logging.debug('No diff found. Everything is good.')
Zhenyao Mo074cebc2018-08-27 11:31:05 -0700222 return 0
Zhenyao Mo72712b02018-08-23 15:55:12 -0700223
224
225def 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 Mo074cebc2018-08-27 11:31:05 -0700240 return CheckForChanges()
241 if options.chromium:
Zhenyao Mo72712b02018-08-23 15:55:12 -0700242 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 Mo074cebc2018-08-27 11:31:05 -0700250 return 0
Zhenyao Mo72712b02018-08-23 15:55:12 -0700251
252if __name__ == '__main__':
253 sys.exit(main(sys.argv[1:]))