1# Copyright (C) 2021 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("@bazel_skylib//lib:paths.bzl", "paths") 16load("//build/bazel/rules:proto_file_utils.bzl", "proto_file_utils") 17load(":cc_library_common.bzl", "create_ccinfo_for_includes") 18load(":cc_library_static.bzl", "cc_library_static") 19 20_SOURCES_KEY = "sources" 21_HEADERS_KEY = "headers" 22PROTO_GEN_NAME_SUFFIX = "_proto_gen" 23 24def _cc_proto_sources_gen_rule_impl(ctx): 25 out_flags = [] 26 plugin_executable = None 27 out_arg = None 28 if ctx.attr.plugin: 29 plugin_executable = ctx.executable.plugin 30 else: 31 out_arg = "--cpp_out" 32 if ctx.attr.out_format: 33 out_flags.append(ctx.attr.out_format) 34 35 srcs = [] 36 hdrs = [] 37 includes = [] 38 proto_infos = [] 39 transitive_proto_infos = [] 40 41 for dep in ctx.attr.deps: 42 proto_info = dep[ProtoInfo] 43 proto_infos.append(proto_info) 44 if proto_info.proto_source_root == ".": 45 includes.append(paths.join(ctx.label.name, ctx.label.package)) 46 47 includes.append(ctx.label.name) 48 49 for transitive_dep in ctx.attr.transitive_deps: 50 transitive_proto_infos.append(transitive_dep[ProtoInfo]) 51 52 outs = _generate_cc_proto_action( 53 proto_infos = proto_infos, 54 protoc = ctx.executable._protoc, 55 ctx = ctx, 56 is_cc = True, 57 out_flags = out_flags, 58 plugin_executable = plugin_executable, 59 out_arg = out_arg, 60 transitive_proto_infos = transitive_proto_infos, 61 ) 62 srcs.extend(outs[_SOURCES_KEY]) 63 hdrs.extend(outs[_HEADERS_KEY]) 64 65 return [ 66 DefaultInfo(files = depset(direct = srcs + hdrs)), 67 create_ccinfo_for_includes(ctx, hdrs = hdrs, includes = includes), 68 ] 69 70_cc_proto_sources_gen = rule( 71 implementation = _cc_proto_sources_gen_rule_impl, 72 attrs = { 73 "deps": attr.label_list( 74 providers = [ProtoInfo], 75 doc = """ 76proto_library or any other target exposing ProtoInfo provider with *.proto files 77""", 78 mandatory = True, 79 ), 80 "transitive_deps": attr.label_list( 81 providers = [ProtoInfo], 82 doc = """ 83proto_library that will be added to aprotoc -I when compiling the direct .proto sources. 84WARNING: This is an experimental attribute and is expected to be deprecated in the future. 85""", 86 ), 87 "_protoc": attr.label( 88 default = Label("//external/protobuf:aprotoc"), 89 executable = True, 90 cfg = "exec", 91 ), 92 "plugin": attr.label( 93 executable = True, 94 cfg = "exec", 95 ), 96 "out_format": attr.string( 97 doc = """ 98Optional argument specifying the out format, e.g. lite. 99If not provided, defaults to full protos. 100""", 101 ), 102 }, 103 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 104 provides = [CcInfo], 105) 106 107def _src_extension(is_cc): 108 if is_cc: 109 return "cc" 110 return "c" 111 112def _generate_cc_proto_action( 113 proto_infos, 114 protoc, 115 ctx, 116 transitive_proto_infos, 117 plugin_executable, 118 out_arg, 119 out_flags, 120 is_cc): 121 type_dictionary = { 122 _SOURCES_KEY: ".pb." + _src_extension(is_cc), 123 _HEADERS_KEY: ".pb.h", 124 } 125 return proto_file_utils.generate_proto_action( 126 proto_infos, 127 protoc, 128 ctx, 129 type_dictionary, 130 out_flags, 131 plugin_executable = plugin_executable, 132 out_arg = out_arg, 133 mnemonic = "CcProtoGen", 134 transitive_proto_infos = transitive_proto_infos, 135 ) 136 137def _cc_proto_library( 138 name, 139 deps = [], 140 transitive_deps = [], 141 cc_deps = [], 142 plugin = None, 143 tags = [], 144 target_compatible_with = [], 145 out_format = None, 146 **kwargs): 147 proto_lib_name = name + PROTO_GEN_NAME_SUFFIX 148 149 _cc_proto_sources_gen( 150 name = proto_lib_name, 151 deps = deps, 152 transitive_deps = transitive_deps, 153 plugin = plugin, 154 out_format = out_format, 155 tags = ["manual"], 156 ) 157 158 cc_library_static( 159 name = name, 160 srcs = [":" + proto_lib_name], 161 deps = [proto_lib_name] + cc_deps, 162 local_includes = ["."], 163 tags = tags, 164 target_compatible_with = target_compatible_with, 165 **kwargs 166 ) 167 168def cc_lite_proto_library( 169 name, 170 deps = [], 171 transitive_deps = [], 172 cc_deps = [], 173 plugin = None, 174 tags = [], 175 target_compatible_with = [], 176 **kwargs): 177 _cc_proto_library( 178 name, 179 deps = deps, 180 transitive_deps = transitive_deps, 181 cc_deps = cc_deps + ["//external/protobuf:libprotobuf-cpp-lite"], 182 plugin = plugin, 183 tags = tags, 184 target_compatible_with = target_compatible_with, 185 out_format = "lite", 186 **kwargs 187 ) 188 189def cc_proto_library( 190 name, 191 deps = [], 192 transitive_deps = [], 193 cc_deps = [], 194 plugin = None, 195 tags = [], 196 target_compatible_with = [], 197 **kwargs): 198 _cc_proto_library( 199 name, 200 deps = deps, 201 transitive_deps = transitive_deps, 202 cc_deps = cc_deps + ["//external/protobuf:libprotobuf-cpp-full"], 203 plugin = plugin, 204 tags = tags, 205 target_compatible_with = target_compatible_with, 206 **kwargs 207 ) 208