blob: 1674c0fd6b1f6a7814189f23b612ca79527a83f7 [file] [log] [blame]
Lalit Maganti279ecde2019-04-01 16:57:12 +01001#!/usr/bin/env python
2# Copyright (C) 2018 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16# This tool translates a collection of BUILD.gn files into a mostly equivalent
17# BUILD file for the Bazel build system. The input to the tool is a
18# JSON description of the GN build definition generated with the following
19# command:
20#
21# gn desc out --format=json --all-toolchains "//*" > desc.json
22#
23# The tool is then given a list of GN labels for which to generate Bazel
24# build rules.
25
26from __future__ import print_function
27import argparse
Lalit Maganti279ecde2019-04-01 16:57:12 +010028import json
29import os
30import re
Lalit Maganti279ecde2019-04-01 16:57:12 +010031import sys
Lalit Maganti279ecde2019-04-01 16:57:12 +010032
Sami Kyostila3c88a1d2019-05-22 18:29:42 +010033import gn_utils
34
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +010035from compat import itervalues, iteritems, basestring
36
Primiano Tucci1d409982019-09-19 10:15:18 +010037# Arguments for the GN output directory.
38# host_os="linux" is to generate the right build files from Mac OS.
39gn_args = ' '.join([
40 'host_os="linux"',
41 'is_debug=false',
42 'is_perfetto_build_generator=true',
43 'enable_perfetto_watchdog=true',
44 'monolithic_binaries=true',
45 'target_os="linux"',
46])
47
48# Default targets to translate to the blueprint file.
49
50# These targets will be exported with public visibility in the generated BUILD.
51public_targets = [
Pascal Muetschardb4966c52019-09-24 13:38:09 -070052 '//:libperfetto_client_experimental',
Primiano Tucci1d409982019-09-19 10:15:18 +010053 '//src/perfetto_cmd:perfetto',
54 '//src/traced/probes:traced_probes',
55 '//src/traced/service:traced',
56 '//src/trace_processor:trace_processor_shell',
57 '//src/trace_processor:trace_processor',
Lalit Maganti65600342019-09-19 21:35:35 +010058 '//tools/trace_to_text:trace_to_text',
Primiano Tucci1d409982019-09-19 10:15:18 +010059 '//tools/trace_to_text:libpprofbuilder',
60]
61
62# These targets are required by internal build rules but don't need to be
63# exported publicly.
64default_targets = [
Lalit Maganti01deefa2019-12-19 14:20:12 +000065 '//test:client_api_example',
Primiano Tucci1d409982019-09-19 10:15:18 +010066 '//src/ipc:perfetto_ipc',
67 '//src/ipc/protoc_plugin:ipc_plugin',
Primiano Tucci916f4e52020-10-16 20:40:33 +020068 '//src/protozero:protozero',
Primiano Tucci1d409982019-09-19 10:15:18 +010069 '//src/protozero/protoc_plugin:protozero_plugin',
Primiano Tucci57dd66b2019-10-15 23:09:04 +010070 '//src/protozero/protoc_plugin:cppgen_plugin',
Primiano Tucci1d409982019-09-19 10:15:18 +010071] + public_targets
72
73# Root proto targets (to force discovery of intermediate proto targets).
Pascal Muetschardb7cdea02019-09-23 15:25:20 -070074# These targets are marked public.
Primiano Tucci1d409982019-09-19 10:15:18 +010075proto_targets = [
Lalit Magantic3187f82019-09-20 14:51:11 +010076 '//protos/perfetto/trace:merged_trace',
Lalit Magantid78606d2019-11-21 17:45:55 +000077 '//protos/perfetto/trace:non_minimal_lite',
Pascal Muetschardb7cdea02019-09-23 15:25:20 -070078 '//protos/perfetto/config:merged_config',
Primiano Tucci1d409982019-09-19 10:15:18 +010079 '//protos/perfetto/metrics:lite',
Lalit Maganti613f97b2019-11-21 14:44:18 +000080 '//protos/perfetto/metrics/android:lite',
Primiano Tucci1d409982019-09-19 10:15:18 +010081 '//protos/perfetto/trace:lite',
82 '//protos/perfetto/config:lite',
83]
84
Lalit Maganti3b09a3f2020-09-14 13:28:44 +010085# Path for the protobuf sources in the standalone build.
86buildtools_protobuf_src = '//buildtools/protobuf/src'
87
Primiano Tucci1d409982019-09-19 10:15:18 +010088# The directory where the generated perfetto_build_flags.h will be copied into.
89buildflags_dir = 'include/perfetto/base/build_configs/bazel'
90
91# Internal equivalents for third-party libraries that the upstream project
92# depends on.
93external_deps = {
94 '//gn:default_deps': [],
95 '//gn:jsoncpp': ['PERFETTO_CONFIG.deps.jsoncpp'],
96 '//gn:linenoise': ['PERFETTO_CONFIG.deps.linenoise'],
97 '//gn:protobuf_full': ['PERFETTO_CONFIG.deps.protobuf_full'],
98 '//gn:protobuf_lite': ['PERFETTO_CONFIG.deps.protobuf_lite'],
99 '//gn:protoc_lib': ['PERFETTO_CONFIG.deps.protoc_lib'],
100 '//gn:protoc': ['PERFETTO_CONFIG.deps.protoc'],
101 '//gn:sqlite': [
102 'PERFETTO_CONFIG.deps.sqlite',
103 'PERFETTO_CONFIG.deps.sqlite_ext_percentile'
104 ],
105 '//gn:zlib': ['PERFETTO_CONFIG.deps.zlib'],
Matthew Clarkson63028d62019-10-10 15:48:23 +0100106 '//src/trace_processor/metrics:gen_merged_sql_metrics': [[
Lalit Maganti117272f2020-09-11 14:01:18 +0100107 ':cc_merged_sql_metrics'
Primiano Tucciec590132020-11-16 14:16:44 +0100108 ]],
109 gn_utils.GEN_VERSION_TARGET: ['PERFETTO_CONFIG.deps.version_header'],
Primiano Tucci1d409982019-09-19 10:15:18 +0100110}
111
112
113def gen_sql_metrics(target):
114 label = BazelLabel(get_bazel_label_name(target.name), 'genrule')
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100115 label.srcs += [re.sub('^//', '', x) for x in sorted(target.inputs)]
Primiano Tucci1d409982019-09-19 10:15:18 +0100116 label.outs += target.outputs
117 label.cmd = r'$(location gen_merged_sql_metrics_py) --cpp_out=$@ $(SRCS)'
Lalit Maganti9d9e56b2020-08-13 17:38:15 +0100118 label.exec_tools += [':gen_merged_sql_metrics_py']
Primiano Tucci1d409982019-09-19 10:15:18 +0100119 return [label]
120
121
Primiano Tucciec590132020-11-16 14:16:44 +0100122def gen_version_header(target):
123 label = BazelLabel(get_bazel_label_name(target.name), 'genrule')
124 label.srcs += [re.sub('^//', '', x) for x in sorted(target.inputs)]
125 label.outs += target.outputs
Primiano Tuccif0ed1d42020-11-18 16:30:18 +0100126 label.cmd = r'$(location gen_version_header_py)'
Joshua Gilpatrick042931b2020-12-04 08:55:59 -0800127 label.cmd += r' --cpp_out=$@ --changelog=$(location CHANGELOG)'
Primiano Tucciec590132020-11-16 14:16:44 +0100128 label.exec_tools += [':gen_version_header_py']
129 return [label]
130
131
Lalit Maganti117272f2020-09-11 14:01:18 +0100132def gen_cc_metrics_descriptor(target):
133 label = BazelLabel(
134 get_bazel_label_name(target.name), 'perfetto_cc_proto_descriptor')
135 label.deps += [':' + get_bazel_label_name(x) for x in target.proto_deps]
136 label.outs += target.outputs
137 return [label]
138
139
Primiano Tucci1d409982019-09-19 10:15:18 +0100140custom_actions = {
Primiano Tucciec590132020-11-16 14:16:44 +0100141 gn_utils.GEN_VERSION_TARGET: gen_version_header,
Primiano Tucci1d409982019-09-19 10:15:18 +0100142 '//src/trace_processor/metrics:gen_merged_sql_metrics': gen_sql_metrics,
Lalit Maganti117272f2020-09-11 14:01:18 +0100143 '//src/trace_processor/metrics:gen_cc_metrics_descriptor':
144 gen_cc_metrics_descriptor,
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100145 '//src/trace_processor/metrics:gen_cc_all_chrome_metrics_descriptor':
146 gen_cc_metrics_descriptor,
Hector Dearmana1d75242020-10-02 09:47:24 +0100147 '//src/trace_processor/importers:gen_cc_config_descriptor':
148 gen_cc_metrics_descriptor,
Andrew Shulaevba0a5d12021-01-07 08:44:50 +0000149 '//src/trace_processor/importers:gen_cc_chrome_track_event_descriptor':
150 gen_cc_metrics_descriptor,
Andrew Shulaeve72d1a32021-01-13 12:59:55 +0000151 '//src/trace_processor/importers:gen_cc_track_event_descriptor':
152 gen_cc_metrics_descriptor,
Primiano Tucci1d409982019-09-19 10:15:18 +0100153}
154
155# ------------------------------------------------------------------------------
156# End of configuration.
157# ------------------------------------------------------------------------------
158
159
160class Error(Exception):
161 pass
162
163
164class BazelLabel(object):
165
166 def __init__(self, name, type):
167 self.comment = None
168 self.name = name
169 self.type = type
170 self.visibility = []
171 self.srcs = []
172 self.hdrs = []
173 self.deps = []
174 self.external_deps = []
175 self.tools = []
Lalit Maganti9d9e56b2020-08-13 17:38:15 +0100176 self.exec_tools = []
Primiano Tucci1d409982019-09-19 10:15:18 +0100177 self.outs = []
178
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100179 def __lt__(self, other):
180 if isinstance(other, self.__class__):
181 return self.name < other.name
Primiano Tucci57dd66b2019-10-15 23:09:04 +0100182 raise TypeError('\'<\' not supported between instances of \'%s\' and \'%s\''
183 % (type(self).__name__, type(other).__name__))
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100184
Primiano Tucci1d409982019-09-19 10:15:18 +0100185 def __str__(self):
186 """Converts the object into a Bazel Starlark label."""
187 res = ''
188 res += ('# GN target: %s\n' % self.comment) if self.comment else ''
189 res += '%s(\n' % self.type
190 any_deps = len(self.deps) + len(self.external_deps) > 0
Lalit Maganti9d9e56b2020-08-13 17:38:15 +0100191 ORD = [
192 'name','srcs', 'hdrs', 'visibility', 'deps', 'outs', 'cmd', 'tools',
193 'exec_tools'
194 ]
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100195 hasher = lambda x: sum((99,) + tuple(ord(c) for c in x))
196 key_sorter = lambda kv: ORD.index(kv[0]) if kv[0] in ORD else hasher(kv[0])
197 for k, v in sorted(iteritems(self.__dict__), key=key_sorter):
Primiano Tucci1d409982019-09-19 10:15:18 +0100198 if k in ('type', 'comment',
199 'external_deps') or v is None or (v == [] and
200 (k != 'deps' or not any_deps)):
201 continue
202 res += ' %s = ' % k
203 if isinstance(v, basestring):
Lalit Magantie5aad3b2020-01-20 18:43:05 +0000204 if v.startswith('PERFETTO_CONFIG.'):
205 res += '%s,\n' % v
206 else:
207 res += '"%s",\n' % v
Lalit Magantif9c004d2020-01-06 14:44:34 +0000208 elif isinstance(v, bool):
209 res += '%s,\n' % v
Primiano Tucci1d409982019-09-19 10:15:18 +0100210 elif isinstance(v, list):
211 res += '[\n'
Lalit Maganti65600342019-09-19 21:35:35 +0100212 if k == 'deps' and len(self.external_deps) > 1:
213 indent = ' '
214 else:
215 indent = ' '
Primiano Tucci1d409982019-09-19 10:15:18 +0100216 for entry in v:
Primiano Tuccie88d9392019-11-19 17:42:41 +0000217 if entry.startswith('PERFETTO_CONFIG.'):
218 res += '%s %s,\n' % (indent, entry)
219 else:
220 res += '%s "%s",\n' % (indent, entry)
Lalit Maganti65600342019-09-19 21:35:35 +0100221 res += '%s]' % indent
222 if k == 'deps' and self.external_deps:
223 res += ' + %s' % self.external_deps[0]
224 for edep in self.external_deps[1:]:
225 if isinstance(edep, list):
226 res += ' + [\n'
227 for inner_dep in edep:
Lalit Magantia4244e42019-09-20 12:03:32 +0100228 res += ' "%s",\n' % inner_dep
Lalit Maganti65600342019-09-19 21:35:35 +0100229 res += ' ]'
230 else:
231 res += ' +\n%s%s' % (indent, edep)
Primiano Tucci1d409982019-09-19 10:15:18 +0100232 res += ',\n'
233 else:
234 raise Error('Unsupported value %s', type(v))
235 res += ')\n\n'
236 return res
237
238
Lalit Maganti613f97b2019-11-21 14:44:18 +0000239# Public visibility for targets in Bazel.
Lalit Magantie5aad3b2020-01-20 18:43:05 +0000240PUBLIC_VISIBILITY = 'PERFETTO_CONFIG.public_visibility'
Lalit Maganti613f97b2019-11-21 14:44:18 +0000241
242
Primiano Tucci1d409982019-09-19 10:15:18 +0100243def get_bazel_label_name(gn_name):
244 """Converts a GN target name into a Bazel label name.
245
Primiano Tucci66b08c32020-07-23 12:37:48 +0200246 If target is in the public target list, returns only the GN target name,
Primiano Tucci1d409982019-09-19 10:15:18 +0100247 e.g.: //src/ipc:perfetto_ipc -> perfetto_ipc
248
Primiano Tucci66b08c32020-07-23 12:37:48 +0200249 Otherwise, in the case of an intermediate target, returns a mangled path.
Primiano Tucci1d409982019-09-19 10:15:18 +0100250 e.g.: //include/perfetto/base:base -> include_perfetto_base_base.
251 """
252 if gn_name in default_targets:
253 return gn_utils.label_without_toolchain(gn_name).split(':')[1]
254 return gn_utils.label_to_target_name_with_path(gn_name)
255
256
257def gen_proto_labels(target):
258 """ Generates the xx_proto_library label for proto targets.
259
260 Bazel requires that each protobuf-related target is modeled with two labels:
Lalit Maganti117272f2020-09-11 14:01:18 +0100261 1. A plugin-agnostic target that defines only the .proto sources and their
Primiano Tucci1d409982019-09-19 10:15:18 +0100262 dependencies.
Lalit Maganti117272f2020-09-11 14:01:18 +0100263 2. A plugin-dependent target (e.g. cc_library, cc_protozero_library) that has
264 only a dependency on 1 and does NOT refer to any .proto sources.
Primiano Tucci1d409982019-09-19 10:15:18 +0100265 """
266 assert (target.type == 'proto_library')
267
268 def get_sources_label(target_name):
Lalit Maganti64cd1f62020-09-14 17:44:52 +0100269 return re.sub('_(lite|zero|cpp|ipc|source_set|descriptor)$', '',
Primiano Tucci1d409982019-09-19 10:15:18 +0100270 get_bazel_label_name(target_name)) + '_protos'
271
272 sources_label_name = get_sources_label(target.name)
273
274 # Generates 1.
Primiano Tucci1d409982019-09-19 10:15:18 +0100275 sources_label = BazelLabel(sources_label_name, 'perfetto_proto_library')
276 sources_label.comment = target.name
277 assert (all(x.startswith('//') for x in target.sources))
278 assert (all(x.endswith('.proto') for x in target.sources))
279 sources_label.srcs = sorted([x[2:] for x in target.sources]) # Strip //.
Primiano Tuccif0d63af2019-11-19 17:07:37 +0000280
Primiano Tuccif0d63af2019-11-19 17:07:37 +0000281 deps = [
282 ':' + get_sources_label(x)
283 for x in target.proto_deps
Primiano Tuccie8020f92019-11-26 13:24:01 +0000284
285 # This is to avoid a dependency-on-self in the case where
286 # protos/perfetto/ipc:ipc depends on protos/perfetto/ipc:cpp and both
287 # targets resolve to "protos_perfetto_ipc_protos".
288 if get_sources_label(x) != sources_label_name
Primiano Tuccif0d63af2019-11-19 17:07:37 +0000289 ]
Primiano Tucci1d409982019-09-19 10:15:18 +0100290 sources_label.deps = sorted(deps)
291
Lalit Maganti3b09a3f2020-09-14 13:28:44 +0100292 # In Bazel, proto_paths are not a supported concept becauase strong dependency
293 # checking is enabled. Instead, we need to depend on the target which includes
294 # the proto we want to depend on.
295 # For example, we include the proto_path |buildtools_protobuf_src| because we
296 # want to depend on the "google/protobuf/descriptor.proto" proto file. This
297 # will be exposed by the |protobuf_descriptor_proto| dep.
298 if buildtools_protobuf_src in target.proto_paths:
299 sources_label.external_deps = [
300 'PERFETTO_CONFIG.deps.protobuf_descriptor_proto'
301 ]
302
Pascal Muetschardb7cdea02019-09-23 15:25:20 -0700303 if target.name in proto_targets:
Lalit Maganti613f97b2019-11-21 14:44:18 +0000304 sources_label.visibility = PUBLIC_VISIBILITY
Primiano Tuccie88d9392019-11-19 17:42:41 +0000305 else:
306 sources_label.visibility = ['PERFETTO_CONFIG.proto_library_visibility']
Pascal Muetschardb7cdea02019-09-23 15:25:20 -0700307
Lalit Maganti117272f2020-09-11 14:01:18 +0100308 # For 'source_set' plugins, we don't want to generate any plugin-dependent
309 # targets so just return the label of the proto sources only.
310 if target.proto_plugin == 'source_set':
311 return [sources_label]
312
313 # Generates 2.
314 if target.proto_plugin == 'proto':
315 plugin_label_type = 'perfetto_cc_proto_library'
316 elif target.proto_plugin == 'protozero':
317 plugin_label_type = 'perfetto_cc_protozero_library'
318 elif target.proto_plugin == 'cppgen':
319 plugin_label_type = 'perfetto_cc_protocpp_library'
320 elif target.proto_plugin == 'ipc':
321 plugin_label_type = 'perfetto_cc_ipc_library'
322 elif target.proto_plugin == 'descriptor':
323 plugin_label_type = 'perfetto_proto_descriptor'
324 else:
325 raise Error('Unknown proto plugin: %s' % target.proto_plugin)
326 plugin_label_name = get_bazel_label_name(target.name)
327 plugin_label = BazelLabel(plugin_label_name, plugin_label_type)
328 plugin_label.comment = target.name
329 plugin_label.deps += [':' + sources_label_name]
330
331 # When using the cppgen plugin we need to pass down also the transitive deps.
332 # For instance consider foo.proto including common.proto. The generated
333 # foo.cc will #include "common.gen.h". Hence the generated cc_protocpp_library
334 # rule need to pass down the dependency on the target that generates
335 # common.gen.{cc,h}. This is not needed for protozero because protozero
336 # headers are fully hermetic deps-wise and use only on forward declarations.
337 if target.proto_deps and target.proto_plugin in ('cppgen', 'ipc'):
338 plugin_label.deps += [
339 ':' + get_bazel_label_name(x) for x in target.proto_deps
340 ]
341
342 if target.proto_plugin == 'descriptor':
343 plugin_label.outs = [plugin_label_name + '.bin']
344
345 return [sources_label, plugin_label]
Primiano Tucci1d409982019-09-19 10:15:18 +0100346
347
348def gen_target(gn_target):
349 if gn_target.type == 'proto_library':
350 return gen_proto_labels(gn_target)
351 elif gn_target.type == 'action':
352 if gn_target.name in custom_actions:
353 return custom_actions[gn_target.name](gn_target)
354 return []
355 elif gn_target.type == 'group':
356 return []
357 elif gn_target.type == 'executable':
358 bazel_type = 'perfetto_cc_binary'
359 elif gn_target.type == 'shared_library':
360 bazel_type = 'perfetto_cc_binary'
361 vars['linkshared'] = True
362 elif gn_target.type == 'static_library':
363 bazel_type = 'perfetto_cc_library'
364 elif gn_target.type == 'source_set':
365 bazel_type = 'filegroup'
366 else:
367 raise Error('target type not supported: %s' % gn_target.type)
368
369 label = BazelLabel(get_bazel_label_name(gn_target.name), bazel_type)
370 label.comment = gn_target.name
Lalit Maganti91d223e2019-12-20 12:28:19 +0000371
372 raw_srcs = [x[2:] for x in gn_target.sources]
373 if bazel_type == 'perfetto_cc_library':
374 label.srcs = [x for x in raw_srcs if not x.startswith('include')]
375 label.hdrs = [x for x in raw_srcs if x.startswith('include')]
Lalit Magantif9c004d2020-01-06 14:44:34 +0000376
377 # Most Perfetto libraries cannot by dynamically linked as they would
378 # cause ODR violations.
379 label.__dict__['linkstatic'] = True
Lalit Maganti91d223e2019-12-20 12:28:19 +0000380 else:
381 label.srcs = raw_srcs
Primiano Tucci1d409982019-09-19 10:15:18 +0100382
383 if gn_target.name in public_targets:
384 label.visibility = ['//visibility:public']
385
386 if gn_target.type in gn_utils.LINKER_UNIT_TYPES:
387 # |source_sets| contains the transitive set of source_set deps.
388 for trans_dep in gn_target.source_set_deps:
389 name = ':' + get_bazel_label_name(trans_dep)
390 if name.startswith(
391 ':include_perfetto_') and gn_target.type != 'executable':
392 label.hdrs += [name]
393 else:
394 label.srcs += [name]
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100395 for dep in sorted(gn_target.deps):
Primiano Tucci1d409982019-09-19 10:15:18 +0100396 if dep.startswith('//gn:'):
397 assert (dep in external_deps), dep
398 if dep in external_deps:
399 assert (isinstance(external_deps[dep], list))
400 label.external_deps += external_deps[dep]
401 else:
402 label.deps += [':' + get_bazel_label_name(dep)]
403 label.deps += [':' + get_bazel_label_name(x) for x in gn_target.proto_deps]
404
Lalit Maganti65600342019-09-19 21:35:35 +0100405 # All items starting with : need to be sorted to the end of the list.
406 # However, Python makes specifying a comparator function hard so cheat
407 # instead and make everything start with : sort as if it started with |
408 # As | > all other normal ASCII characters, this will lead to all : targets
409 # starting with : to be sorted to the end.
410 label.srcs = sorted(label.srcs, key=lambda x: x.replace(':', '|'))
411
Primiano Tucci1d409982019-09-19 10:15:18 +0100412 label.deps = sorted(label.deps)
Primiano Tucci1d409982019-09-19 10:15:18 +0100413 label.hdrs = sorted(label.hdrs)
414 return [label]
415
416
417def gen_target_str(gn_target):
418 return ''.join(str(x) for x in gen_target(gn_target))
419
420
421def generate_build(gn_desc, targets, extras):
422 gn = gn_utils.GnParser(gn_desc)
423 res = '''
424# Copyright (C) 2019 The Android Open Source Project
Lalit Maganti279ecde2019-04-01 16:57:12 +0100425#
426# Licensed under the Apache License, Version 2.0 (the "License");
427# you may not use this file except in compliance with the License.
428# You may obtain a copy of the License at
429#
430# http://www.apache.org/licenses/LICENSE-2.0
431#
432# Unless required by applicable law or agreed to in writing, software
433# distributed under the License is distributed on an "AS IS" BASIS,
434# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
435# See the License for the specific language governing permissions and
436# limitations under the License.
437#
438# This file is automatically generated by {}. Do not edit.
Lalit Maganti279ecde2019-04-01 16:57:12 +0100439
Primiano Tucci1d409982019-09-19 10:15:18 +0100440load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
441load(
442 "@perfetto//bazel:rules.bzl",
443 "perfetto_cc_binary",
444 "perfetto_cc_ipc_library",
445 "perfetto_cc_library",
Lalit Maganti117272f2020-09-11 14:01:18 +0100446 "perfetto_cc_proto_descriptor",
Primiano Tucci1d409982019-09-19 10:15:18 +0100447 "perfetto_cc_proto_library",
Primiano Tucci57dd66b2019-10-15 23:09:04 +0100448 "perfetto_cc_protocpp_library",
Primiano Tucci1d409982019-09-19 10:15:18 +0100449 "perfetto_cc_protozero_library",
Lalit Maganti65600342019-09-19 21:35:35 +0100450 "perfetto_java_proto_library",
Lalit Maganti46e2bda2020-05-06 12:51:33 +0100451 "perfetto_java_lite_proto_library",
Primiano Tucci1d409982019-09-19 10:15:18 +0100452 "perfetto_proto_library",
Lalit Maganti117272f2020-09-11 14:01:18 +0100453 "perfetto_proto_descriptor",
Primiano Tucci1d409982019-09-19 10:15:18 +0100454 "perfetto_py_binary",
Anindita Ghosh237a7762020-06-30 10:46:52 +0000455 "perfetto_py_library",
Lalit Maganti65600342019-09-19 21:35:35 +0100456 "perfetto_gensignature_internal_only",
Primiano Tucci1d409982019-09-19 10:15:18 +0100457)
Lalit Maganti279ecde2019-04-01 16:57:12 +0100458
Primiano Tucci1d409982019-09-19 10:15:18 +0100459package(default_visibility = ["//visibility:private"])
Lalit Maganti65600342019-09-19 21:35:35 +0100460
Lalit Magantibb037f72019-09-24 16:22:45 +0100461licenses(["notice"])
Lalit Maganti65600342019-09-19 21:35:35 +0100462
Primiano Tucci1d409982019-09-19 10:15:18 +0100463exports_files(["NOTICE"])
Lalit Magantia48710d2019-09-24 13:10:11 +0100464
Lalit Maganti65600342019-09-19 21:35:35 +0100465'''.format(__file__).lstrip()
Lalit Maganti279ecde2019-04-01 16:57:12 +0100466
Primiano Tucci1d409982019-09-19 10:15:18 +0100467 # Public targets need to be computed at the beginning (to figure out the
468 # intermediate deps) but printed at the end (because declaration order matters
469 # in Bazel).
470 public_str = ''
471 for target_name in sorted(public_targets):
472 target = gn.get_target(target_name)
473 public_str += gen_target_str(target)
Primiano Tucci8e627442019-08-28 07:58:38 +0200474
Primiano Tucci1d409982019-09-19 10:15:18 +0100475 res += '''
476# ##############################################################################
477# Internal targets
478# ##############################################################################
Lalit Maganti279ecde2019-04-01 16:57:12 +0100479
Lalit Maganti65600342019-09-19 21:35:35 +0100480'''.lstrip()
Primiano Tucci1d409982019-09-19 10:15:18 +0100481 # Generate the other non-public targets.
482 for target_name in sorted(set(default_targets) - set(public_targets)):
483 target = gn.get_target(target_name)
484 res += gen_target_str(target)
Lalit Maganti279ecde2019-04-01 16:57:12 +0100485
Primiano Tucci1d409982019-09-19 10:15:18 +0100486 # Generate all the intermediate targets.
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100487 for target in sorted(itervalues(gn.all_targets)):
Primiano Tucci1d409982019-09-19 10:15:18 +0100488 if target.name in default_targets or target.name in gn.proto_libs:
489 continue
490 res += gen_target_str(target)
Lalit Maganti279ecde2019-04-01 16:57:12 +0100491
Primiano Tucci1d409982019-09-19 10:15:18 +0100492 res += '''
493# ##############################################################################
494# Proto libraries
495# ##############################################################################
Lalit Maganti279ecde2019-04-01 16:57:12 +0100496
Lalit Maganti65600342019-09-19 21:35:35 +0100497'''.lstrip()
Primiano Tucci1d409982019-09-19 10:15:18 +0100498 # Force discovery of explicilty listed root proto targets.
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100499 for target_name in sorted(proto_targets):
Primiano Tucci1d409982019-09-19 10:15:18 +0100500 gn.get_target(target_name)
Lalit Maganti279ecde2019-04-01 16:57:12 +0100501
Primiano Tucci1d409982019-09-19 10:15:18 +0100502 # Generate targets for the transitive set of proto targets.
503 # TODO explain deduping here.
504 labels = {}
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100505 for target in sorted(itervalues(gn.proto_libs)):
Primiano Tucci1d409982019-09-19 10:15:18 +0100506 for label in gen_target(target):
Lalit Maganti613f97b2019-11-21 14:44:18 +0000507 # Ensure that if the existing target has public visibility, we preserve
508 # that in the new label; this ensures that we don't accidentaly reduce
509 # the visibility of targets which are meant to be public.
510 existing_label = labels.get(label.name)
511 if existing_label and existing_label.visibility == PUBLIC_VISIBILITY:
512 label.visibility = PUBLIC_VISIBILITY
Primiano Tucci1d409982019-09-19 10:15:18 +0100513 labels[label.name] = label
Lalit Maganti279ecde2019-04-01 16:57:12 +0100514
Matthew Clarkson9a5dfa52019-10-03 09:54:04 +0100515 res += ''.join(str(x) for x in sorted(itervalues(labels)))
Lalit Maganti279ecde2019-04-01 16:57:12 +0100516
Primiano Tucci1d409982019-09-19 10:15:18 +0100517 res += '''
518# ##############################################################################
519# Public targets
520# ##############################################################################
Lalit Maganti279ecde2019-04-01 16:57:12 +0100521
Lalit Maganti65600342019-09-19 21:35:35 +0100522'''.lstrip()
Primiano Tucci1d409982019-09-19 10:15:18 +0100523 res += public_str
524 res += '# Content from BUILD.extras\n\n'
525 res += extras
Lalit Maganti279ecde2019-04-01 16:57:12 +0100526
Primiano Tucci916f4e52020-10-16 20:40:33 +0200527 # Check for ODR violations
528 for target_name in default_targets + proto_targets:
529 checker = gn_utils.ODRChecker(gn, target_name)
530
531 return res
Lalit Maganti279ecde2019-04-01 16:57:12 +0100532
Lalit Maganti279ecde2019-04-01 16:57:12 +0100533def main():
534 parser = argparse.ArgumentParser(
535 description='Generate BUILD from a GN description.')
536 parser.add_argument(
Primiano Tucci1d409982019-09-19 10:15:18 +0100537 '--check-only',
538 help='Don\'t keep the generated files',
539 action='store_true')
Primiano Tucci9c411652019-08-27 07:13:59 +0200540 parser.add_argument(
Lalit Maganti279ecde2019-04-01 16:57:12 +0100541 '--desc',
Primiano Tucci1d409982019-09-19 10:15:18 +0100542 help='GN description ' +
543 '(e.g., gn desc out --format=json --all-toolchains "//*"')
Lalit Maganti279ecde2019-04-01 16:57:12 +0100544 parser.add_argument(
545 '--repo-root',
546 help='Standalone Perfetto repository to generate a GN description',
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100547 default=gn_utils.repo_root(),
Lalit Maganti279ecde2019-04-01 16:57:12 +0100548 )
549 parser.add_argument(
550 '--extras',
551 help='Extra targets to include at the end of the BUILD file',
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100552 default=os.path.join(gn_utils.repo_root(), 'BUILD.extras'),
Lalit Maganti279ecde2019-04-01 16:57:12 +0100553 )
554 parser.add_argument(
555 '--output',
556 help='BUILD file to create',
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100557 default=os.path.join(gn_utils.repo_root(), 'BUILD'),
Lalit Maganti279ecde2019-04-01 16:57:12 +0100558 )
559 parser.add_argument(
560 '--output-proto',
561 help='Proto BUILD file to create',
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100562 default=os.path.join(gn_utils.repo_root(), 'protos', 'BUILD'),
Lalit Maganti279ecde2019-04-01 16:57:12 +0100563 )
564 parser.add_argument(
565 'targets',
566 nargs=argparse.REMAINDER,
567 help='Targets to include in the BUILD file (e.g., "//:perfetto_tests")')
568 args = parser.parse_args()
569
570 if args.desc:
571 with open(args.desc) as f:
572 desc = json.load(f)
573 else:
Sami Kyostila3c88a1d2019-05-22 18:29:42 +0100574 desc = gn_utils.create_build_description(gn_args, args.repo_root)
Lalit Maganti279ecde2019-04-01 16:57:12 +0100575
Primiano Tucci9c411652019-08-27 07:13:59 +0200576 out_files = []
577
Primiano Tucci9c411652019-08-27 07:13:59 +0200578 # Generate the main BUILD file.
Primiano Tucci1d409982019-09-19 10:15:18 +0100579 with open(args.extras, 'r') as extra_f:
580 extras = extra_f.read()
Lalit Maganti279ecde2019-04-01 16:57:12 +0100581
Primiano Tucci1d409982019-09-19 10:15:18 +0100582 contents = generate_build(desc, args.targets or default_targets, extras)
583 out_files.append(args.output + '.swp')
584 with open(out_files[-1], 'w') as out_f:
585 out_f.write(contents)
Lalit Maganti279ecde2019-04-01 16:57:12 +0100586
Primiano Tucci8e627442019-08-28 07:58:38 +0200587 # Generate the build flags file.
588 out_files.append(os.path.join(buildflags_dir, 'perfetto_build_flags.h.swp'))
589 gn_utils.gen_buildflags(gn_args, out_files[-1])
590
Primiano Tucci9c411652019-08-27 07:13:59 +0200591 return gn_utils.check_or_commit_generated_files(out_files, args.check_only)
Lalit Maganti279ecde2019-04-01 16:57:12 +0100592
593
594if __name__ == '__main__':
595 sys.exit(main())