xref: /aosp_15_r20/external/perfetto/tools/gen_bazel (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2018 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker#
4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker#
8*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker#
10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Worker# This tool translates a collection of BUILD.gn files into a mostly equivalent
17*6dbdd20aSAndroid Build Coastguard Worker# BUILD file for the Bazel build system. The input to the tool is a
18*6dbdd20aSAndroid Build Coastguard Worker# JSON description of the GN build definition generated with the following
19*6dbdd20aSAndroid Build Coastguard Worker# command:
20*6dbdd20aSAndroid Build Coastguard Worker#
21*6dbdd20aSAndroid Build Coastguard Worker#   gn desc out --format=json --all-toolchains "//*" > desc.json
22*6dbdd20aSAndroid Build Coastguard Worker#
23*6dbdd20aSAndroid Build Coastguard Worker# The tool is then given a list of GN labels for which to generate Bazel
24*6dbdd20aSAndroid Build Coastguard Worker# build rules.
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard Workerfrom __future__ import print_function
27*6dbdd20aSAndroid Build Coastguard Workerimport argparse
28*6dbdd20aSAndroid Build Coastguard Workerimport json
29*6dbdd20aSAndroid Build Coastguard Workerimport os
30*6dbdd20aSAndroid Build Coastguard Workerimport re
31*6dbdd20aSAndroid Build Coastguard Workerimport sys
32*6dbdd20aSAndroid Build Coastguard Workerfrom typing import Any
33*6dbdd20aSAndroid Build Coastguard Workerfrom typing import Dict
34*6dbdd20aSAndroid Build Coastguard Workerfrom typing import List
35*6dbdd20aSAndroid Build Coastguard Workerfrom typing import Optional
36*6dbdd20aSAndroid Build Coastguard Workerfrom typing import Union
37*6dbdd20aSAndroid Build Coastguard Worker
38*6dbdd20aSAndroid Build Coastguard Workerfrom gn_utils import GnParser
39*6dbdd20aSAndroid Build Coastguard Workerimport gn_utils
40*6dbdd20aSAndroid Build Coastguard Worker
41*6dbdd20aSAndroid Build Coastguard Workerfrom compat import itervalues, iteritems, basestring
42*6dbdd20aSAndroid Build Coastguard Worker
43*6dbdd20aSAndroid Build Coastguard Worker# Visibility option for targets which we want an allowlist of public targets
44*6dbdd20aSAndroid Build Coastguard Worker# which can depend on it.
45*6dbdd20aSAndroid Build Coastguard WorkerALLOWLIST_PUBLIC_VISIBILITY = 'PERFETTO_CONFIG.public_visibility'
46*6dbdd20aSAndroid Build Coastguard Worker
47*6dbdd20aSAndroid Build Coastguard Worker# Arguments for the GN output directory.
48*6dbdd20aSAndroid Build Coastguard Worker# host_os="linux" is to generate the right build files from Mac OS.
49*6dbdd20aSAndroid Build Coastguard Workergn_args_base = {
50*6dbdd20aSAndroid Build Coastguard Worker    'host_os': '"linux"',
51*6dbdd20aSAndroid Build Coastguard Worker    'is_debug': 'false',
52*6dbdd20aSAndroid Build Coastguard Worker    'is_perfetto_build_generator': 'true',
53*6dbdd20aSAndroid Build Coastguard Worker    'monolithic_binaries': 'true',
54*6dbdd20aSAndroid Build Coastguard Worker    'target_os': '"linux"',
55*6dbdd20aSAndroid Build Coastguard Worker    'enable_perfetto_heapprofd': 'false',
56*6dbdd20aSAndroid Build Coastguard Worker    'enable_perfetto_traced_perf': 'false',
57*6dbdd20aSAndroid Build Coastguard Worker    'perfetto_force_dcheck': '"off"',
58*6dbdd20aSAndroid Build Coastguard Worker    'enable_perfetto_llvm_demangle': 'true',
59*6dbdd20aSAndroid Build Coastguard Worker    'enable_perfetto_etm_importer': 'false',
60*6dbdd20aSAndroid Build Coastguard Worker}
61*6dbdd20aSAndroid Build Coastguard Workergn_args = ' '.join((map(lambda x:'='.join(x), gn_args_base.items())))
62*6dbdd20aSAndroid Build Coastguard Worker
63*6dbdd20aSAndroid Build Coastguard Worker# We generate a second set of build rules for Windows, in order to
64*6dbdd20aSAndroid Build Coastguard Worker# conditionally filter out targets which are gated behind !is_win
65*6dbdd20aSAndroid Build Coastguard Worker# in the GN build files.
66*6dbdd20aSAndroid Build Coastguard Workergn_args_win_base = {
67*6dbdd20aSAndroid Build Coastguard Worker    **gn_args_base,
68*6dbdd20aSAndroid Build Coastguard Worker    'host_os': '"win"',
69*6dbdd20aSAndroid Build Coastguard Worker    'host_cpu': '"x86"',
70*6dbdd20aSAndroid Build Coastguard Worker    'target_os': '"win"',
71*6dbdd20aSAndroid Build Coastguard Worker    'target_cpu': '"x64"',
72*6dbdd20aSAndroid Build Coastguard Worker    'is_cross_compiling': 'false',
73*6dbdd20aSAndroid Build Coastguard Worker}
74*6dbdd20aSAndroid Build Coastguard Workergn_args_win = ' '.join((map(lambda x:'='.join(x), gn_args_win_base.items())))
75*6dbdd20aSAndroid Build Coastguard Worker
76*6dbdd20aSAndroid Build Coastguard Worker# Default targets to translate to the blueprint file.
77*6dbdd20aSAndroid Build Coastguard Worker
78*6dbdd20aSAndroid Build Coastguard Worker# These targets will be exported with public visibility in the generated BUILD.
79*6dbdd20aSAndroid Build Coastguard Workerpublic_targets = [
80*6dbdd20aSAndroid Build Coastguard Worker    '//:libperfetto_client_experimental',
81*6dbdd20aSAndroid Build Coastguard Worker    '//src/perfetto_cmd:perfetto',
82*6dbdd20aSAndroid Build Coastguard Worker    '//src/traced/probes:traced_probes',
83*6dbdd20aSAndroid Build Coastguard Worker    '//src/traced/service:traced',
84*6dbdd20aSAndroid Build Coastguard Worker    '//src/trace_processor:trace_processor_shell',
85*6dbdd20aSAndroid Build Coastguard Worker    '//src/trace_processor:trace_processor',
86*6dbdd20aSAndroid Build Coastguard Worker    '//src/traceconv:traceconv',
87*6dbdd20aSAndroid Build Coastguard Worker]
88*6dbdd20aSAndroid Build Coastguard Worker
89*6dbdd20aSAndroid Build Coastguard Worker# These targets will be exported with visibility only to our allowlist.
90*6dbdd20aSAndroid Build Coastguard Workerallowlist_public_targets = [
91*6dbdd20aSAndroid Build Coastguard Worker    '//src/shared_lib:libperfetto_c',
92*6dbdd20aSAndroid Build Coastguard Worker    '//src/traceconv:libpprofbuilder',
93*6dbdd20aSAndroid Build Coastguard Worker]
94*6dbdd20aSAndroid Build Coastguard Worker
95*6dbdd20aSAndroid Build Coastguard Worker# These targets are required by internal build rules but don't need to be
96*6dbdd20aSAndroid Build Coastguard Worker# exported publicly.
97*6dbdd20aSAndroid Build Coastguard Workerdefault_targets = [
98*6dbdd20aSAndroid Build Coastguard Worker    '//src/base:perfetto_base_default_platform',
99*6dbdd20aSAndroid Build Coastguard Worker    '//src/ipc:perfetto_ipc',
100*6dbdd20aSAndroid Build Coastguard Worker    '//src/ipc/protoc_plugin:ipc_plugin',
101*6dbdd20aSAndroid Build Coastguard Worker    '//src/protozero:protozero',
102*6dbdd20aSAndroid Build Coastguard Worker    '//src/protozero/protoc_plugin:cppgen_plugin',
103*6dbdd20aSAndroid Build Coastguard Worker    '//src/protozero/protoc_plugin:protozero_plugin',
104*6dbdd20aSAndroid Build Coastguard Worker    '//src/tools/proto_filter:proto_filter',
105*6dbdd20aSAndroid Build Coastguard Worker    '//src/tools/proto_merger:proto_merger',
106*6dbdd20aSAndroid Build Coastguard Worker    '//src/trace_processor/rpc:trace_processor_rpc',
107*6dbdd20aSAndroid Build Coastguard Worker    '//test:client_api_example',
108*6dbdd20aSAndroid Build Coastguard Worker] + public_targets + allowlist_public_targets
109*6dbdd20aSAndroid Build Coastguard Worker
110*6dbdd20aSAndroid Build Coastguard Worker# Proto target groups which will be made public.
111*6dbdd20aSAndroid Build Coastguard Workerproto_groups = {
112*6dbdd20aSAndroid Build Coastguard Worker    'config': {
113*6dbdd20aSAndroid Build Coastguard Worker        'sources': ['//protos/perfetto/config:source_set'],
114*6dbdd20aSAndroid Build Coastguard Worker        'visibility': ['//visibility:public'],
115*6dbdd20aSAndroid Build Coastguard Worker    },
116*6dbdd20aSAndroid Build Coastguard Worker    'trace': {
117*6dbdd20aSAndroid Build Coastguard Worker        'sources': [
118*6dbdd20aSAndroid Build Coastguard Worker            '//protos/perfetto/trace:non_minimal_source_set',
119*6dbdd20aSAndroid Build Coastguard Worker            '//protos/perfetto/trace:minimal_source_set'
120*6dbdd20aSAndroid Build Coastguard Worker        ],
121*6dbdd20aSAndroid Build Coastguard Worker        'visibility': ALLOWLIST_PUBLIC_VISIBILITY,
122*6dbdd20aSAndroid Build Coastguard Worker    },
123*6dbdd20aSAndroid Build Coastguard Worker    'metrics': {
124*6dbdd20aSAndroid Build Coastguard Worker        'sources': ['//protos/perfetto/metrics:source_set',],
125*6dbdd20aSAndroid Build Coastguard Worker        'visibility': ['//visibility:public'],
126*6dbdd20aSAndroid Build Coastguard Worker    },
127*6dbdd20aSAndroid Build Coastguard Worker    'chromium': {
128*6dbdd20aSAndroid Build Coastguard Worker        'sources': ['//protos/third_party/chromium:source_set',],
129*6dbdd20aSAndroid Build Coastguard Worker        'visibility': ALLOWLIST_PUBLIC_VISIBILITY,
130*6dbdd20aSAndroid Build Coastguard Worker    },
131*6dbdd20aSAndroid Build Coastguard Worker    'chrome_metrics': {
132*6dbdd20aSAndroid Build Coastguard Worker        'sources': ['//protos/perfetto/metrics/chrome:source_set',],
133*6dbdd20aSAndroid Build Coastguard Worker        'visibility': ALLOWLIST_PUBLIC_VISIBILITY,
134*6dbdd20aSAndroid Build Coastguard Worker    },
135*6dbdd20aSAndroid Build Coastguard Worker    'trace_processor': {
136*6dbdd20aSAndroid Build Coastguard Worker        'sources': ['//protos/perfetto/trace_processor:source_set',],
137*6dbdd20aSAndroid Build Coastguard Worker        'visibility': [],
138*6dbdd20aSAndroid Build Coastguard Worker    },
139*6dbdd20aSAndroid Build Coastguard Worker}
140*6dbdd20aSAndroid Build Coastguard Worker
141*6dbdd20aSAndroid Build Coastguard Worker# Path for the protobuf sources in the standalone build.
142*6dbdd20aSAndroid Build Coastguard Workerbuildtools_protobuf_src = '//buildtools/protobuf/src'
143*6dbdd20aSAndroid Build Coastguard Worker
144*6dbdd20aSAndroid Build Coastguard Worker# The directory where the generated perfetto_build_flags.h will be copied into.
145*6dbdd20aSAndroid Build Coastguard Workerbuildflags_dir = 'include/perfetto/base/build_configs/bazel'
146*6dbdd20aSAndroid Build Coastguard Worker
147*6dbdd20aSAndroid Build Coastguard Worker# Internal equivalents for third-party libraries that the upstream project
148*6dbdd20aSAndroid Build Coastguard Worker# depends on.
149*6dbdd20aSAndroid Build Coastguard Workerexternal_deps = {
150*6dbdd20aSAndroid Build Coastguard Worker    '//gn:default_deps': [],
151*6dbdd20aSAndroid Build Coastguard Worker    '//gn:base_platform': ['PERFETTO_CONFIG.deps.base_platform'],
152*6dbdd20aSAndroid Build Coastguard Worker    '//gn:expat': ['PERFETTO_CONFIG.deps.expat'],
153*6dbdd20aSAndroid Build Coastguard Worker    '//gn:jsoncpp': ['PERFETTO_CONFIG.deps.jsoncpp'],
154*6dbdd20aSAndroid Build Coastguard Worker    '//gn:linenoise': ['PERFETTO_CONFIG.deps.linenoise'],
155*6dbdd20aSAndroid Build Coastguard Worker    '//gn:open_csd': ['PERFETTO_CONFIG.deps.open_csd'],
156*6dbdd20aSAndroid Build Coastguard Worker    '//gn:protobuf_full': ['PERFETTO_CONFIG.deps.protobuf_full'],
157*6dbdd20aSAndroid Build Coastguard Worker    '//gn:protobuf_lite': ['PERFETTO_CONFIG.deps.protobuf_lite'],
158*6dbdd20aSAndroid Build Coastguard Worker    '//gn:protoc_lib': ['PERFETTO_CONFIG.deps.protoc_lib'],
159*6dbdd20aSAndroid Build Coastguard Worker    '//gn:protoc': ['PERFETTO_CONFIG.deps.protoc'],
160*6dbdd20aSAndroid Build Coastguard Worker    '//gn:sqlite': [
161*6dbdd20aSAndroid Build Coastguard Worker        'PERFETTO_CONFIG.deps.sqlite',
162*6dbdd20aSAndroid Build Coastguard Worker        'PERFETTO_CONFIG.deps.sqlite_ext_percentile'
163*6dbdd20aSAndroid Build Coastguard Worker    ],
164*6dbdd20aSAndroid Build Coastguard Worker    '//gn:zlib': ['PERFETTO_CONFIG.deps.zlib'],
165*6dbdd20aSAndroid Build Coastguard Worker    '//gn:llvm_demangle': ['PERFETTO_CONFIG.deps.llvm_demangle'],
166*6dbdd20aSAndroid Build Coastguard Worker    '//src/trace_processor:demangle': ['PERFETTO_CONFIG.deps.demangle_wrapper'],
167*6dbdd20aSAndroid Build Coastguard Worker    gn_utils.GEN_VERSION_TARGET: ['PERFETTO_CONFIG.deps.version_header'],
168*6dbdd20aSAndroid Build Coastguard Worker}
169*6dbdd20aSAndroid Build Coastguard Worker
170*6dbdd20aSAndroid Build Coastguard Worker# These are Python targets which are exposed with public visibility.
171*6dbdd20aSAndroid Build Coastguard Workerpublic_python_targets = [
172*6dbdd20aSAndroid Build Coastguard Worker    '//python:batch_trace_processor',
173*6dbdd20aSAndroid Build Coastguard Worker    '//python:trace_processor_py',
174*6dbdd20aSAndroid Build Coastguard Worker    '//python:trace_processor_py_no_resolvers',
175*6dbdd20aSAndroid Build Coastguard Worker]
176*6dbdd20aSAndroid Build Coastguard Worker
177*6dbdd20aSAndroid Build Coastguard Worker# These are Python targets which are exposed by default.
178*6dbdd20aSAndroid Build Coastguard Workerdefault_python_targets = [
179*6dbdd20aSAndroid Build Coastguard Worker    '//python:batch_trace_processor',
180*6dbdd20aSAndroid Build Coastguard Worker    '//python:experimental_slice_breakdown_bin',
181*6dbdd20aSAndroid Build Coastguard Worker    '//python:trace_processor_table_generator',
182*6dbdd20aSAndroid Build Coastguard Worker    '//python:trace_processor_py_example',
183*6dbdd20aSAndroid Build Coastguard Worker    '//python:sql_processing',
184*6dbdd20aSAndroid Build Coastguard Worker]
185*6dbdd20aSAndroid Build Coastguard Worker
186*6dbdd20aSAndroid Build Coastguard Worker# Internal equivalents for third-party Python libraries.
187*6dbdd20aSAndroid Build Coastguard Workerexternal_python_deps: Dict[str, List[str]] = {
188*6dbdd20aSAndroid Build Coastguard Worker    '//gn:pandas_py': ['PERFETTO_CONFIG.deps.pandas_py'],
189*6dbdd20aSAndroid Build Coastguard Worker    '//gn:protobuf_py': ['PERFETTO_CONFIG.deps.protobuf_py'],
190*6dbdd20aSAndroid Build Coastguard Worker    '//gn:tp_vendor_py': ['PERFETTO_CONFIG.deps.tp_vendor_py'],
191*6dbdd20aSAndroid Build Coastguard Worker    '//gn:tp_resolvers_py': ['PERFETTO_CONFIG.deps.tp_resolvers_py'],
192*6dbdd20aSAndroid Build Coastguard Worker}
193*6dbdd20aSAndroid Build Coastguard Worker
194*6dbdd20aSAndroid Build Coastguard Worker# Additional arguments
195*6dbdd20aSAndroid Build Coastguard Workertarget_overrides = {
196*6dbdd20aSAndroid Build Coastguard Worker  '//src/trace_processor/perfetto_sql/stdlib/chrome:chrome_sql': {
197*6dbdd20aSAndroid Build Coastguard Worker    'srcs': 'glob(["src/trace_processor/perfetto_sql/stdlib/chrome/**/*.sql"])'
198*6dbdd20aSAndroid Build Coastguard Worker  }
199*6dbdd20aSAndroid Build Coastguard Worker}
200*6dbdd20aSAndroid Build Coastguard Worker
201*6dbdd20aSAndroid Build Coastguard Worker# Defines required for Bazel.
202*6dbdd20aSAndroid Build Coastguard Workerbazel_required_defines = [
203*6dbdd20aSAndroid Build Coastguard Worker  "PERFETTO_SHLIB_SDK_IMPLEMENTATION"
204*6dbdd20aSAndroid Build Coastguard Worker]
205*6dbdd20aSAndroid Build Coastguard Worker
206*6dbdd20aSAndroid Build Coastguard Worker# Targets with the "avoid_dep" tag;
207*6dbdd20aSAndroid Build Coastguard Workeravoid_dep_targets = set([
208*6dbdd20aSAndroid Build Coastguard Worker  '//python:trace_processor_py_no_resolvers',
209*6dbdd20aSAndroid Build Coastguard Worker])
210*6dbdd20aSAndroid Build Coastguard Worker
211*6dbdd20aSAndroid Build Coastguard Worker# Filter defines that appear in the bazel build file to only those that bazel requires.
212*6dbdd20aSAndroid Build Coastguard Workerdef filter_defines(defines):
213*6dbdd20aSAndroid Build Coastguard Worker  return [d for d in defines if d in bazel_required_defines]
214*6dbdd20aSAndroid Build Coastguard Worker
215*6dbdd20aSAndroid Build Coastguard Worker
216*6dbdd20aSAndroid Build Coastguard Workerdef gen_version_header(target):
217*6dbdd20aSAndroid Build Coastguard Worker  label = BazelLabel(get_bazel_label_name(target.name), 'perfetto_genrule')
218*6dbdd20aSAndroid Build Coastguard Worker  label.srcs += [gn_utils.label_to_path(x) for x in sorted(target.inputs)]
219*6dbdd20aSAndroid Build Coastguard Worker  label.outs += target.outputs
220*6dbdd20aSAndroid Build Coastguard Worker  label.cmd = r'$(location gen_version_header_py)'
221*6dbdd20aSAndroid Build Coastguard Worker  label.cmd += r' --cpp_out=$@ --changelog=$(location CHANGELOG)'
222*6dbdd20aSAndroid Build Coastguard Worker  label.tools += [':gen_version_header_py']
223*6dbdd20aSAndroid Build Coastguard Worker  return [label]
224*6dbdd20aSAndroid Build Coastguard Worker
225*6dbdd20aSAndroid Build Coastguard Worker
226*6dbdd20aSAndroid Build Coastguard Workercustom_actions = {
227*6dbdd20aSAndroid Build Coastguard Worker    gn_utils.GEN_VERSION_TARGET: gen_version_header,
228*6dbdd20aSAndroid Build Coastguard Worker}
229*6dbdd20aSAndroid Build Coastguard Worker
230*6dbdd20aSAndroid Build Coastguard Worker# ------------------------------------------------------------------------------
231*6dbdd20aSAndroid Build Coastguard Worker# End of configuration.
232*6dbdd20aSAndroid Build Coastguard Worker# ------------------------------------------------------------------------------
233*6dbdd20aSAndroid Build Coastguard Worker
234*6dbdd20aSAndroid Build Coastguard Worker
235*6dbdd20aSAndroid Build Coastguard Workerclass PythonBuildGenerator:
236*6dbdd20aSAndroid Build Coastguard Worker  '''Generator of the BUILD file in the python folder.
237*6dbdd20aSAndroid Build Coastguard Worker
238*6dbdd20aSAndroid Build Coastguard Worker  This code is split into its own class to avoid polluting
239*6dbdd20aSAndroid Build Coastguard Worker  the generation of the main build file with Python related
240*6dbdd20aSAndroid Build Coastguard Worker  content.
241*6dbdd20aSAndroid Build Coastguard Worker  '''
242*6dbdd20aSAndroid Build Coastguard Worker
243*6dbdd20aSAndroid Build Coastguard Worker  def populate_python_deps(self, target: GnParser.Target, label: 'BazelLabel'):
244*6dbdd20aSAndroid Build Coastguard Worker    '''Populates deps for a GN target into Bazel Python label.'''
245*6dbdd20aSAndroid Build Coastguard Worker    for dep in sorted(target.non_proto_or_source_set_deps()):
246*6dbdd20aSAndroid Build Coastguard Worker      if dep.name in external_python_deps:
247*6dbdd20aSAndroid Build Coastguard Worker        assert (isinstance(external_python_deps[dep.name], list))
248*6dbdd20aSAndroid Build Coastguard Worker        label.external_deps += external_python_deps[dep.name]
249*6dbdd20aSAndroid Build Coastguard Worker      else:
250*6dbdd20aSAndroid Build Coastguard Worker        label.deps += [':' + get_bazel_python_label_name(dep.name)]
251*6dbdd20aSAndroid Build Coastguard Worker
252*6dbdd20aSAndroid Build Coastguard Worker  def python_label_to_path(self, gn_name: str):
253*6dbdd20aSAndroid Build Coastguard Worker    """Converts a Python GN path label into a Bazel path."""
254*6dbdd20aSAndroid Build Coastguard Worker    return re.sub(r'^python/', '', gn_utils.label_to_path(gn_name))
255*6dbdd20aSAndroid Build Coastguard Worker
256*6dbdd20aSAndroid Build Coastguard Worker  def python_data_to_path(self, gn_name: str):
257*6dbdd20aSAndroid Build Coastguard Worker    """Converts a Python GN data label into a Bazel data label."""
258*6dbdd20aSAndroid Build Coastguard Worker    return re.sub(r'^\.\.(.*)', r'PERFETTO_CONFIG.root + "\1"', gn_name)
259*6dbdd20aSAndroid Build Coastguard Worker
260*6dbdd20aSAndroid Build Coastguard Worker  def gen_python_library(self, target: GnParser.Target):
261*6dbdd20aSAndroid Build Coastguard Worker    """Creates a Bazel target for a Python library GN target."""
262*6dbdd20aSAndroid Build Coastguard Worker    label = BazelLabel(
263*6dbdd20aSAndroid Build Coastguard Worker        get_bazel_python_label_name(target.name), 'perfetto_py_library')
264*6dbdd20aSAndroid Build Coastguard Worker    label.comment = target.name
265*6dbdd20aSAndroid Build Coastguard Worker    label.srcs += (self.python_label_to_path(x) for x in target.sources)
266*6dbdd20aSAndroid Build Coastguard Worker    label.data += (self.python_data_to_path(x) for x in target.data)
267*6dbdd20aSAndroid Build Coastguard Worker    self.populate_python_deps(target, label)
268*6dbdd20aSAndroid Build Coastguard Worker    if target.name in public_python_targets:
269*6dbdd20aSAndroid Build Coastguard Worker      label.visibility = ['//visibility:public']
270*6dbdd20aSAndroid Build Coastguard Worker    if target.name in avoid_dep_targets:
271*6dbdd20aSAndroid Build Coastguard Worker      label.tags += ['avoid_dep']
272*6dbdd20aSAndroid Build Coastguard Worker    return [label]
273*6dbdd20aSAndroid Build Coastguard Worker
274*6dbdd20aSAndroid Build Coastguard Worker  def gen_python_binary(self, target: GnParser.Target):
275*6dbdd20aSAndroid Build Coastguard Worker    """Creates a Bazel target for a Python binary GN target."""
276*6dbdd20aSAndroid Build Coastguard Worker    label = BazelLabel(
277*6dbdd20aSAndroid Build Coastguard Worker        get_bazel_python_label_name(target.name), 'perfetto_py_binary')
278*6dbdd20aSAndroid Build Coastguard Worker    label.comment = target.name
279*6dbdd20aSAndroid Build Coastguard Worker    label.srcs += (self.python_label_to_path(x) for x in target.sources)
280*6dbdd20aSAndroid Build Coastguard Worker    label.data += (self.python_data_to_path(x) for x in target.data)
281*6dbdd20aSAndroid Build Coastguard Worker    label.main = target.python_main
282*6dbdd20aSAndroid Build Coastguard Worker    label.python_version = 'PY3'
283*6dbdd20aSAndroid Build Coastguard Worker    if target.name in public_python_targets:
284*6dbdd20aSAndroid Build Coastguard Worker      label.visibility = ['//visibility:public']
285*6dbdd20aSAndroid Build Coastguard Worker
286*6dbdd20aSAndroid Build Coastguard Worker    self.populate_python_deps(target, label)
287*6dbdd20aSAndroid Build Coastguard Worker    return [label]
288*6dbdd20aSAndroid Build Coastguard Worker
289*6dbdd20aSAndroid Build Coastguard Worker  def gen_target(self, gn_target: GnParser.Target):
290*6dbdd20aSAndroid Build Coastguard Worker    """Creates a Bazel target for a Python GN target."""
291*6dbdd20aSAndroid Build Coastguard Worker    assert (gn_target.type == 'action')
292*6dbdd20aSAndroid Build Coastguard Worker    if gn_target.name in external_python_deps:
293*6dbdd20aSAndroid Build Coastguard Worker      return []
294*6dbdd20aSAndroid Build Coastguard Worker    if gn_target.custom_action_type == 'python_library':
295*6dbdd20aSAndroid Build Coastguard Worker      return self.gen_python_library(gn_target)
296*6dbdd20aSAndroid Build Coastguard Worker    if gn_target.custom_action_type == 'python_binary':
297*6dbdd20aSAndroid Build Coastguard Worker      return self.gen_python_binary(gn_target)
298*6dbdd20aSAndroid Build Coastguard Worker    assert (False)
299*6dbdd20aSAndroid Build Coastguard Worker
300*6dbdd20aSAndroid Build Coastguard Worker  def gen_target_str(self, gn_target: GnParser.Target):
301*6dbdd20aSAndroid Build Coastguard Worker    """Creates a Bazel target string for a Python GN target."""
302*6dbdd20aSAndroid Build Coastguard Worker    return ''.join(str(x) for x in self.gen_target(gn_target))
303*6dbdd20aSAndroid Build Coastguard Worker
304*6dbdd20aSAndroid Build Coastguard Worker  def generate(self, gn_desc):
305*6dbdd20aSAndroid Build Coastguard Worker    """Creates a Python BUILD file for the GN description."""
306*6dbdd20aSAndroid Build Coastguard Worker    gn = gn_utils.GnParser(gn_desc)
307*6dbdd20aSAndroid Build Coastguard Worker    project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
308*6dbdd20aSAndroid Build Coastguard Worker    tool_name = os.path.relpath(os.path.abspath(__file__), project_root)
309*6dbdd20aSAndroid Build Coastguard Worker    tool_name = tool_name.replace('\\', '/')
310*6dbdd20aSAndroid Build Coastguard Worker    res = '''
311*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project
312*6dbdd20aSAndroid Build Coastguard Worker#
313*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
314*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
315*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
316*6dbdd20aSAndroid Build Coastguard Worker#
317*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
318*6dbdd20aSAndroid Build Coastguard Worker#
319*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
320*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
321*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
322*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
323*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
324*6dbdd20aSAndroid Build Coastguard Worker#
325*6dbdd20aSAndroid Build Coastguard Worker# This file is automatically generated by {}. Do not edit.
326*6dbdd20aSAndroid Build Coastguard Worker
327*6dbdd20aSAndroid Build Coastguard Workerload("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
328*6dbdd20aSAndroid Build Coastguard Workerload(
329*6dbdd20aSAndroid Build Coastguard Worker    "@perfetto//bazel:rules.bzl",
330*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_py_binary",
331*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_py_library",
332*6dbdd20aSAndroid Build Coastguard Worker)
333*6dbdd20aSAndroid Build Coastguard Worker
334*6dbdd20aSAndroid Build Coastguard Workerlicenses(["notice"])
335*6dbdd20aSAndroid Build Coastguard Worker
336*6dbdd20aSAndroid Build Coastguard Workerpackage(default_visibility = [PERFETTO_CONFIG.root + ":__subpackages__"])
337*6dbdd20aSAndroid Build Coastguard Worker
338*6dbdd20aSAndroid Build Coastguard Worker'''.format(tool_name).lstrip()
339*6dbdd20aSAndroid Build Coastguard Worker
340*6dbdd20aSAndroid Build Coastguard Worker    # Find all the targets in the //python folder.
341*6dbdd20aSAndroid Build Coastguard Worker    for target_name in default_python_targets:
342*6dbdd20aSAndroid Build Coastguard Worker      target = gn.get_target(target_name)
343*6dbdd20aSAndroid Build Coastguard Worker      res += self.gen_target_str(target)
344*6dbdd20aSAndroid Build Coastguard Worker
345*6dbdd20aSAndroid Build Coastguard Worker    # Generate all the intermediate targets.
346*6dbdd20aSAndroid Build Coastguard Worker    for target in sorted(itervalues(gn.all_targets)):
347*6dbdd20aSAndroid Build Coastguard Worker      if target.name in default_python_targets:
348*6dbdd20aSAndroid Build Coastguard Worker        continue
349*6dbdd20aSAndroid Build Coastguard Worker      res += self.gen_target_str(target)
350*6dbdd20aSAndroid Build Coastguard Worker
351*6dbdd20aSAndroid Build Coastguard Worker    return res
352*6dbdd20aSAndroid Build Coastguard Worker
353*6dbdd20aSAndroid Build Coastguard Worker
354*6dbdd20aSAndroid Build Coastguard Workerclass Error(Exception):
355*6dbdd20aSAndroid Build Coastguard Worker  pass
356*6dbdd20aSAndroid Build Coastguard Worker
357*6dbdd20aSAndroid Build Coastguard Worker
358*6dbdd20aSAndroid Build Coastguard Workerclass BazelLabel(object):
359*6dbdd20aSAndroid Build Coastguard Worker
360*6dbdd20aSAndroid Build Coastguard Worker  def __init__(self, name, type):
361*6dbdd20aSAndroid Build Coastguard Worker    self.comment: Optional[str] = None
362*6dbdd20aSAndroid Build Coastguard Worker    self.name = name
363*6dbdd20aSAndroid Build Coastguard Worker    self.type = type
364*6dbdd20aSAndroid Build Coastguard Worker    self.visibility: Union[List[str], str] = []
365*6dbdd20aSAndroid Build Coastguard Worker    self.srcs: Union[List[str], str] = []
366*6dbdd20aSAndroid Build Coastguard Worker    self.win_srcs: Union[List[str], str] = None
367*6dbdd20aSAndroid Build Coastguard Worker    self.hdrs = []
368*6dbdd20aSAndroid Build Coastguard Worker    self.defines = []
369*6dbdd20aSAndroid Build Coastguard Worker    self.data = []
370*6dbdd20aSAndroid Build Coastguard Worker    self.deps = []
371*6dbdd20aSAndroid Build Coastguard Worker    self.external_deps = []
372*6dbdd20aSAndroid Build Coastguard Worker    self.tools = []
373*6dbdd20aSAndroid Build Coastguard Worker    self.outs = []
374*6dbdd20aSAndroid Build Coastguard Worker    self.exports = []
375*6dbdd20aSAndroid Build Coastguard Worker    self.main = None
376*6dbdd20aSAndroid Build Coastguard Worker    self.cmd: Optional[str] = None
377*6dbdd20aSAndroid Build Coastguard Worker    self.python_version: Optional[str] = None
378*6dbdd20aSAndroid Build Coastguard Worker    self.root_dir: Optional[str] = None
379*6dbdd20aSAndroid Build Coastguard Worker    self.namespace: Optional[str] = None
380*6dbdd20aSAndroid Build Coastguard Worker    self.tags: List[str] = []
381*6dbdd20aSAndroid Build Coastguard Worker
382*6dbdd20aSAndroid Build Coastguard Worker  def __lt__(self, other):
383*6dbdd20aSAndroid Build Coastguard Worker    if isinstance(other, self.__class__):
384*6dbdd20aSAndroid Build Coastguard Worker      return self.name < other.name
385*6dbdd20aSAndroid Build Coastguard Worker    raise TypeError(
386*6dbdd20aSAndroid Build Coastguard Worker        '\'<\' not supported between instances of \'%s\' and \'%s\'' %
387*6dbdd20aSAndroid Build Coastguard Worker        (type(self).__name__, type(other).__name__))
388*6dbdd20aSAndroid Build Coastguard Worker
389*6dbdd20aSAndroid Build Coastguard Worker  def __str__(self):
390*6dbdd20aSAndroid Build Coastguard Worker    """Converts the object into a Bazel Starlark label."""
391*6dbdd20aSAndroid Build Coastguard Worker    res = ''
392*6dbdd20aSAndroid Build Coastguard Worker    res += ('# GN target: %s\n' % self.comment) if self.comment else ''
393*6dbdd20aSAndroid Build Coastguard Worker    res += '%s(\n' % self.type
394*6dbdd20aSAndroid Build Coastguard Worker    any_deps = len(self.deps) + len(self.external_deps) > 0
395*6dbdd20aSAndroid Build Coastguard Worker    ORD = [
396*6dbdd20aSAndroid Build Coastguard Worker        'name', 'srcs', 'hdrs', 'defines', 'visibility', 'data', 'deps', 'outs',
397*6dbdd20aSAndroid Build Coastguard Worker        'cmd', 'tools', 'exports', 'main', 'python_version'
398*6dbdd20aSAndroid Build Coastguard Worker    ]
399*6dbdd20aSAndroid Build Coastguard Worker    hasher = lambda x: sum((99,) + tuple(ord(c) for c in x))
400*6dbdd20aSAndroid Build Coastguard Worker    key_sorter = lambda kv: ORD.index(kv[0]) if kv[0] in ORD else hasher(kv[0])
401*6dbdd20aSAndroid Build Coastguard Worker    for k, v in sorted(iteritems(self.__dict__), key=key_sorter):
402*6dbdd20aSAndroid Build Coastguard Worker      if k in ('type', 'comment',
403*6dbdd20aSAndroid Build Coastguard Worker               'external_deps', 'win_srcs') or v is None or (v == [] and
404*6dbdd20aSAndroid Build Coastguard Worker                                                 (k != 'deps' or not any_deps)):
405*6dbdd20aSAndroid Build Coastguard Worker        continue
406*6dbdd20aSAndroid Build Coastguard Worker      res += '    %s = ' % k
407*6dbdd20aSAndroid Build Coastguard Worker      if isinstance(v, basestring):
408*6dbdd20aSAndroid Build Coastguard Worker        if v.startswith('PERFETTO_CONFIG.') or v.startswith('glob'):
409*6dbdd20aSAndroid Build Coastguard Worker          res += '%s,\n' % v
410*6dbdd20aSAndroid Build Coastguard Worker        else:
411*6dbdd20aSAndroid Build Coastguard Worker          res += '"%s",\n' % v
412*6dbdd20aSAndroid Build Coastguard Worker      elif isinstance(v, bool):
413*6dbdd20aSAndroid Build Coastguard Worker        res += '%s,\n' % v
414*6dbdd20aSAndroid Build Coastguard Worker      elif isinstance(v, list):
415*6dbdd20aSAndroid Build Coastguard Worker        res += '[\n'
416*6dbdd20aSAndroid Build Coastguard Worker        if k == 'deps' and len(self.external_deps) > 1:
417*6dbdd20aSAndroid Build Coastguard Worker          indent = '           '
418*6dbdd20aSAndroid Build Coastguard Worker        else:
419*6dbdd20aSAndroid Build Coastguard Worker          indent = '    '
420*6dbdd20aSAndroid Build Coastguard Worker
421*6dbdd20aSAndroid Build Coastguard Worker        non_win_srcs = {}
422*6dbdd20aSAndroid Build Coastguard Worker        if k == "srcs" and self.win_srcs is not None:
423*6dbdd20aSAndroid Build Coastguard Worker          non_win_srcs = sorted(set(self.srcs) - set(self.win_srcs))
424*6dbdd20aSAndroid Build Coastguard Worker
425*6dbdd20aSAndroid Build Coastguard Worker        for entry in sorted(v):
426*6dbdd20aSAndroid Build Coastguard Worker          if entry in non_win_srcs:
427*6dbdd20aSAndroid Build Coastguard Worker            continue
428*6dbdd20aSAndroid Build Coastguard Worker          if entry.startswith('PERFETTO_CONFIG.'):
429*6dbdd20aSAndroid Build Coastguard Worker            res += '%s    %s,\n' % (indent, entry)
430*6dbdd20aSAndroid Build Coastguard Worker          else:
431*6dbdd20aSAndroid Build Coastguard Worker            res += '%s    "%s",\n' % (indent, entry)
432*6dbdd20aSAndroid Build Coastguard Worker        if non_win_srcs:
433*6dbdd20aSAndroid Build Coastguard Worker          res += '    ] + select({\n'
434*6dbdd20aSAndroid Build Coastguard Worker          res += '        "@platforms//os:windows": [],\n'
435*6dbdd20aSAndroid Build Coastguard Worker          res += '        "//conditions:default": [\n'
436*6dbdd20aSAndroid Build Coastguard Worker          for win_src in non_win_srcs:
437*6dbdd20aSAndroid Build Coastguard Worker            res += '            "%s",\n' % win_src
438*6dbdd20aSAndroid Build Coastguard Worker          res += '        ],\n'
439*6dbdd20aSAndroid Build Coastguard Worker          res += '    }),\n'
440*6dbdd20aSAndroid Build Coastguard Worker        else:
441*6dbdd20aSAndroid Build Coastguard Worker          res += '%s]' % indent
442*6dbdd20aSAndroid Build Coastguard Worker          if k == 'deps' and self.external_deps:
443*6dbdd20aSAndroid Build Coastguard Worker            res += ' + %s' % self.external_deps[0]
444*6dbdd20aSAndroid Build Coastguard Worker            for edep in self.external_deps[1:]:
445*6dbdd20aSAndroid Build Coastguard Worker              if isinstance(edep, list):
446*6dbdd20aSAndroid Build Coastguard Worker                res += ' + [\n'
447*6dbdd20aSAndroid Build Coastguard Worker                for inner_dep in edep:
448*6dbdd20aSAndroid Build Coastguard Worker                  res += '        "%s",\n' % inner_dep
449*6dbdd20aSAndroid Build Coastguard Worker                res += '    ]'
450*6dbdd20aSAndroid Build Coastguard Worker              else:
451*6dbdd20aSAndroid Build Coastguard Worker                res += ' +\n%s%s' % (indent, edep)
452*6dbdd20aSAndroid Build Coastguard Worker          res += ',\n'
453*6dbdd20aSAndroid Build Coastguard Worker      else:
454*6dbdd20aSAndroid Build Coastguard Worker        raise Error('Unsupported value %s', type(v))
455*6dbdd20aSAndroid Build Coastguard Worker    res += ')\n\n'
456*6dbdd20aSAndroid Build Coastguard Worker    return res
457*6dbdd20aSAndroid Build Coastguard Worker
458*6dbdd20aSAndroid Build Coastguard Worker
459*6dbdd20aSAndroid Build Coastguard Workerdef get_bazel_label_name(gn_name: str):
460*6dbdd20aSAndroid Build Coastguard Worker  """Converts a GN target name into a Bazel label name.
461*6dbdd20aSAndroid Build Coastguard Worker
462*6dbdd20aSAndroid Build Coastguard Worker  If target is in the public target list, returns only the GN target name,
463*6dbdd20aSAndroid Build Coastguard Worker  e.g.: //src/ipc:perfetto_ipc -> perfetto_ipc
464*6dbdd20aSAndroid Build Coastguard Worker
465*6dbdd20aSAndroid Build Coastguard Worker  Otherwise, in the case of an intermediate target, returns a mangled path.
466*6dbdd20aSAndroid Build Coastguard Worker  e.g.:  //include/perfetto/base:base -> include_perfetto_base_base.
467*6dbdd20aSAndroid Build Coastguard Worker  """
468*6dbdd20aSAndroid Build Coastguard Worker  if gn_name in default_targets:
469*6dbdd20aSAndroid Build Coastguard Worker    return gn_utils.label_without_toolchain(gn_name).split(':')[1]
470*6dbdd20aSAndroid Build Coastguard Worker  return gn_utils.label_to_target_name_with_path(gn_name)
471*6dbdd20aSAndroid Build Coastguard Worker
472*6dbdd20aSAndroid Build Coastguard Worker
473*6dbdd20aSAndroid Build Coastguard Workerdef get_bazel_python_label_name(gn_name: str):
474*6dbdd20aSAndroid Build Coastguard Worker  """Converts a Python GN label into a Bazel label."""
475*6dbdd20aSAndroid Build Coastguard Worker  name = re.sub(r'^//python:?', '', gn_name)
476*6dbdd20aSAndroid Build Coastguard Worker  return gn_utils.label_to_target_name_with_path(name)
477*6dbdd20aSAndroid Build Coastguard Worker
478*6dbdd20aSAndroid Build Coastguard Worker
479*6dbdd20aSAndroid Build Coastguard Workerdef get_bazel_proto_sources_label(target_name: str):
480*6dbdd20aSAndroid Build Coastguard Worker  """Converts a GN target name into a Bazel proto label name."""
481*6dbdd20aSAndroid Build Coastguard Worker  return re.sub('_(lite|zero|cpp|ipc|source_set|descriptor)$', '',
482*6dbdd20aSAndroid Build Coastguard Worker                get_bazel_label_name(target_name)) + '_protos'
483*6dbdd20aSAndroid Build Coastguard Worker
484*6dbdd20aSAndroid Build Coastguard Worker
485*6dbdd20aSAndroid Build Coastguard Workerdef gen_proto_label(target: GnParser.Target):
486*6dbdd20aSAndroid Build Coastguard Worker  """ Generates the xx_proto_library label for proto targets."""
487*6dbdd20aSAndroid Build Coastguard Worker  assert (target.type == 'proto_library')
488*6dbdd20aSAndroid Build Coastguard Worker
489*6dbdd20aSAndroid Build Coastguard Worker  sources_label_name = get_bazel_proto_sources_label(target.name)
490*6dbdd20aSAndroid Build Coastguard Worker
491*6dbdd20aSAndroid Build Coastguard Worker  # For 'source_set' plugins, we don't want to generate any plugin-dependent
492*6dbdd20aSAndroid Build Coastguard Worker  # targets so just return the label of the proto sources only.
493*6dbdd20aSAndroid Build Coastguard Worker  if target.proto_plugin == 'source_set':
494*6dbdd20aSAndroid Build Coastguard Worker    sources_label = BazelLabel(sources_label_name, 'perfetto_proto_library')
495*6dbdd20aSAndroid Build Coastguard Worker    sources_label.comment = target.name
496*6dbdd20aSAndroid Build Coastguard Worker    assert (all(x.startswith('//') for x in target.sources))
497*6dbdd20aSAndroid Build Coastguard Worker    assert (all(x.endswith('.proto') for x in target.sources))
498*6dbdd20aSAndroid Build Coastguard Worker    sources_label.srcs = sorted([x[2:] for x in target.sources])  # Strip //.
499*6dbdd20aSAndroid Build Coastguard Worker    sources_label.deps = sorted([
500*6dbdd20aSAndroid Build Coastguard Worker        ':' + get_bazel_proto_sources_label(x.name)
501*6dbdd20aSAndroid Build Coastguard Worker        for x in target.transitive_proto_deps()
502*6dbdd20aSAndroid Build Coastguard Worker    ])
503*6dbdd20aSAndroid Build Coastguard Worker
504*6dbdd20aSAndroid Build Coastguard Worker    # In Bazel, proto_paths are not a supported concept becauase strong
505*6dbdd20aSAndroid Build Coastguard Worker    # dependency checking is enabled. Instead, we need to depend on the target
506*6dbdd20aSAndroid Build Coastguard Worker    # which includes the proto we want to depend on.
507*6dbdd20aSAndroid Build Coastguard Worker    # For example, we include the proto_path |buildtools_protobuf_src| because
508*6dbdd20aSAndroid Build Coastguard Worker    # we want to depend on the "google/protobuf/descriptor.proto" proto file.
509*6dbdd20aSAndroid Build Coastguard Worker    # This will be exposed by the |protobuf_descriptor_proto| dep.
510*6dbdd20aSAndroid Build Coastguard Worker    if buildtools_protobuf_src in target.proto_paths:
511*6dbdd20aSAndroid Build Coastguard Worker      sources_label.external_deps = [
512*6dbdd20aSAndroid Build Coastguard Worker          'PERFETTO_CONFIG.deps.protobuf_descriptor_proto'
513*6dbdd20aSAndroid Build Coastguard Worker      ]
514*6dbdd20aSAndroid Build Coastguard Worker
515*6dbdd20aSAndroid Build Coastguard Worker    sources_label.visibility = ['PERFETTO_CONFIG.proto_library_visibility']
516*6dbdd20aSAndroid Build Coastguard Worker
517*6dbdd20aSAndroid Build Coastguard Worker    sources_label.exports = sorted(
518*6dbdd20aSAndroid Build Coastguard Worker        [':' + get_bazel_proto_sources_label(d) for d in target.proto_exports])
519*6dbdd20aSAndroid Build Coastguard Worker    return sources_label
520*6dbdd20aSAndroid Build Coastguard Worker
521*6dbdd20aSAndroid Build Coastguard Worker  # For all other types of plugins, we need to generate
522*6dbdd20aSAndroid Build Coastguard Worker  if target.proto_plugin == 'proto':
523*6dbdd20aSAndroid Build Coastguard Worker    plugin_label_type = 'perfetto_cc_proto_library'
524*6dbdd20aSAndroid Build Coastguard Worker  elif target.proto_plugin == 'protozero':
525*6dbdd20aSAndroid Build Coastguard Worker    plugin_label_type = 'perfetto_cc_protozero_library'
526*6dbdd20aSAndroid Build Coastguard Worker  elif target.proto_plugin == 'cppgen':
527*6dbdd20aSAndroid Build Coastguard Worker    plugin_label_type = 'perfetto_cc_protocpp_library'
528*6dbdd20aSAndroid Build Coastguard Worker  elif target.proto_plugin == 'ipc':
529*6dbdd20aSAndroid Build Coastguard Worker    plugin_label_type = 'perfetto_cc_ipc_library'
530*6dbdd20aSAndroid Build Coastguard Worker  elif target.proto_plugin == 'descriptor':
531*6dbdd20aSAndroid Build Coastguard Worker    plugin_label_type = 'perfetto_proto_descriptor'
532*6dbdd20aSAndroid Build Coastguard Worker  else:
533*6dbdd20aSAndroid Build Coastguard Worker    raise Error('Unknown proto plugin: %s' % target.proto_plugin)
534*6dbdd20aSAndroid Build Coastguard Worker  plugin_label_name = get_bazel_label_name(target.name)
535*6dbdd20aSAndroid Build Coastguard Worker  plugin_label = BazelLabel(plugin_label_name, plugin_label_type)
536*6dbdd20aSAndroid Build Coastguard Worker  plugin_label.comment = target.name
537*6dbdd20aSAndroid Build Coastguard Worker
538*6dbdd20aSAndroid Build Coastguard Worker  # When using the plugins we need to pass down also the transitive deps.
539*6dbdd20aSAndroid Build Coastguard Worker  # For instance consider foo.proto including common.proto. The generated
540*6dbdd20aSAndroid Build Coastguard Worker  # foo.cc will #include "common.gen.h". Hence the generated cc_protocpp_library
541*6dbdd20aSAndroid Build Coastguard Worker  # rule need to pass down the dependency on the target that generates
542*6dbdd20aSAndroid Build Coastguard Worker  # common.gen.{cc,h}.
543*6dbdd20aSAndroid Build Coastguard Worker  if target.proto_plugin in ('cppgen', 'ipc', 'protozero'):
544*6dbdd20aSAndroid Build Coastguard Worker    plugin_label.deps += [
545*6dbdd20aSAndroid Build Coastguard Worker        ':' + get_bazel_label_name(x.name)
546*6dbdd20aSAndroid Build Coastguard Worker        for x in target.transitive_proto_deps()
547*6dbdd20aSAndroid Build Coastguard Worker    ]
548*6dbdd20aSAndroid Build Coastguard Worker
549*6dbdd20aSAndroid Build Coastguard Worker  # Add any dependencies on source_set targets (i.e. targets containing proto
550*6dbdd20aSAndroid Build Coastguard Worker  # files). For descriptors, we will have an explicit edge between the
551*6dbdd20aSAndroid Build Coastguard Worker  # descriptor and source set wheras for other plugin types, this edge is
552*6dbdd20aSAndroid Build Coastguard Worker  # implicit.
553*6dbdd20aSAndroid Build Coastguard Worker  if target.proto_plugin == 'descriptor':
554*6dbdd20aSAndroid Build Coastguard Worker    plugin_label.deps += [
555*6dbdd20aSAndroid Build Coastguard Worker        ':' + get_bazel_proto_sources_label(x.name)
556*6dbdd20aSAndroid Build Coastguard Worker        for x in target.proto_deps()
557*6dbdd20aSAndroid Build Coastguard Worker    ]
558*6dbdd20aSAndroid Build Coastguard Worker  else:
559*6dbdd20aSAndroid Build Coastguard Worker    plugin_label.deps += [':' + sources_label_name]
560*6dbdd20aSAndroid Build Coastguard Worker
561*6dbdd20aSAndroid Build Coastguard Worker  # Since the descriptor generates an explicit output file which can be
562*6dbdd20aSAndroid Build Coastguard Worker  # referenced by other targets, we specify a name for it.
563*6dbdd20aSAndroid Build Coastguard Worker  if target.proto_plugin == 'descriptor':
564*6dbdd20aSAndroid Build Coastguard Worker    plugin_label.outs = [plugin_label_name + '.bin']
565*6dbdd20aSAndroid Build Coastguard Worker
566*6dbdd20aSAndroid Build Coastguard Worker  return plugin_label
567*6dbdd20aSAndroid Build Coastguard Worker
568*6dbdd20aSAndroid Build Coastguard Worker
569*6dbdd20aSAndroid Build Coastguard Workerdef gen_proto_group_target(gn: GnParser, name: str, desc: Dict[str, Any]):
570*6dbdd20aSAndroid Build Coastguard Worker  # Get a recursive list of the proto_library targets rooted here which
571*6dbdd20aSAndroid Build Coastguard Worker  # have src.
572*6dbdd20aSAndroid Build Coastguard Worker  deps_set = set(desc['sources'])
573*6dbdd20aSAndroid Build Coastguard Worker  for target_name in desc['sources']:
574*6dbdd20aSAndroid Build Coastguard Worker    target = gn.get_target(target_name)
575*6dbdd20aSAndroid Build Coastguard Worker    deps_set.update(d.name for d in target.transitive_proto_deps())
576*6dbdd20aSAndroid Build Coastguard Worker
577*6dbdd20aSAndroid Build Coastguard Worker  # First, create a root source set target which references all the child
578*6dbdd20aSAndroid Build Coastguard Worker  # source set targets. We publish this as well as depending on this in all
579*6dbdd20aSAndroid Build Coastguard Worker  # subsequent targets.
580*6dbdd20aSAndroid Build Coastguard Worker  sources_label = BazelLabel(name + '_proto', 'perfetto_proto_library')
581*6dbdd20aSAndroid Build Coastguard Worker  sources_label.deps = [
582*6dbdd20aSAndroid Build Coastguard Worker      ':' + get_bazel_proto_sources_label(name)
583*6dbdd20aSAndroid Build Coastguard Worker      for name in sorted(list(deps_set))
584*6dbdd20aSAndroid Build Coastguard Worker  ]
585*6dbdd20aSAndroid Build Coastguard Worker  sources_label.comment = f'''[{', '.join(desc['sources'])}]'''
586*6dbdd20aSAndroid Build Coastguard Worker
587*6dbdd20aSAndroid Build Coastguard Worker  cc_label = BazelLabel(name + '_cc_proto', 'perfetto_cc_proto_library')
588*6dbdd20aSAndroid Build Coastguard Worker  cc_label.deps = [':' + sources_label.name]
589*6dbdd20aSAndroid Build Coastguard Worker  cc_label.comment = sources_label.comment
590*6dbdd20aSAndroid Build Coastguard Worker
591*6dbdd20aSAndroid Build Coastguard Worker  java_label = BazelLabel(name + '_java_proto', 'perfetto_java_proto_library')
592*6dbdd20aSAndroid Build Coastguard Worker  java_label.deps = [':' + sources_label.name]
593*6dbdd20aSAndroid Build Coastguard Worker  java_label.comment = sources_label.comment
594*6dbdd20aSAndroid Build Coastguard Worker
595*6dbdd20aSAndroid Build Coastguard Worker  lite_name = name + '_java_proto_lite'
596*6dbdd20aSAndroid Build Coastguard Worker  java_lite_label = BazelLabel(lite_name, 'perfetto_java_lite_proto_library')
597*6dbdd20aSAndroid Build Coastguard Worker  java_lite_label.deps = [':' + sources_label.name]
598*6dbdd20aSAndroid Build Coastguard Worker  java_lite_label.comment = sources_label.comment
599*6dbdd20aSAndroid Build Coastguard Worker
600*6dbdd20aSAndroid Build Coastguard Worker  py_label = BazelLabel(name + '_py_pb2', 'perfetto_py_proto_library')
601*6dbdd20aSAndroid Build Coastguard Worker  py_label.deps = [':' + sources_label.name]
602*6dbdd20aSAndroid Build Coastguard Worker  py_label.comment = sources_label.comment
603*6dbdd20aSAndroid Build Coastguard Worker
604*6dbdd20aSAndroid Build Coastguard Worker  visibility = desc['visibility']
605*6dbdd20aSAndroid Build Coastguard Worker  if visibility:
606*6dbdd20aSAndroid Build Coastguard Worker    sources_label.visibility = visibility
607*6dbdd20aSAndroid Build Coastguard Worker    cc_label.visibility = visibility
608*6dbdd20aSAndroid Build Coastguard Worker    java_label.visibility = visibility
609*6dbdd20aSAndroid Build Coastguard Worker    java_lite_label.visibility = visibility
610*6dbdd20aSAndroid Build Coastguard Worker    py_label.visibility = visibility
611*6dbdd20aSAndroid Build Coastguard Worker
612*6dbdd20aSAndroid Build Coastguard Worker  return [sources_label, cc_label, java_label, java_lite_label, py_label]
613*6dbdd20aSAndroid Build Coastguard Worker
614*6dbdd20aSAndroid Build Coastguard Worker
615*6dbdd20aSAndroid Build Coastguard Workerdef gen_cc_proto_descriptor(target: GnParser.Target):
616*6dbdd20aSAndroid Build Coastguard Worker  label = BazelLabel(
617*6dbdd20aSAndroid Build Coastguard Worker      get_bazel_label_name(target.name), 'perfetto_cc_proto_descriptor')
618*6dbdd20aSAndroid Build Coastguard Worker  label.comment = target.name
619*6dbdd20aSAndroid Build Coastguard Worker  label.deps += [
620*6dbdd20aSAndroid Build Coastguard Worker      ':' + get_bazel_label_name(x.name) for x in target.proto_deps()
621*6dbdd20aSAndroid Build Coastguard Worker  ]
622*6dbdd20aSAndroid Build Coastguard Worker  label.deps += [
623*6dbdd20aSAndroid Build Coastguard Worker      gn_utils.label_to_path(src)
624*6dbdd20aSAndroid Build Coastguard Worker      for src in target.inputs
625*6dbdd20aSAndroid Build Coastguard Worker      if "tmp.gn_utils" not in src
626*6dbdd20aSAndroid Build Coastguard Worker  ]
627*6dbdd20aSAndroid Build Coastguard Worker
628*6dbdd20aSAndroid Build Coastguard Worker  label.outs += target.outputs
629*6dbdd20aSAndroid Build Coastguard Worker  return [label]
630*6dbdd20aSAndroid Build Coastguard Worker
631*6dbdd20aSAndroid Build Coastguard Worker
632*6dbdd20aSAndroid Build Coastguard Workerdef gen_cc_amalgamated_sql(target: GnParser.Target):
633*6dbdd20aSAndroid Build Coastguard Worker  label = BazelLabel(
634*6dbdd20aSAndroid Build Coastguard Worker      get_bazel_label_name(target.name), 'perfetto_cc_amalgamated_sql')
635*6dbdd20aSAndroid Build Coastguard Worker
636*6dbdd20aSAndroid Build Coastguard Worker  def find_arg(name):
637*6dbdd20aSAndroid Build Coastguard Worker    for i, arg in enumerate(target.args):
638*6dbdd20aSAndroid Build Coastguard Worker      if arg.startswith(f'--{name}'):
639*6dbdd20aSAndroid Build Coastguard Worker        return target.args[i + 1]
640*6dbdd20aSAndroid Build Coastguard Worker
641*6dbdd20aSAndroid Build Coastguard Worker  label.comment = target.name
642*6dbdd20aSAndroid Build Coastguard Worker  label.namespace = find_arg('namespace')
643*6dbdd20aSAndroid Build Coastguard Worker
644*6dbdd20aSAndroid Build Coastguard Worker  label.deps += sorted(
645*6dbdd20aSAndroid Build Coastguard Worker      ':' + get_bazel_label_name(x.name) for x in target.transitive_deps)
646*6dbdd20aSAndroid Build Coastguard Worker  label.outs += target.outputs
647*6dbdd20aSAndroid Build Coastguard Worker  return [label]
648*6dbdd20aSAndroid Build Coastguard Worker
649*6dbdd20aSAndroid Build Coastguard Worker
650*6dbdd20aSAndroid Build Coastguard Workerdef gen_sql_source_set(target: GnParser.Target):
651*6dbdd20aSAndroid Build Coastguard Worker  label = BazelLabel(get_bazel_label_name(target.name), 'perfetto_filegroup')
652*6dbdd20aSAndroid Build Coastguard Worker  label.comment = target.name
653*6dbdd20aSAndroid Build Coastguard Worker  label.srcs += (gn_utils.label_to_path(x) for x in target.inputs)
654*6dbdd20aSAndroid Build Coastguard Worker  return [label]
655*6dbdd20aSAndroid Build Coastguard Worker
656*6dbdd20aSAndroid Build Coastguard Worker
657*6dbdd20aSAndroid Build Coastguard Workerdef gen_cc_tp_tables(target: GnParser.Target):
658*6dbdd20aSAndroid Build Coastguard Worker  label = BazelLabel(get_bazel_label_name(target.name), 'perfetto_cc_tp_tables')
659*6dbdd20aSAndroid Build Coastguard Worker  label.comment = target.name
660*6dbdd20aSAndroid Build Coastguard Worker  label.srcs += (gn_utils.label_to_path(x) for x in target.sources)
661*6dbdd20aSAndroid Build Coastguard Worker  label.deps += sorted(':' + get_bazel_label_name(x.name)
662*6dbdd20aSAndroid Build Coastguard Worker                       for x in target.transitive_deps
663*6dbdd20aSAndroid Build Coastguard Worker                       if x.name not in default_python_targets)
664*6dbdd20aSAndroid Build Coastguard Worker  label.outs += target.outputs
665*6dbdd20aSAndroid Build Coastguard Worker  return [label]
666*6dbdd20aSAndroid Build Coastguard Worker
667*6dbdd20aSAndroid Build Coastguard Worker
668*6dbdd20aSAndroid Build Coastguard Workerdef gen_target_helper(gn_target: GnParser.Target, win_target: GnParser.Target = None):
669*6dbdd20aSAndroid Build Coastguard Worker  if gn_target.type == 'proto_library':
670*6dbdd20aSAndroid Build Coastguard Worker    return [gen_proto_label(gn_target)]
671*6dbdd20aSAndroid Build Coastguard Worker  elif gn_target.type == 'action':
672*6dbdd20aSAndroid Build Coastguard Worker    if gn_target.name in custom_actions:
673*6dbdd20aSAndroid Build Coastguard Worker      return custom_actions[gn_target.name](gn_target)
674*6dbdd20aSAndroid Build Coastguard Worker    if gn_target.custom_action_type == 'sql_amalgamation':
675*6dbdd20aSAndroid Build Coastguard Worker      return gen_cc_amalgamated_sql(gn_target)
676*6dbdd20aSAndroid Build Coastguard Worker    if gn_target.custom_action_type == 'sql_source_set':
677*6dbdd20aSAndroid Build Coastguard Worker      return gen_sql_source_set(gn_target)
678*6dbdd20aSAndroid Build Coastguard Worker    if gn_target.custom_action_type == 'cc_proto_descriptor':
679*6dbdd20aSAndroid Build Coastguard Worker      return gen_cc_proto_descriptor(gn_target)
680*6dbdd20aSAndroid Build Coastguard Worker    if gn_target.custom_action_type == 'tp_tables':
681*6dbdd20aSAndroid Build Coastguard Worker      return gen_cc_tp_tables(gn_target)
682*6dbdd20aSAndroid Build Coastguard Worker    return []
683*6dbdd20aSAndroid Build Coastguard Worker  elif gn_target.type == 'group':
684*6dbdd20aSAndroid Build Coastguard Worker    return []
685*6dbdd20aSAndroid Build Coastguard Worker  elif gn_target.type == 'executable':
686*6dbdd20aSAndroid Build Coastguard Worker    bazel_type = 'perfetto_cc_binary'
687*6dbdd20aSAndroid Build Coastguard Worker  elif gn_target.type == 'shared_library':
688*6dbdd20aSAndroid Build Coastguard Worker    bazel_type = 'perfetto_cc_library'
689*6dbdd20aSAndroid Build Coastguard Worker  elif gn_target.type == 'static_library':
690*6dbdd20aSAndroid Build Coastguard Worker    bazel_type = 'perfetto_cc_library'
691*6dbdd20aSAndroid Build Coastguard Worker  elif gn_target.type == 'source_set':
692*6dbdd20aSAndroid Build Coastguard Worker    bazel_type = 'perfetto_filegroup'
693*6dbdd20aSAndroid Build Coastguard Worker  elif gn_target.type == 'generated_file':
694*6dbdd20aSAndroid Build Coastguard Worker    return []
695*6dbdd20aSAndroid Build Coastguard Worker  else:
696*6dbdd20aSAndroid Build Coastguard Worker    raise Error('target type not supported: %s' % gn_target.type)
697*6dbdd20aSAndroid Build Coastguard Worker
698*6dbdd20aSAndroid Build Coastguard Worker  label = BazelLabel(get_bazel_label_name(gn_target.name), bazel_type)
699*6dbdd20aSAndroid Build Coastguard Worker  label.comment = gn_target.name
700*6dbdd20aSAndroid Build Coastguard Worker
701*6dbdd20aSAndroid Build Coastguard Worker  # Supporting 'public' on source_sets would require not converting them to
702*6dbdd20aSAndroid Build Coastguard Worker  # filegroups in bazel.
703*6dbdd20aSAndroid Build Coastguard Worker  if gn_target.public_headers:
704*6dbdd20aSAndroid Build Coastguard Worker    if bazel_type == 'perfetto_cc_library':
705*6dbdd20aSAndroid Build Coastguard Worker      label.hdrs += [x[2:] for x in gn_target.public_headers]
706*6dbdd20aSAndroid Build Coastguard Worker    else:
707*6dbdd20aSAndroid Build Coastguard Worker      raise Error('%s: \'public\' currently supported only for cc_library' %
708*6dbdd20aSAndroid Build Coastguard Worker                  gn_target.name)
709*6dbdd20aSAndroid Build Coastguard Worker
710*6dbdd20aSAndroid Build Coastguard Worker  raw_srcs = [x[2:] for x in gn_target.sources]
711*6dbdd20aSAndroid Build Coastguard Worker  raw_srcs += [x[2:] for x in gn_target.inputs]
712*6dbdd20aSAndroid Build Coastguard Worker  if bazel_type == 'perfetto_cc_library':
713*6dbdd20aSAndroid Build Coastguard Worker    label.srcs += [x for x in raw_srcs if not x.startswith('include')]
714*6dbdd20aSAndroid Build Coastguard Worker    label.hdrs += [x for x in raw_srcs if x.startswith('include')]
715*6dbdd20aSAndroid Build Coastguard Worker
716*6dbdd20aSAndroid Build Coastguard Worker    # Most Perfetto libraries cannot be dynamically linked as they would
717*6dbdd20aSAndroid Build Coastguard Worker    # cause ODR violations.
718*6dbdd20aSAndroid Build Coastguard Worker    label.__dict__['linkstatic'] = True
719*6dbdd20aSAndroid Build Coastguard Worker  else:
720*6dbdd20aSAndroid Build Coastguard Worker    label.srcs = raw_srcs
721*6dbdd20aSAndroid Build Coastguard Worker
722*6dbdd20aSAndroid Build Coastguard Worker  is_public = gn_target.name in public_targets
723*6dbdd20aSAndroid Build Coastguard Worker  is_public_for_allowlist = gn_target.name in allowlist_public_targets
724*6dbdd20aSAndroid Build Coastguard Worker  if is_public and is_public_for_allowlist:
725*6dbdd20aSAndroid Build Coastguard Worker    raise Error('Target %s in both public_targets and allowlist_public_targets', gn.target.name)
726*6dbdd20aSAndroid Build Coastguard Worker  elif is_public:
727*6dbdd20aSAndroid Build Coastguard Worker    label.visibility = ['//visibility:public']
728*6dbdd20aSAndroid Build Coastguard Worker  elif is_public_for_allowlist:
729*6dbdd20aSAndroid Build Coastguard Worker    label.visibility = ALLOWLIST_PUBLIC_VISIBILITY
730*6dbdd20aSAndroid Build Coastguard Worker
731*6dbdd20aSAndroid Build Coastguard Worker  if win_target:
732*6dbdd20aSAndroid Build Coastguard Worker    label.win_srcs = list(set(label.srcs) & {s[2:] for s in win_target.sources | win_target.inputs})
733*6dbdd20aSAndroid Build Coastguard Worker
734*6dbdd20aSAndroid Build Coastguard Worker  if gn_target.type in gn_utils.LINKER_UNIT_TYPES:
735*6dbdd20aSAndroid Build Coastguard Worker    # |source_sets| contains the transitive set of source_set deps.
736*6dbdd20aSAndroid Build Coastguard Worker    for trans_dep in gn_target.transitive_source_set_deps():
737*6dbdd20aSAndroid Build Coastguard Worker      name = ':' + get_bazel_label_name(trans_dep.name)
738*6dbdd20aSAndroid Build Coastguard Worker      if name.startswith(
739*6dbdd20aSAndroid Build Coastguard Worker          ':include_perfetto_') and gn_target.type != 'executable':
740*6dbdd20aSAndroid Build Coastguard Worker        label.hdrs += [name]
741*6dbdd20aSAndroid Build Coastguard Worker      else:
742*6dbdd20aSAndroid Build Coastguard Worker        if win_target:
743*6dbdd20aSAndroid Build Coastguard Worker          win_target_names = [target.name for target in win_target.transitive_source_set_deps()]
744*6dbdd20aSAndroid Build Coastguard Worker          if trans_dep.name in win_target_names:
745*6dbdd20aSAndroid Build Coastguard Worker            label.win_srcs += [name]
746*6dbdd20aSAndroid Build Coastguard Worker
747*6dbdd20aSAndroid Build Coastguard Worker        label.srcs += [name]
748*6dbdd20aSAndroid Build Coastguard Worker
749*6dbdd20aSAndroid Build Coastguard Worker      # Add defines from all transitive dependencies.
750*6dbdd20aSAndroid Build Coastguard Worker      label.defines += trans_dep.defines
751*6dbdd20aSAndroid Build Coastguard Worker
752*6dbdd20aSAndroid Build Coastguard Worker    for dep in sorted(gn_target.non_proto_or_source_set_deps()):
753*6dbdd20aSAndroid Build Coastguard Worker      dep_name = dep.name
754*6dbdd20aSAndroid Build Coastguard Worker      if dep_name.startswith('//gn:'):
755*6dbdd20aSAndroid Build Coastguard Worker        assert (dep_name in external_deps), dep
756*6dbdd20aSAndroid Build Coastguard Worker
757*6dbdd20aSAndroid Build Coastguard Worker      # tp_tables produces a filegroup not a cc_library so should end up srcs
758*6dbdd20aSAndroid Build Coastguard Worker      # not deps.
759*6dbdd20aSAndroid Build Coastguard Worker      if dep.custom_action_type == 'tp_tables':
760*6dbdd20aSAndroid Build Coastguard Worker        label_name = ':' + get_bazel_label_name(dep_name)
761*6dbdd20aSAndroid Build Coastguard Worker        win_target_names = [target.name for target in win_target.non_proto_or_source_set_deps()]
762*6dbdd20aSAndroid Build Coastguard Worker        if win_target and dep_name in win_target_names:
763*6dbdd20aSAndroid Build Coastguard Worker          label.win_srcs += [label_name]
764*6dbdd20aSAndroid Build Coastguard Worker        label.srcs += [label_name]
765*6dbdd20aSAndroid Build Coastguard Worker      elif dep_name in external_deps:
766*6dbdd20aSAndroid Build Coastguard Worker        assert (isinstance(external_deps[dep_name], list))
767*6dbdd20aSAndroid Build Coastguard Worker        label.external_deps += external_deps[dep_name]
768*6dbdd20aSAndroid Build Coastguard Worker      else:
769*6dbdd20aSAndroid Build Coastguard Worker        label.deps += [':' + get_bazel_label_name(dep_name)]
770*6dbdd20aSAndroid Build Coastguard Worker
771*6dbdd20aSAndroid Build Coastguard Worker    label.deps += [
772*6dbdd20aSAndroid Build Coastguard Worker        ':' + get_bazel_label_name(x.name)
773*6dbdd20aSAndroid Build Coastguard Worker        for x in gn_target.transitive_cpp_proto_deps()
774*6dbdd20aSAndroid Build Coastguard Worker    ]
775*6dbdd20aSAndroid Build Coastguard Worker
776*6dbdd20aSAndroid Build Coastguard Worker  # All items starting with : need to be sorted to the end of the list.
777*6dbdd20aSAndroid Build Coastguard Worker  # However, Python makes specifying a comparator function hard so cheat
778*6dbdd20aSAndroid Build Coastguard Worker  # instead and make everything start with : sort as if it started with |
779*6dbdd20aSAndroid Build Coastguard Worker  # As | > all other normal ASCII characters, this will lead to all : targets
780*6dbdd20aSAndroid Build Coastguard Worker  # starting with : to be sorted to the end.
781*6dbdd20aSAndroid Build Coastguard Worker  label.srcs = sorted(label.srcs, key=lambda x: x.replace(':', '|'))
782*6dbdd20aSAndroid Build Coastguard Worker  if win_target:
783*6dbdd20aSAndroid Build Coastguard Worker    label.win_srcs = sorted(label.win_srcs, key=lambda x: x.replace(':', '|'))
784*6dbdd20aSAndroid Build Coastguard Worker
785*6dbdd20aSAndroid Build Coastguard Worker  label.deps = sorted(label.deps)
786*6dbdd20aSAndroid Build Coastguard Worker  label.hdrs = sorted(label.hdrs)
787*6dbdd20aSAndroid Build Coastguard Worker  label.defines = sorted(filter_defines(set(label.defines)))
788*6dbdd20aSAndroid Build Coastguard Worker  return [label]
789*6dbdd20aSAndroid Build Coastguard Worker
790*6dbdd20aSAndroid Build Coastguard Worker
791*6dbdd20aSAndroid Build Coastguard Workerdef gen_target(gn_target: GnParser.Target, win_target: GnParser.Target = None):
792*6dbdd20aSAndroid Build Coastguard Worker  targets = gen_target_helper(gn_target, win_target)
793*6dbdd20aSAndroid Build Coastguard Worker  if gn_target.name not in target_overrides:
794*6dbdd20aSAndroid Build Coastguard Worker    return targets
795*6dbdd20aSAndroid Build Coastguard Worker  for target in targets:
796*6dbdd20aSAndroid Build Coastguard Worker    for key, add_val in target_overrides[gn_target.name].items():
797*6dbdd20aSAndroid Build Coastguard Worker      setattr(target, key, add_val)
798*6dbdd20aSAndroid Build Coastguard Worker  return targets
799*6dbdd20aSAndroid Build Coastguard Worker
800*6dbdd20aSAndroid Build Coastguard Worker
801*6dbdd20aSAndroid Build Coastguard Workerdef gen_target_str(gn_target, win_target: GnParser.Target = None):
802*6dbdd20aSAndroid Build Coastguard Worker  return ''.join(str(x) for x in gen_target(gn_target, win_target))
803*6dbdd20aSAndroid Build Coastguard Worker
804*6dbdd20aSAndroid Build Coastguard Worker
805*6dbdd20aSAndroid Build Coastguard Workerdef generate_build(gn_desc, gn_desc_win, targets, extras):
806*6dbdd20aSAndroid Build Coastguard Worker  gn = gn_utils.GnParser(gn_desc)
807*6dbdd20aSAndroid Build Coastguard Worker  gn_win = gn_utils.GnParser(gn_desc_win)
808*6dbdd20aSAndroid Build Coastguard Worker  project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
809*6dbdd20aSAndroid Build Coastguard Worker  tool_name = os.path.relpath(os.path.abspath(__file__), project_root)
810*6dbdd20aSAndroid Build Coastguard Worker  tool_name = tool_name.replace('\\', '/')
811*6dbdd20aSAndroid Build Coastguard Worker  res = '''
812*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2019 The Android Open Source Project
813*6dbdd20aSAndroid Build Coastguard Worker#
814*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
815*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
816*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
817*6dbdd20aSAndroid Build Coastguard Worker#
818*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
819*6dbdd20aSAndroid Build Coastguard Worker#
820*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
821*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
822*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
823*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
824*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
825*6dbdd20aSAndroid Build Coastguard Worker#
826*6dbdd20aSAndroid Build Coastguard Worker# This file is automatically generated by {}. Do not edit.
827*6dbdd20aSAndroid Build Coastguard Worker
828*6dbdd20aSAndroid Build Coastguard Workerload("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
829*6dbdd20aSAndroid Build Coastguard Workerload(
830*6dbdd20aSAndroid Build Coastguard Worker    "@perfetto//bazel:rules.bzl",
831*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_build_config_cc_library",
832*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_amalgamated_sql",
833*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_binary",
834*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_ipc_library",
835*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_library",
836*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_proto_descriptor",
837*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_proto_library",
838*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_protocpp_library",
839*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_protozero_library",
840*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_cc_tp_tables",
841*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_filegroup",
842*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_genrule",
843*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_go_proto_library",
844*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_java_lite_proto_library",
845*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_java_proto_library",
846*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_proto_descriptor",
847*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_proto_library",
848*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_py_binary",
849*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_py_library",
850*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_py_proto_library",
851*6dbdd20aSAndroid Build Coastguard Worker    "perfetto_jspb_proto_library",
852*6dbdd20aSAndroid Build Coastguard Worker)
853*6dbdd20aSAndroid Build Coastguard Worker
854*6dbdd20aSAndroid Build Coastguard Workerpackage(default_visibility = [PERFETTO_CONFIG.root + ":__subpackages__"])
855*6dbdd20aSAndroid Build Coastguard Worker
856*6dbdd20aSAndroid Build Coastguard Workerlicenses(["notice"])
857*6dbdd20aSAndroid Build Coastguard Worker
858*6dbdd20aSAndroid Build Coastguard Workerexports_files(["NOTICE"])
859*6dbdd20aSAndroid Build Coastguard Worker
860*6dbdd20aSAndroid Build Coastguard Worker'''.format(tool_name).lstrip()
861*6dbdd20aSAndroid Build Coastguard Worker
862*6dbdd20aSAndroid Build Coastguard Worker  # Public targets need to be computed at the beginning (to figure out the
863*6dbdd20aSAndroid Build Coastguard Worker  # intermediate deps) but printed at the end (because declaration order matters
864*6dbdd20aSAndroid Build Coastguard Worker  # in Bazel).
865*6dbdd20aSAndroid Build Coastguard Worker  public_str = ''
866*6dbdd20aSAndroid Build Coastguard Worker
867*6dbdd20aSAndroid Build Coastguard Worker  for target_name in sorted(public_targets):
868*6dbdd20aSAndroid Build Coastguard Worker    target = gn.get_target(target_name)
869*6dbdd20aSAndroid Build Coastguard Worker    public_str += gen_target_str(target, gn_win.get_target(target_name))
870*6dbdd20aSAndroid Build Coastguard Worker
871*6dbdd20aSAndroid Build Coastguard Worker  res += '''
872*6dbdd20aSAndroid Build Coastguard Worker# ##############################################################################
873*6dbdd20aSAndroid Build Coastguard Worker# Internal targets
874*6dbdd20aSAndroid Build Coastguard Worker# ##############################################################################
875*6dbdd20aSAndroid Build Coastguard Worker
876*6dbdd20aSAndroid Build Coastguard Worker'''.lstrip()
877*6dbdd20aSAndroid Build Coastguard Worker  # Generate the other non-public targets.
878*6dbdd20aSAndroid Build Coastguard Worker  for target_name in sorted(set(default_targets) - set(public_targets)):
879*6dbdd20aSAndroid Build Coastguard Worker    gn_win.get_target(target_name)
880*6dbdd20aSAndroid Build Coastguard Worker
881*6dbdd20aSAndroid Build Coastguard Worker  for target_name in sorted(set(default_targets) - set(public_targets)):
882*6dbdd20aSAndroid Build Coastguard Worker    target = gn.get_target(target_name)
883*6dbdd20aSAndroid Build Coastguard Worker    res += gen_target_str(target, gn_win.get_target(target_name))
884*6dbdd20aSAndroid Build Coastguard Worker
885*6dbdd20aSAndroid Build Coastguard Worker  # Generate all the intermediate targets.
886*6dbdd20aSAndroid Build Coastguard Worker  for target in sorted(itervalues(gn.all_targets)):
887*6dbdd20aSAndroid Build Coastguard Worker    if target.name in default_targets or target.name in gn.proto_libs:
888*6dbdd20aSAndroid Build Coastguard Worker      continue
889*6dbdd20aSAndroid Build Coastguard Worker    res += gen_target_str(target, gn_win.get_target(target.name))
890*6dbdd20aSAndroid Build Coastguard Worker
891*6dbdd20aSAndroid Build Coastguard Worker  res += '''
892*6dbdd20aSAndroid Build Coastguard Worker# ##############################################################################
893*6dbdd20aSAndroid Build Coastguard Worker# Proto libraries
894*6dbdd20aSAndroid Build Coastguard Worker# ##############################################################################
895*6dbdd20aSAndroid Build Coastguard Worker
896*6dbdd20aSAndroid Build Coastguard Worker'''.lstrip()
897*6dbdd20aSAndroid Build Coastguard Worker  # Generate targets for proto groups.
898*6dbdd20aSAndroid Build Coastguard Worker  for l_name, t_desc in proto_groups.items():
899*6dbdd20aSAndroid Build Coastguard Worker    res += ''.join(str(x) for x in gen_proto_group_target(gn, l_name, t_desc))
900*6dbdd20aSAndroid Build Coastguard Worker
901*6dbdd20aSAndroid Build Coastguard Worker  # For any non-source set and non-descriptor targets, ensure the source set
902*6dbdd20aSAndroid Build Coastguard Worker  # associated to that target is discovered.
903*6dbdd20aSAndroid Build Coastguard Worker  for target in sorted(itervalues(gn.all_targets)):
904*6dbdd20aSAndroid Build Coastguard Worker    plugin = target.proto_plugin
905*6dbdd20aSAndroid Build Coastguard Worker    if plugin is None or plugin == 'source_set' or plugin == 'descriptor':
906*6dbdd20aSAndroid Build Coastguard Worker      continue
907*6dbdd20aSAndroid Build Coastguard Worker    gn.get_target(re.sub('(lite|zero|cpp|ipc)$', 'source_set', target.name))
908*6dbdd20aSAndroid Build Coastguard Worker
909*6dbdd20aSAndroid Build Coastguard Worker  # Generate targets for the transitive set of proto targets.
910*6dbdd20aSAndroid Build Coastguard Worker  labels = [
911*6dbdd20aSAndroid Build Coastguard Worker      l for target in sorted(itervalues(gn.proto_libs))
912*6dbdd20aSAndroid Build Coastguard Worker      for l in gen_target(target)
913*6dbdd20aSAndroid Build Coastguard Worker  ]
914*6dbdd20aSAndroid Build Coastguard Worker  res += ''.join(str(x) for x in sorted(labels))
915*6dbdd20aSAndroid Build Coastguard Worker
916*6dbdd20aSAndroid Build Coastguard Worker  res += '''
917*6dbdd20aSAndroid Build Coastguard Worker# ##############################################################################
918*6dbdd20aSAndroid Build Coastguard Worker# Public targets
919*6dbdd20aSAndroid Build Coastguard Worker# ##############################################################################
920*6dbdd20aSAndroid Build Coastguard Worker
921*6dbdd20aSAndroid Build Coastguard Worker'''.lstrip()
922*6dbdd20aSAndroid Build Coastguard Worker  res += public_str
923*6dbdd20aSAndroid Build Coastguard Worker  res += '# Content from BUILD.extras\n\n'
924*6dbdd20aSAndroid Build Coastguard Worker  res += extras
925*6dbdd20aSAndroid Build Coastguard Worker
926*6dbdd20aSAndroid Build Coastguard Worker  # Check for ODR violations
927*6dbdd20aSAndroid Build Coastguard Worker  for target_name in default_targets:
928*6dbdd20aSAndroid Build Coastguard Worker    checker = gn_utils.ODRChecker(gn, target_name)
929*6dbdd20aSAndroid Build Coastguard Worker
930*6dbdd20aSAndroid Build Coastguard Worker  return res
931*6dbdd20aSAndroid Build Coastguard Worker
932*6dbdd20aSAndroid Build Coastguard Worker
933*6dbdd20aSAndroid Build Coastguard Workerdef main():
934*6dbdd20aSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(
935*6dbdd20aSAndroid Build Coastguard Worker      description='Generate BUILD from a GN description.')
936*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
937*6dbdd20aSAndroid Build Coastguard Worker      '--check-only',
938*6dbdd20aSAndroid Build Coastguard Worker      help='Don\'t keep the generated files',
939*6dbdd20aSAndroid Build Coastguard Worker      action='store_true')
940*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
941*6dbdd20aSAndroid Build Coastguard Worker      '--desc',
942*6dbdd20aSAndroid Build Coastguard Worker      help='GN description ' +
943*6dbdd20aSAndroid Build Coastguard Worker      '(e.g., gn desc out --format=json --all-toolchains "//*"')
944*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
945*6dbdd20aSAndroid Build Coastguard Worker      '--repo-root',
946*6dbdd20aSAndroid Build Coastguard Worker      help='Standalone Perfetto repository to generate a GN description',
947*6dbdd20aSAndroid Build Coastguard Worker      default=gn_utils.repo_root(),
948*6dbdd20aSAndroid Build Coastguard Worker  )
949*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
950*6dbdd20aSAndroid Build Coastguard Worker      '--extras',
951*6dbdd20aSAndroid Build Coastguard Worker      help='Extra targets to include at the end of the BUILD file',
952*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.join(gn_utils.repo_root(), 'BUILD.extras'),
953*6dbdd20aSAndroid Build Coastguard Worker  )
954*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
955*6dbdd20aSAndroid Build Coastguard Worker      '--output',
956*6dbdd20aSAndroid Build Coastguard Worker      help='BUILD file to create',
957*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.join(gn_utils.repo_root(), 'BUILD'),
958*6dbdd20aSAndroid Build Coastguard Worker  )
959*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
960*6dbdd20aSAndroid Build Coastguard Worker      '--output-python',
961*6dbdd20aSAndroid Build Coastguard Worker      help='Python BUILD file to create',
962*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.join(gn_utils.repo_root(), 'python', 'BUILD'),
963*6dbdd20aSAndroid Build Coastguard Worker  )
964*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
965*6dbdd20aSAndroid Build Coastguard Worker      'targets',
966*6dbdd20aSAndroid Build Coastguard Worker      nargs=argparse.REMAINDER,
967*6dbdd20aSAndroid Build Coastguard Worker      help='Targets to include in the BUILD file (e.g., "//:perfetto_tests")')
968*6dbdd20aSAndroid Build Coastguard Worker  args = parser.parse_args()
969*6dbdd20aSAndroid Build Coastguard Worker
970*6dbdd20aSAndroid Build Coastguard Worker  if args.desc:
971*6dbdd20aSAndroid Build Coastguard Worker    with open(args.desc) as f:
972*6dbdd20aSAndroid Build Coastguard Worker      desc = json.load(f)
973*6dbdd20aSAndroid Build Coastguard Worker  else:
974*6dbdd20aSAndroid Build Coastguard Worker    desc = gn_utils.create_build_description(gn_args, args.repo_root)
975*6dbdd20aSAndroid Build Coastguard Worker
976*6dbdd20aSAndroid Build Coastguard Worker  desc_win = gn_utils.create_build_description(gn_args_win, args.repo_root)
977*6dbdd20aSAndroid Build Coastguard Worker  out_files = []
978*6dbdd20aSAndroid Build Coastguard Worker
979*6dbdd20aSAndroid Build Coastguard Worker  # Generate the main BUILD file.
980*6dbdd20aSAndroid Build Coastguard Worker  with open(args.extras, 'r') as extra_f:
981*6dbdd20aSAndroid Build Coastguard Worker    extras = extra_f.read()
982*6dbdd20aSAndroid Build Coastguard Worker
983*6dbdd20aSAndroid Build Coastguard Worker  contents = generate_build(desc, desc_win, args.targets or default_targets, extras)
984*6dbdd20aSAndroid Build Coastguard Worker  out_files.append(args.output + '.swp')
985*6dbdd20aSAndroid Build Coastguard Worker  with open(out_files[-1], 'w', newline='\n') as out_f:
986*6dbdd20aSAndroid Build Coastguard Worker    out_f.write(contents)
987*6dbdd20aSAndroid Build Coastguard Worker
988*6dbdd20aSAndroid Build Coastguard Worker  # Generate the python BUILD file.
989*6dbdd20aSAndroid Build Coastguard Worker  python_gen = PythonBuildGenerator()
990*6dbdd20aSAndroid Build Coastguard Worker  python_contents = python_gen.generate(desc)
991*6dbdd20aSAndroid Build Coastguard Worker  out_files.append(args.output_python + '.swp')
992*6dbdd20aSAndroid Build Coastguard Worker  with open(out_files[-1], 'w', newline='\n') as out_f:
993*6dbdd20aSAndroid Build Coastguard Worker    out_f.write(python_contents)
994*6dbdd20aSAndroid Build Coastguard Worker
995*6dbdd20aSAndroid Build Coastguard Worker  # Generate the build flags file.
996*6dbdd20aSAndroid Build Coastguard Worker  out_files.append(os.path.join(buildflags_dir, 'perfetto_build_flags.h.swp'))
997*6dbdd20aSAndroid Build Coastguard Worker  gn_utils.gen_buildflags(gn_args, out_files[-1])
998*6dbdd20aSAndroid Build Coastguard Worker
999*6dbdd20aSAndroid Build Coastguard Worker  return gn_utils.check_or_commit_generated_files(out_files, args.check_only)
1000*6dbdd20aSAndroid Build Coastguard Worker
1001*6dbdd20aSAndroid Build Coastguard Worker
1002*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__':
1003*6dbdd20aSAndroid Build Coastguard Worker  sys.exit(main())
1004