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