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": [ 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 Python proto libraries. 89def perfetto_py_proto_library(**kwargs): 90 _rule_override("py_proto_library", **kwargs) 91 92# +----------------------------------------------------------------------------+ 93# | Misc rules. | 94# +----------------------------------------------------------------------------+ 95 96# Unlike the other rules, this is an noop by default because Bazel does not 97# support gensignature. 98def perfetto_gensignature_internal_only(**kwargs): 99 _rule_override("gensignature_internal_only", **kwargs) 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 exec_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 283# +----------------------------------------------------------------------------+ 284# | Misc utility functions | 285# +----------------------------------------------------------------------------+ 286 287def _rule_override(rule_name, **kwargs): 288 overrides = getattr(PERFETTO_CONFIG, "rule_overrides", struct()) 289 overridden_rule = getattr(overrides, rule_name, None) 290 if overridden_rule: 291 overridden_rule(**kwargs) 292 return True 293 return False 294 295def _merge_dicts(*args): 296 res = {} 297 for arg in args: 298 for k, v in arg.items(): 299 if type(v) == "string" or type(v) == "bool": 300 res[k] = v 301 elif type(v) == "list" or type(v) == "select": 302 res[k] = res.get(k, []) + v 303 else: 304 fail("key type not supported: " + type(v)) 305 return res 306