• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2019 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
16load("@perfetto//bazel:proto_gen.bzl", "proto_descriptor_gen", "proto_gen")
17
18# +----------------------------------------------------------------------------+
19# | Base C++ rules.                                                            |
20# +----------------------------------------------------------------------------+
21
22def default_cc_args():
23    return {
24        "deps": PERFETTO_CONFIG.deps.build_config,
25        "copts": PERFETTO_CONFIG.default_copts + [
26            "-Wno-pragma-system-header-outside-header",
27        ],
28        "includes": ["include"],
29        "linkopts": select({
30            "@perfetto//bazel:os_linux": ["-ldl", "-lrt", "-lpthread"],
31            "@perfetto//bazel:os_osx": [],
32            "@perfetto//bazel:os_windows": [],
33            "//conditions:default": ["-ldl"],
34        }),
35    }
36
37def perfetto_build_config_cc_library(**kwargs):
38    if not _rule_override("cc_library", **kwargs):
39        native.cc_library(**kwargs)
40
41def perfetto_filegroup(**kwargs):
42    if not _rule_override("filegroup", **kwargs):
43        native.filegroup(**kwargs)
44
45def perfetto_genrule(**kwargs):
46    if not _rule_override("genrule", **kwargs):
47        native.genrule(**kwargs)
48
49def perfetto_cc_library(**kwargs):
50    args = _merge_dicts(default_cc_args(), kwargs)
51    if not _rule_override("cc_library", **args):
52        native.cc_library(**args)
53
54def perfetto_cc_binary(**kwargs):
55    args = _merge_dicts(default_cc_args(), kwargs)
56    if not _rule_override("cc_binary", **args):
57        native.cc_binary(**args)
58
59def perfetto_py_binary(**kwargs):
60    if not _rule_override("py_binary", **kwargs):
61        native.py_binary(**kwargs)
62
63def perfetto_py_library(**kwargs):
64    if not _rule_override("py_library", **kwargs):
65        native.py_library(**kwargs)
66
67# +----------------------------------------------------------------------------+
68# | Proto-related rules                                                        |
69# +----------------------------------------------------------------------------+
70
71def perfetto_proto_library(**kwargs):
72    if not _rule_override("proto_library", **kwargs):
73        native.proto_library(**kwargs)
74
75def perfetto_cc_proto_library(**kwargs):
76    if not _rule_override("cc_proto_library", **kwargs):
77        native.cc_proto_library(**kwargs)
78
79def perfetto_java_proto_library(**kwargs):
80    if not _rule_override("java_proto_library", **kwargs):
81        native.java_proto_library(**kwargs)
82
83def perfetto_java_lite_proto_library(**kwargs):
84    if not _rule_override("java_lite_proto_library", **kwargs):
85        native.java_lite_proto_library(**kwargs)
86
87# Unlike the other rules, this is an noop by default because Bazel does not
88# support Go proto libraries.
89def perfetto_go_proto_library(**kwargs):
90    _rule_override("go_proto_library", **kwargs)
91
92# Unlike the other rules, this is an noop by default because Bazel does not
93# support Python proto libraries.
94def perfetto_py_proto_library(**kwargs):
95    _rule_override("py_proto_library", **kwargs)
96
97# +----------------------------------------------------------------------------+
98# | Misc rules.                                                                |
99# +----------------------------------------------------------------------------+
100
101# Generates .pbzero.{cc,h} from .proto(s). We deliberately do NOT generate
102# conventional .pb.{cc,h} from here as protozero gen sources do not have any
103# dependency on libprotobuf.
104def perfetto_cc_protozero_library(name, deps, **kwargs):
105    if _rule_override(
106        "cc_protozero_library",
107        name = name,
108        deps = deps,
109        **kwargs
110    ):
111        return
112
113    # A perfetto_cc_protozero_library has two types of dependencies:
114    # 1. Exactly one dependency on a proto_library target. This defines the
115    #    .proto sources for the target
116    # 2. Zero or more deps on other perfetto_cc_protozero_library targets. This
117    #    to deal with the case of foo.proto including common.proto from another
118    #    target.
119    _proto_deps = [d for d in deps if d.endswith("_protos")]
120    _cc_deps = [d for d in deps if d not in _proto_deps]
121    if len(_proto_deps) != 1:
122        fail("Too many proto deps for target %s" % name)
123
124    args = {
125        'name': name + "_src",
126        'deps': _proto_deps,
127        'suffix': "pbzero",
128        'plugin': PERFETTO_CONFIG.root + ":protozero_plugin",
129        'wrapper_namespace': "pbzero",
130        'protoc': PERFETTO_CONFIG.deps.protoc[0],
131        'root': PERFETTO_CONFIG.root,
132    }
133    if not _rule_override("proto_gen", **args):
134        proto_gen(**args)
135
136    perfetto_filegroup(
137        name = name + "_h",
138        srcs = [":" + name + "_src"],
139        output_group = "h",
140    )
141
142    perfetto_cc_library(
143        name = name,
144        srcs = [":" + name + "_src"],
145        hdrs = [":" + name + "_h"],
146        deps = [PERFETTO_CONFIG.root + ":protozero"] + _cc_deps,
147        **kwargs
148    )
149
150# Generates .ipc.{cc,h} and .pb.{cc.h} from .proto(s). The IPC sources depend
151# on .pb.h so we need to generate also the standard protobuf sources here.
152def perfetto_cc_ipc_library(name, deps, **kwargs):
153    if _rule_override("cc_ipc_library", name = name, deps = deps, **kwargs):
154        return
155
156    # A perfetto_cc_ipc_library has two types of dependencies:
157    # 1. Exactly one dependency on a proto_library target. This defines the
158    #    .proto sources for the target
159    # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This
160    #    to deal with the case of foo.proto including common.proto from another
161    #    target.
162    _proto_deps = [d for d in deps if d.endswith("_protos")]
163    _cc_deps = [d for d in deps if d not in _proto_deps]
164    if len(_proto_deps) != 1:
165        fail("Too many proto deps for target %s" % name)
166
167    # Generates .ipc.{cc,h}.
168    args = {
169        'name': name + "_src",
170        'deps': _proto_deps,
171        'suffix': "ipc",
172        'plugin': PERFETTO_CONFIG.root + ":ipc_plugin",
173        'wrapper_namespace': "gen",
174        'protoc': PERFETTO_CONFIG.deps.protoc[0],
175        'root': PERFETTO_CONFIG.root,
176    }
177    if not _rule_override("proto_gen", **args):
178        proto_gen(**args)
179
180    perfetto_filegroup(
181        name = name + "_h",
182        srcs = [":" + name + "_src"],
183        output_group = "h",
184    )
185
186    perfetto_cc_library(
187        name = name,
188        srcs = [":" + name + "_src"],
189        hdrs = [":" + name + "_h"],
190        deps = [
191            # Generated .ipc.{cc,h} depend on this and protozero.
192            PERFETTO_CONFIG.root + ":perfetto_ipc",
193            PERFETTO_CONFIG.root + ":protozero",
194        ] + _cc_deps,
195        **kwargs
196    )
197
198# Generates .gen.{cc,h} from .proto(s).
199def perfetto_cc_protocpp_library(name, deps, **kwargs):
200    if _rule_override(
201        "cc_protocpp_library",
202        name = name,
203        deps = deps,
204        **kwargs
205    ):
206        return
207
208    # A perfetto_cc_protocpp_library has two types of dependencies:
209    # 1. Exactly one dependency on a proto_library target. This defines the
210    #    .proto sources for the target
211    # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This
212    #    to deal with the case of foo.proto including common.proto from another
213    #    target.
214    _proto_deps = [d for d in deps if d.endswith("_protos")]
215    _cc_deps = [d for d in deps if d not in _proto_deps]
216    if len(_proto_deps) != 1:
217        fail("Too many proto deps for target %s" % name)
218
219    args = {
220        'name': name + "_gen",
221        'deps': _proto_deps,
222        'suffix': "gen",
223        'plugin': PERFETTO_CONFIG.root + ":cppgen_plugin",
224        'wrapper_namespace': "gen",
225        'protoc': PERFETTO_CONFIG.deps.protoc[0],
226        'root': PERFETTO_CONFIG.root,
227    }
228    if not _rule_override("proto_gen", **args):
229        proto_gen(**args)
230
231    perfetto_filegroup(
232        name = name + "_gen_h",
233        srcs = [":" + name + "_gen"],
234        output_group = "h",
235    )
236
237    # The headers from the gen plugin have implicit dependencies
238    # on each other so will fail when compiled independently. Use
239    # textual_hdrs to indicate this to Bazel.
240    perfetto_cc_library(
241        name = name,
242        srcs = [":" + name + "_gen"],
243        textual_hdrs = [":" + name + "_gen_h"],
244        deps = [
245            PERFETTO_CONFIG.root + ":protozero",
246        ] + _cc_deps,
247        **kwargs
248    )
249
250def perfetto_proto_descriptor(name, deps, outs, **kwargs):
251    args = {
252        'name': name,
253        'deps': deps,
254        'outs': outs,
255    }
256    if not _rule_override("proto_descriptor_gen", **args):
257        proto_descriptor_gen(**args)
258
259# Generator .descriptor.h from protos
260def perfetto_cc_proto_descriptor(name, deps, outs, **kwargs):
261    cmd = [
262        "$(location gen_cc_proto_descriptor_py)",
263        "--cpp_out=$@",
264        "--gen_dir=$(GENDIR)",
265        "$<"
266    ]
267    perfetto_genrule(
268        name = name + "_gen",
269        cmd = " ".join(cmd),
270        tools = [
271            ":gen_cc_proto_descriptor_py",
272        ],
273        srcs = deps,
274        outs = outs,
275    )
276
277    perfetto_cc_library(
278        name = name,
279        hdrs = [":" + name + "_gen"],
280        **kwargs
281    )
282
283def perfetto_cc_amalgamated_sql(name, deps, outs, namespace, **kwargs):
284    if PERFETTO_CONFIG.root[:2] != "//":
285        fail("Expected PERFETTO_CONFIG.root to start with //")
286
287    cmd = [
288        "$(location gen_amalgamated_sql_py)",
289        "--namespace",
290        namespace,
291        "--cpp-out=$@",
292        "$(SRCS)",
293    ]
294
295    perfetto_genrule(
296        name = name + "_gen",
297        cmd = " ".join(cmd),
298        tools = [
299            ":gen_amalgamated_sql_py",
300        ],
301        srcs = deps,
302        outs = outs,
303    )
304
305    perfetto_cc_library(
306        name = name,
307        hdrs = [":" + name + "_gen"],
308        **kwargs,
309    )
310
311def perfetto_cc_tp_tables(name, srcs, outs, deps = [], **kwargs):
312    if PERFETTO_CONFIG.root[:2] != "//":
313        fail("Expected PERFETTO_CONFIG.root to start with //")
314
315    if PERFETTO_CONFIG.root == "//":
316        python_path = PERFETTO_CONFIG.root + "python"
317    else:
318        python_path = PERFETTO_CONFIG.root + "/python"
319
320    perfetto_py_library(
321        name = name + "_lib",
322        deps = [
323            python_path + ":trace_processor_table_generator",
324        ],
325        srcs = srcs,
326    )
327
328    perfetto_py_binary(
329        name = name + "_tool",
330        deps = [
331            ":" + name + "_lib",
332            python_path + ":trace_processor_table_generator",
333        ] + [d + "_lib" for d in deps],
334        srcs = [
335            "tools/gen_tp_table_headers.py",
336        ],
337        main = "tools/gen_tp_table_headers.py",
338        python_version = "PY3",
339    )
340
341    cmd = ["$(location " + name + "_tool)"]
342    cmd += ["--gen-dir", "$(RULEDIR)"]
343    cmd += ["--inputs", "$(SRCS)"]
344    if PERFETTO_CONFIG.root != "//":
345        cmd += ["--import-prefix", PERFETTO_CONFIG.root[2:]]
346        cmd += ["--relative-input-dir", PERFETTO_CONFIG.root[2:]]
347
348    perfetto_genrule(
349        name = name + "_gen",
350        cmd = " ".join(cmd),
351        tools = [
352            ":" + name + "_tool",
353        ],
354        srcs = srcs,
355        outs = outs,
356    )
357
358    perfetto_filegroup(
359        name = name,
360        srcs = [":" + name + "_gen"],
361        **kwargs,
362    )
363
364# +----------------------------------------------------------------------------+
365# | Misc utility functions                                                     |
366# +----------------------------------------------------------------------------+
367
368def _rule_override(rule_name, **kwargs):
369    overrides = getattr(PERFETTO_CONFIG, "rule_overrides", struct())
370    overridden_rule = getattr(overrides, rule_name, None)
371    if overridden_rule:
372        overridden_rule(**kwargs)
373        return True
374    return False
375
376def _merge_dicts(*args):
377    res = {}
378    for arg in args:
379        for k, v in arg.items():
380            if type(v) == "string" or type(v) == "bool":
381                res[k] = v
382            elif type(v) == "list" or type(v) == "select":
383                res[k] = res.get(k, []) + v
384            else:
385                fail("key type not supported: " + type(v))
386    return res
387