Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 1 | #!/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 | |
| 26 | from __future__ import print_function |
| 27 | import argparse |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 28 | import json |
| 29 | import os |
| 30 | import re |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 31 | import sys |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 32 | |
Sami Kyostila | 3c88a1d | 2019-05-22 18:29:42 +0100 | [diff] [blame] | 33 | import gn_utils |
| 34 | |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 35 | from compat import itervalues, iteritems, basestring |
| 36 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 37 | # Arguments for the GN output directory. |
| 38 | # host_os="linux" is to generate the right build files from Mac OS. |
| 39 | gn_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. |
| 51 | public_targets = [ |
Pascal Muetschard | b4966c5 | 2019-09-24 13:38:09 -0700 | [diff] [blame] | 52 | '//:libperfetto_client_experimental', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 53 | '//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 Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 58 | '//tools/trace_to_text:trace_to_text', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 59 | '//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. |
| 64 | default_targets = [ |
Lalit Maganti | 01deefa | 2019-12-19 14:20:12 +0000 | [diff] [blame] | 65 | '//test:client_api_example', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 66 | '//src/ipc:perfetto_ipc', |
| 67 | '//src/ipc/protoc_plugin:ipc_plugin', |
Primiano Tucci | 916f4e5 | 2020-10-16 20:40:33 +0200 | [diff] [blame] | 68 | '//src/protozero:protozero', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 69 | '//src/protozero/protoc_plugin:protozero_plugin', |
Primiano Tucci | 57dd66b | 2019-10-15 23:09:04 +0100 | [diff] [blame] | 70 | '//src/protozero/protoc_plugin:cppgen_plugin', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 71 | ] + public_targets |
| 72 | |
| 73 | # Root proto targets (to force discovery of intermediate proto targets). |
Pascal Muetschard | b7cdea0 | 2019-09-23 15:25:20 -0700 | [diff] [blame] | 74 | # These targets are marked public. |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 75 | proto_targets = [ |
Lalit Maganti | c3187f8 | 2019-09-20 14:51:11 +0100 | [diff] [blame] | 76 | '//protos/perfetto/trace:merged_trace', |
Lalit Maganti | d78606d | 2019-11-21 17:45:55 +0000 | [diff] [blame] | 77 | '//protos/perfetto/trace:non_minimal_lite', |
Pascal Muetschard | b7cdea0 | 2019-09-23 15:25:20 -0700 | [diff] [blame] | 78 | '//protos/perfetto/config:merged_config', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 79 | '//protos/perfetto/metrics:lite', |
Lalit Maganti | 613f97b | 2019-11-21 14:44:18 +0000 | [diff] [blame] | 80 | '//protos/perfetto/metrics/android:lite', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 81 | '//protos/perfetto/trace:lite', |
| 82 | '//protos/perfetto/config:lite', |
| 83 | ] |
| 84 | |
Lalit Maganti | 3b09a3f | 2020-09-14 13:28:44 +0100 | [diff] [blame] | 85 | # Path for the protobuf sources in the standalone build. |
| 86 | buildtools_protobuf_src = '//buildtools/protobuf/src' |
| 87 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 88 | # The directory where the generated perfetto_build_flags.h will be copied into. |
| 89 | buildflags_dir = 'include/perfetto/base/build_configs/bazel' |
| 90 | |
| 91 | # Internal equivalents for third-party libraries that the upstream project |
| 92 | # depends on. |
| 93 | external_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 Clarkson | 63028d6 | 2019-10-10 15:48:23 +0100 | [diff] [blame] | 106 | '//src/trace_processor/metrics:gen_merged_sql_metrics': [[ |
Lalit Maganti | 117272f | 2020-09-11 14:01:18 +0100 | [diff] [blame] | 107 | ':cc_merged_sql_metrics' |
Primiano Tucci | ec59013 | 2020-11-16 14:16:44 +0100 | [diff] [blame] | 108 | ]], |
| 109 | gn_utils.GEN_VERSION_TARGET: ['PERFETTO_CONFIG.deps.version_header'], |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | |
| 113 | def gen_sql_metrics(target): |
| 114 | label = BazelLabel(get_bazel_label_name(target.name), 'genrule') |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 115 | label.srcs += [re.sub('^//', '', x) for x in sorted(target.inputs)] |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 116 | label.outs += target.outputs |
| 117 | label.cmd = r'$(location gen_merged_sql_metrics_py) --cpp_out=$@ $(SRCS)' |
Lalit Maganti | 9d9e56b | 2020-08-13 17:38:15 +0100 | [diff] [blame] | 118 | label.exec_tools += [':gen_merged_sql_metrics_py'] |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 119 | return [label] |
| 120 | |
| 121 | |
Primiano Tucci | ec59013 | 2020-11-16 14:16:44 +0100 | [diff] [blame] | 122 | def 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 Tucci | f0ed1d4 | 2020-11-18 16:30:18 +0100 | [diff] [blame] | 126 | label.cmd = r'$(location gen_version_header_py)' |
Joshua Gilpatrick | 042931b | 2020-12-04 08:55:59 -0800 | [diff] [blame] | 127 | label.cmd += r' --cpp_out=$@ --changelog=$(location CHANGELOG)' |
Primiano Tucci | ec59013 | 2020-11-16 14:16:44 +0100 | [diff] [blame] | 128 | label.exec_tools += [':gen_version_header_py'] |
| 129 | return [label] |
| 130 | |
| 131 | |
Lalit Maganti | 117272f | 2020-09-11 14:01:18 +0100 | [diff] [blame] | 132 | def 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 Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 140 | custom_actions = { |
Primiano Tucci | ec59013 | 2020-11-16 14:16:44 +0100 | [diff] [blame] | 141 | gn_utils.GEN_VERSION_TARGET: gen_version_header, |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 142 | '//src/trace_processor/metrics:gen_merged_sql_metrics': gen_sql_metrics, |
Lalit Maganti | 117272f | 2020-09-11 14:01:18 +0100 | [diff] [blame] | 143 | '//src/trace_processor/metrics:gen_cc_metrics_descriptor': |
| 144 | gen_cc_metrics_descriptor, |
Lalit Maganti | 3b09a3f | 2020-09-14 13:28:44 +0100 | [diff] [blame] | 145 | '//src/trace_processor/metrics:gen_cc_all_chrome_metrics_descriptor': |
| 146 | gen_cc_metrics_descriptor, |
Hector Dearman | a1d7524 | 2020-10-02 09:47:24 +0100 | [diff] [blame] | 147 | '//src/trace_processor/importers:gen_cc_config_descriptor': |
| 148 | gen_cc_metrics_descriptor, |
Andrew Shulaev | ba0a5d1 | 2021-01-07 08:44:50 +0000 | [diff] [blame] | 149 | '//src/trace_processor/importers:gen_cc_chrome_track_event_descriptor': |
| 150 | gen_cc_metrics_descriptor, |
Andrew Shulaev | e72d1a3 | 2021-01-13 12:59:55 +0000 | [diff] [blame] | 151 | '//src/trace_processor/importers:gen_cc_track_event_descriptor': |
| 152 | gen_cc_metrics_descriptor, |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | # ------------------------------------------------------------------------------ |
| 156 | # End of configuration. |
| 157 | # ------------------------------------------------------------------------------ |
| 158 | |
| 159 | |
| 160 | class Error(Exception): |
| 161 | pass |
| 162 | |
| 163 | |
| 164 | class 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 Maganti | 9d9e56b | 2020-08-13 17:38:15 +0100 | [diff] [blame] | 176 | self.exec_tools = [] |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 177 | self.outs = [] |
| 178 | |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 179 | def __lt__(self, other): |
| 180 | if isinstance(other, self.__class__): |
| 181 | return self.name < other.name |
Primiano Tucci | 57dd66b | 2019-10-15 23:09:04 +0100 | [diff] [blame] | 182 | raise TypeError('\'<\' not supported between instances of \'%s\' and \'%s\'' |
| 183 | % (type(self).__name__, type(other).__name__)) |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 184 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 185 | 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 Maganti | 9d9e56b | 2020-08-13 17:38:15 +0100 | [diff] [blame] | 191 | ORD = [ |
| 192 | 'name','srcs', 'hdrs', 'visibility', 'deps', 'outs', 'cmd', 'tools', |
| 193 | 'exec_tools' |
| 194 | ] |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 195 | 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 Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 198 | 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 Maganti | e5aad3b | 2020-01-20 18:43:05 +0000 | [diff] [blame] | 204 | if v.startswith('PERFETTO_CONFIG.'): |
| 205 | res += '%s,\n' % v |
| 206 | else: |
| 207 | res += '"%s",\n' % v |
Lalit Maganti | f9c004d | 2020-01-06 14:44:34 +0000 | [diff] [blame] | 208 | elif isinstance(v, bool): |
| 209 | res += '%s,\n' % v |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 210 | elif isinstance(v, list): |
| 211 | res += '[\n' |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 212 | if k == 'deps' and len(self.external_deps) > 1: |
| 213 | indent = ' ' |
| 214 | else: |
| 215 | indent = ' ' |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 216 | for entry in v: |
Primiano Tucci | e88d939 | 2019-11-19 17:42:41 +0000 | [diff] [blame] | 217 | if entry.startswith('PERFETTO_CONFIG.'): |
| 218 | res += '%s %s,\n' % (indent, entry) |
| 219 | else: |
| 220 | res += '%s "%s",\n' % (indent, entry) |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 221 | 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 Maganti | a4244e4 | 2019-09-20 12:03:32 +0100 | [diff] [blame] | 228 | res += ' "%s",\n' % inner_dep |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 229 | res += ' ]' |
| 230 | else: |
| 231 | res += ' +\n%s%s' % (indent, edep) |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 232 | res += ',\n' |
| 233 | else: |
| 234 | raise Error('Unsupported value %s', type(v)) |
| 235 | res += ')\n\n' |
| 236 | return res |
| 237 | |
| 238 | |
Lalit Maganti | 613f97b | 2019-11-21 14:44:18 +0000 | [diff] [blame] | 239 | # Public visibility for targets in Bazel. |
Lalit Maganti | e5aad3b | 2020-01-20 18:43:05 +0000 | [diff] [blame] | 240 | PUBLIC_VISIBILITY = 'PERFETTO_CONFIG.public_visibility' |
Lalit Maganti | 613f97b | 2019-11-21 14:44:18 +0000 | [diff] [blame] | 241 | |
| 242 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 243 | def get_bazel_label_name(gn_name): |
| 244 | """Converts a GN target name into a Bazel label name. |
| 245 | |
Primiano Tucci | 66b08c3 | 2020-07-23 12:37:48 +0200 | [diff] [blame] | 246 | If target is in the public target list, returns only the GN target name, |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 247 | e.g.: //src/ipc:perfetto_ipc -> perfetto_ipc |
| 248 | |
Primiano Tucci | 66b08c3 | 2020-07-23 12:37:48 +0200 | [diff] [blame] | 249 | Otherwise, in the case of an intermediate target, returns a mangled path. |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 250 | 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 | |
| 257 | def 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 Maganti | 117272f | 2020-09-11 14:01:18 +0100 | [diff] [blame] | 261 | 1. A plugin-agnostic target that defines only the .proto sources and their |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 262 | dependencies. |
Lalit Maganti | 117272f | 2020-09-11 14:01:18 +0100 | [diff] [blame] | 263 | 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 Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 265 | """ |
| 266 | assert (target.type == 'proto_library') |
| 267 | |
| 268 | def get_sources_label(target_name): |
Lalit Maganti | 64cd1f6 | 2020-09-14 17:44:52 +0100 | [diff] [blame] | 269 | return re.sub('_(lite|zero|cpp|ipc|source_set|descriptor)$', '', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 270 | get_bazel_label_name(target_name)) + '_protos' |
| 271 | |
| 272 | sources_label_name = get_sources_label(target.name) |
| 273 | |
| 274 | # Generates 1. |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 275 | 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 Tucci | f0d63af | 2019-11-19 17:07:37 +0000 | [diff] [blame] | 280 | |
Primiano Tucci | f0d63af | 2019-11-19 17:07:37 +0000 | [diff] [blame] | 281 | deps = [ |
| 282 | ':' + get_sources_label(x) |
| 283 | for x in target.proto_deps |
Primiano Tucci | e8020f9 | 2019-11-26 13:24:01 +0000 | [diff] [blame] | 284 | |
| 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 Tucci | f0d63af | 2019-11-19 17:07:37 +0000 | [diff] [blame] | 289 | ] |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 290 | sources_label.deps = sorted(deps) |
| 291 | |
Lalit Maganti | 3b09a3f | 2020-09-14 13:28:44 +0100 | [diff] [blame] | 292 | # 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 Muetschard | b7cdea0 | 2019-09-23 15:25:20 -0700 | [diff] [blame] | 303 | if target.name in proto_targets: |
Lalit Maganti | 613f97b | 2019-11-21 14:44:18 +0000 | [diff] [blame] | 304 | sources_label.visibility = PUBLIC_VISIBILITY |
Primiano Tucci | e88d939 | 2019-11-19 17:42:41 +0000 | [diff] [blame] | 305 | else: |
| 306 | sources_label.visibility = ['PERFETTO_CONFIG.proto_library_visibility'] |
Pascal Muetschard | b7cdea0 | 2019-09-23 15:25:20 -0700 | [diff] [blame] | 307 | |
Lalit Maganti | 117272f | 2020-09-11 14:01:18 +0100 | [diff] [blame] | 308 | # 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 Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 346 | |
| 347 | |
| 348 | def 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 Maganti | 91d223e | 2019-12-20 12:28:19 +0000 | [diff] [blame] | 371 | |
| 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 Maganti | f9c004d | 2020-01-06 14:44:34 +0000 | [diff] [blame] | 376 | |
| 377 | # Most Perfetto libraries cannot by dynamically linked as they would |
| 378 | # cause ODR violations. |
| 379 | label.__dict__['linkstatic'] = True |
Lalit Maganti | 91d223e | 2019-12-20 12:28:19 +0000 | [diff] [blame] | 380 | else: |
| 381 | label.srcs = raw_srcs |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 382 | |
| 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 Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 395 | for dep in sorted(gn_target.deps): |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 396 | 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 Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 405 | # 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 Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 412 | label.deps = sorted(label.deps) |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 413 | label.hdrs = sorted(label.hdrs) |
| 414 | return [label] |
| 415 | |
| 416 | |
| 417 | def gen_target_str(gn_target): |
| 418 | return ''.join(str(x) for x in gen_target(gn_target)) |
| 419 | |
| 420 | |
| 421 | def 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 Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 425 | # |
| 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 Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 439 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 440 | load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG") |
| 441 | load( |
| 442 | "@perfetto//bazel:rules.bzl", |
| 443 | "perfetto_cc_binary", |
| 444 | "perfetto_cc_ipc_library", |
| 445 | "perfetto_cc_library", |
Lalit Maganti | 117272f | 2020-09-11 14:01:18 +0100 | [diff] [blame] | 446 | "perfetto_cc_proto_descriptor", |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 447 | "perfetto_cc_proto_library", |
Primiano Tucci | 57dd66b | 2019-10-15 23:09:04 +0100 | [diff] [blame] | 448 | "perfetto_cc_protocpp_library", |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 449 | "perfetto_cc_protozero_library", |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 450 | "perfetto_java_proto_library", |
Lalit Maganti | 46e2bda | 2020-05-06 12:51:33 +0100 | [diff] [blame] | 451 | "perfetto_java_lite_proto_library", |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 452 | "perfetto_proto_library", |
Lalit Maganti | 117272f | 2020-09-11 14:01:18 +0100 | [diff] [blame] | 453 | "perfetto_proto_descriptor", |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 454 | "perfetto_py_binary", |
Anindita Ghosh | 237a776 | 2020-06-30 10:46:52 +0000 | [diff] [blame] | 455 | "perfetto_py_library", |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 456 | "perfetto_gensignature_internal_only", |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 457 | ) |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 458 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 459 | package(default_visibility = ["//visibility:private"]) |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 460 | |
Lalit Maganti | bb037f7 | 2019-09-24 16:22:45 +0100 | [diff] [blame] | 461 | licenses(["notice"]) |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 462 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 463 | exports_files(["NOTICE"]) |
Lalit Maganti | a48710d | 2019-09-24 13:10:11 +0100 | [diff] [blame] | 464 | |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 465 | '''.format(__file__).lstrip() |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 466 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 467 | # 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 Tucci | 8e62744 | 2019-08-28 07:58:38 +0200 | [diff] [blame] | 474 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 475 | res += ''' |
| 476 | # ############################################################################## |
| 477 | # Internal targets |
| 478 | # ############################################################################## |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 479 | |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 480 | '''.lstrip() |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 481 | # 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 Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 485 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 486 | # Generate all the intermediate targets. |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 487 | for target in sorted(itervalues(gn.all_targets)): |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 488 | if target.name in default_targets or target.name in gn.proto_libs: |
| 489 | continue |
| 490 | res += gen_target_str(target) |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 491 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 492 | res += ''' |
| 493 | # ############################################################################## |
| 494 | # Proto libraries |
| 495 | # ############################################################################## |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 496 | |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 497 | '''.lstrip() |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 498 | # Force discovery of explicilty listed root proto targets. |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 499 | for target_name in sorted(proto_targets): |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 500 | gn.get_target(target_name) |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 501 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 502 | # Generate targets for the transitive set of proto targets. |
| 503 | # TODO explain deduping here. |
| 504 | labels = {} |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 505 | for target in sorted(itervalues(gn.proto_libs)): |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 506 | for label in gen_target(target): |
Lalit Maganti | 613f97b | 2019-11-21 14:44:18 +0000 | [diff] [blame] | 507 | # 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 Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 513 | labels[label.name] = label |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 514 | |
Matthew Clarkson | 9a5dfa5 | 2019-10-03 09:54:04 +0100 | [diff] [blame] | 515 | res += ''.join(str(x) for x in sorted(itervalues(labels))) |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 516 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 517 | res += ''' |
| 518 | # ############################################################################## |
| 519 | # Public targets |
| 520 | # ############################################################################## |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 521 | |
Lalit Maganti | 6560034 | 2019-09-19 21:35:35 +0100 | [diff] [blame] | 522 | '''.lstrip() |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 523 | res += public_str |
| 524 | res += '# Content from BUILD.extras\n\n' |
| 525 | res += extras |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 526 | |
Primiano Tucci | 916f4e5 | 2020-10-16 20:40:33 +0200 | [diff] [blame] | 527 | # 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 Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 532 | |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 533 | def main(): |
| 534 | parser = argparse.ArgumentParser( |
| 535 | description='Generate BUILD from a GN description.') |
| 536 | parser.add_argument( |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 537 | '--check-only', |
| 538 | help='Don\'t keep the generated files', |
| 539 | action='store_true') |
Primiano Tucci | 9c41165 | 2019-08-27 07:13:59 +0200 | [diff] [blame] | 540 | parser.add_argument( |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 541 | '--desc', |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 542 | help='GN description ' + |
| 543 | '(e.g., gn desc out --format=json --all-toolchains "//*"') |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 544 | parser.add_argument( |
| 545 | '--repo-root', |
| 546 | help='Standalone Perfetto repository to generate a GN description', |
Sami Kyostila | 3c88a1d | 2019-05-22 18:29:42 +0100 | [diff] [blame] | 547 | default=gn_utils.repo_root(), |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 548 | ) |
| 549 | parser.add_argument( |
| 550 | '--extras', |
| 551 | help='Extra targets to include at the end of the BUILD file', |
Sami Kyostila | 3c88a1d | 2019-05-22 18:29:42 +0100 | [diff] [blame] | 552 | default=os.path.join(gn_utils.repo_root(), 'BUILD.extras'), |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 553 | ) |
| 554 | parser.add_argument( |
| 555 | '--output', |
| 556 | help='BUILD file to create', |
Sami Kyostila | 3c88a1d | 2019-05-22 18:29:42 +0100 | [diff] [blame] | 557 | default=os.path.join(gn_utils.repo_root(), 'BUILD'), |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 558 | ) |
| 559 | parser.add_argument( |
| 560 | '--output-proto', |
| 561 | help='Proto BUILD file to create', |
Sami Kyostila | 3c88a1d | 2019-05-22 18:29:42 +0100 | [diff] [blame] | 562 | default=os.path.join(gn_utils.repo_root(), 'protos', 'BUILD'), |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 563 | ) |
| 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 Kyostila | 3c88a1d | 2019-05-22 18:29:42 +0100 | [diff] [blame] | 574 | desc = gn_utils.create_build_description(gn_args, args.repo_root) |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 575 | |
Primiano Tucci | 9c41165 | 2019-08-27 07:13:59 +0200 | [diff] [blame] | 576 | out_files = [] |
| 577 | |
Primiano Tucci | 9c41165 | 2019-08-27 07:13:59 +0200 | [diff] [blame] | 578 | # Generate the main BUILD file. |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 579 | with open(args.extras, 'r') as extra_f: |
| 580 | extras = extra_f.read() |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 581 | |
Primiano Tucci | 1d40998 | 2019-09-19 10:15:18 +0100 | [diff] [blame] | 582 | 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 Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 586 | |
Primiano Tucci | 8e62744 | 2019-08-28 07:58:38 +0200 | [diff] [blame] | 587 | # 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 Tucci | 9c41165 | 2019-08-27 07:13:59 +0200 | [diff] [blame] | 591 | return gn_utils.check_or_commit_generated_files(out_files, args.check_only) |
Lalit Maganti | 279ecde | 2019-04-01 16:57:12 +0100 | [diff] [blame] | 592 | |
| 593 | |
| 594 | if __name__ == '__main__': |
| 595 | sys.exit(main()) |