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_cc_library(**kwargs): 38 args = _merge_dicts(default_cc_args(), kwargs) 39 if not _rule_override("cc_library", **args): 40 native.cc_library(**args) 41 42def perfetto_cc_binary(**kwargs): 43 args = _merge_dicts(default_cc_args(), kwargs) 44 if not _rule_override("cc_binary", **args): 45 native.cc_binary(**args) 46 47def perfetto_py_binary(**kwargs): 48 if not _rule_override("py_binary", **kwargs): 49 native.py_binary(**kwargs) 50 51def perfetto_py_library(**kwargs): 52 if not _rule_override("py_library", **kwargs): 53 native.py_library(**kwargs) 54 55# +----------------------------------------------------------------------------+ 56# | Proto-related rules | 57# +----------------------------------------------------------------------------+ 58 59def perfetto_proto_library(**kwargs): 60 if not _rule_override("proto_library", **kwargs): 61 native.proto_library(**kwargs) 62 63def perfetto_cc_proto_library(**kwargs): 64 if not _rule_override("cc_proto_library", **kwargs): 65 native.cc_proto_library(**kwargs) 66 67def perfetto_java_proto_library(**kwargs): 68 if not _rule_override("java_proto_library", **kwargs): 69 native.java_proto_library(**kwargs) 70 71def perfetto_java_lite_proto_library(**kwargs): 72 if not _rule_override("java_lite_proto_library", **kwargs): 73 native.java_lite_proto_library(**kwargs) 74 75# +----------------------------------------------------------------------------+ 76# | Misc rules. | 77# +----------------------------------------------------------------------------+ 78 79# Unlike all the other rules, this is an noop by default because Bazel does not 80# support gensignature. 81def perfetto_gensignature_internal_only(**kwargs): 82 _rule_override("gensignature_internal_only", **kwargs) 83 84# Generates .pbzero.{cc,h} from .proto(s). We deliberately do NOT generate 85# conventional .pb.{cc,h} from here as protozero gen sources do not have any 86# dependency on libprotobuf. 87def perfetto_cc_protozero_library(name, deps, **kwargs): 88 if _rule_override( 89 "cc_protozero_library", 90 name = name, 91 deps = deps, 92 **kwargs 93 ): 94 return 95 96 # A perfetto_cc_protozero_library has two types of dependencies: 97 # 1. Exactly one dependency on a proto_library target. This defines the 98 # .proto sources for the target 99 # 2. Zero or more deps on other perfetto_cc_protozero_library targets. This 100 # to deal with the case of foo.proto including common.proto from another 101 # target. 102 _proto_deps = [d for d in deps if d.endswith("_protos")] 103 _cc_deps = [d for d in deps if d not in _proto_deps] 104 if len(_proto_deps) != 1: 105 fail("Too many proto deps for target %s" % name) 106 107 proto_gen( 108 name = name + "_src", 109 deps = _proto_deps, 110 suffix = "pbzero", 111 plugin = PERFETTO_CONFIG.root + ":protozero_plugin", 112 wrapper_namespace = "pbzero", 113 protoc = PERFETTO_CONFIG.deps.protoc[0], 114 root = PERFETTO_CONFIG.root, 115 ) 116 117 native.filegroup( 118 name = name + "_h", 119 srcs = [":" + name + "_src"], 120 output_group = "h", 121 ) 122 123 perfetto_cc_library( 124 name = name, 125 srcs = [":" + name + "_src"], 126 hdrs = [":" + name + "_h"], 127 deps = [PERFETTO_CONFIG.root + ":protozero"] + _cc_deps, 128 **kwargs 129 ) 130 131# Generates .ipc.{cc,h} and .pb.{cc.h} from .proto(s). The IPC sources depend 132# on .pb.h so we need to generate also the standard protobuf sources here. 133def perfetto_cc_ipc_library(name, deps, **kwargs): 134 if _rule_override("cc_ipc_library", name = name, deps = deps, **kwargs): 135 return 136 137 # A perfetto_cc_ipc_library has two types of dependencies: 138 # 1. Exactly one dependency on a proto_library target. This defines the 139 # .proto sources for the target 140 # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This 141 # to deal with the case of foo.proto including common.proto from another 142 # target. 143 _proto_deps = [d for d in deps if d.endswith("_protos")] 144 _cc_deps = [d for d in deps if d not in _proto_deps] 145 if len(_proto_deps) != 1: 146 fail("Too many proto deps for target %s" % name) 147 148 # Generates .ipc.{cc,h}. 149 proto_gen( 150 name = name + "_src", 151 deps = _proto_deps, 152 suffix = "ipc", 153 plugin = PERFETTO_CONFIG.root + ":ipc_plugin", 154 wrapper_namespace = "gen", 155 protoc = PERFETTO_CONFIG.deps.protoc[0], 156 root = PERFETTO_CONFIG.root, 157 ) 158 159 native.filegroup( 160 name = name + "_h", 161 srcs = [":" + name + "_src"], 162 output_group = "h", 163 ) 164 165 perfetto_cc_library( 166 name = name, 167 srcs = [":" + name + "_src"], 168 hdrs = [":" + name + "_h"], 169 deps = [ 170 # Generated .ipc.{cc,h} depend on this and protozero. 171 PERFETTO_CONFIG.root + ":perfetto_ipc", 172 PERFETTO_CONFIG.root + ":protozero", 173 ] + _cc_deps, 174 **kwargs 175 ) 176 177# Generates .gen.{cc,h} from .proto(s). 178def perfetto_cc_protocpp_library(name, deps, **kwargs): 179 if _rule_override( 180 "cc_protocpp_library", 181 name = name, 182 deps = deps, 183 **kwargs 184 ): 185 return 186 187 # A perfetto_cc_protocpp_library has two types of dependencies: 188 # 1. Exactly one dependency on a proto_library target. This defines the 189 # .proto sources for the target 190 # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This 191 # to deal with the case of foo.proto including common.proto from another 192 # target. 193 _proto_deps = [d for d in deps if d.endswith("_protos")] 194 _cc_deps = [d for d in deps if d not in _proto_deps] 195 if len(_proto_deps) != 1: 196 fail("Too many proto deps for target %s" % name) 197 198 proto_gen( 199 name = name + "_gen", 200 deps = _proto_deps, 201 suffix = "gen", 202 plugin = PERFETTO_CONFIG.root + ":cppgen_plugin", 203 wrapper_namespace = "gen", 204 protoc = PERFETTO_CONFIG.deps.protoc[0], 205 root = PERFETTO_CONFIG.root, 206 ) 207 208 native.filegroup( 209 name = name + "_gen_h", 210 srcs = [":" + name + "_gen"], 211 output_group = "h", 212 ) 213 214 # The headers from the gen plugin have implicit dependencies 215 # on each other so will fail when compiled independently. Use 216 # textual_hdrs to indicate this to Bazel. 217 perfetto_cc_library( 218 name = name, 219 srcs = [":" + name + "_gen"], 220 textual_hdrs = [":" + name + "_gen_h"], 221 deps = [ 222 PERFETTO_CONFIG.root + ":protozero", 223 ] + _cc_deps, 224 **kwargs 225 ) 226 227def perfetto_proto_descriptor(name, deps, outs, **kwargs): 228 proto_descriptor_gen( 229 name = name, 230 deps = deps, 231 outs = outs, 232 ) 233 234# Generator .descriptor.h from protos 235def perfetto_cc_proto_descriptor(name, deps, outs, **kwargs): 236 cmd = [ 237 "$(location gen_cc_proto_descriptor_py)", 238 "--cpp_out=$@", 239 "--gen_dir=$(GENDIR)", 240 "$<" 241 ] 242 native.genrule( 243 name = name + "_gen", 244 cmd = " ".join(cmd), 245 exec_tools = [ 246 ":gen_cc_proto_descriptor_py", 247 ], 248 srcs = deps, 249 outs = outs, 250 ) 251 252 perfetto_cc_library( 253 name = name, 254 hdrs = [":" + name + "_gen"], 255 **kwargs 256 ) 257 258# +----------------------------------------------------------------------------+ 259# | Misc utility functions | 260# +----------------------------------------------------------------------------+ 261 262def _rule_override(rule_name, **kwargs): 263 overrides = getattr(PERFETTO_CONFIG, "rule_overrides", struct()) 264 overridden_rule = getattr(overrides, rule_name, None) 265 if overridden_rule: 266 overridden_rule(**kwargs) 267 return True 268 return False 269 270def _merge_dicts(*args): 271 res = {} 272 for arg in args: 273 for k, v in arg.items(): 274 if type(v) == "string" or type(v) == "bool": 275 res[k] = v 276 elif type(v) == "list" or type(v) == "select": 277 res[k] = res.get(k, []) + v 278 else: 279 fail("key type not supported: " + type(v)) 280 return res 281