238 lines
7.9 KiB
Python
238 lines
7.9 KiB
Python
# Copyright 2022 The Pigweed Authors
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
# use this file except in compliance with the License. You may obtain a copy of
|
|
# the License at
|
|
#
|
|
# https://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations under
|
|
# the License.
|
|
|
|
"""Backend implementation for 'pw_protobuf_compiler/proto.bzl'"""
|
|
|
|
# Apache License, Version 2.0, January 2004, http://www.apache.org/licenses/
|
|
# Adapted from: https://github.com/rules-proto-grpc/rules_proto_grpc/
|
|
# Files adapted:
|
|
# - rules_proto_grpc/cpp/cpp_grpc_library.bzl
|
|
# - rules_proto_grpc/cpp/cpp_grpc_compile.bzl
|
|
# These two files have been adapted for use in Pigweed and combined into this
|
|
# file.
|
|
|
|
load("@rules_proto//proto:defs.bzl", "ProtoInfo")
|
|
load(
|
|
"@rules_proto_grpc//:defs.bzl",
|
|
"ProtoLibraryAspectNodeInfo",
|
|
"ProtoPluginInfo",
|
|
"proto_compile_aspect_attrs",
|
|
"proto_compile_aspect_impl",
|
|
"proto_compile_attrs",
|
|
"proto_compile_impl",
|
|
)
|
|
load("@rules_proto_grpc//internal:filter_files.bzl", "filter_files")
|
|
|
|
# Create compile rule
|
|
def _proto_compiler_aspect(plugin_group, prefix):
|
|
return aspect(
|
|
implementation = proto_compile_aspect_impl,
|
|
provides = [ProtoLibraryAspectNodeInfo],
|
|
attr_aspects = ["deps"],
|
|
attrs = dict(
|
|
proto_compile_aspect_attrs,
|
|
_plugins = attr.label_list(
|
|
doc = "List of protoc plugins to apply",
|
|
providers = [ProtoPluginInfo],
|
|
default = plugin_group,
|
|
),
|
|
_prefix = attr.string(
|
|
doc = "String used to disambiguate aspects when generating \
|
|
outputs",
|
|
default = prefix,
|
|
),
|
|
),
|
|
toolchains = [str(Label("@rules_proto_grpc//protobuf:toolchain_type"))],
|
|
)
|
|
|
|
def _proto_compiler_rule(plugin_group, aspect):
|
|
return rule(
|
|
implementation = proto_compile_impl,
|
|
attrs = dict(
|
|
proto_compile_attrs,
|
|
_plugins = attr.label_list(
|
|
doc = "List of protoc plugins to apply",
|
|
providers = [ProtoPluginInfo],
|
|
default = plugin_group,
|
|
),
|
|
protos = attr.label_list(
|
|
providers = [ProtoInfo],
|
|
doc = "List of proto_library targets.",
|
|
),
|
|
deps = attr.label_list(
|
|
doc = "List of proto_library targets. Prefer protos.",
|
|
aspects = [aspect],
|
|
),
|
|
),
|
|
toolchains = [str(Label("@rules_proto_grpc//protobuf:toolchain_type"))],
|
|
)
|
|
|
|
nanopb_compile_aspect = _proto_compiler_aspect(
|
|
[Label("//pw_rpc:nanopb_plugin")],
|
|
"nanopb_proto_compile_aspect",
|
|
)
|
|
nanopb_compile = _proto_compiler_rule(
|
|
[Label("//pw_rpc:nanopb_plugin")],
|
|
nanopb_compile_aspect,
|
|
)
|
|
|
|
pwpb_compile_aspect = _proto_compiler_aspect(
|
|
[Label("@pigweed//pw_protobuf:pw_cc_plugin")],
|
|
"pwpb_proto_compile_aspect",
|
|
)
|
|
pwpb_compile = _proto_compiler_rule(
|
|
[Label("@pigweed//pw_protobuf:pw_cc_plugin")],
|
|
pwpb_compile_aspect,
|
|
)
|
|
|
|
raw_rpc_compile_aspect = _proto_compiler_aspect(
|
|
[Label("@pigweed//pw_rpc:pw_cc_plugin_raw")],
|
|
"raw_rpc_proto_compile_aspect",
|
|
)
|
|
raw_rpc_compile = _proto_compiler_rule(
|
|
[Label("@pigweed//pw_rpc:pw_cc_plugin_raw")],
|
|
raw_rpc_compile_aspect,
|
|
)
|
|
|
|
nanopb_rpc_compile_aspect = _proto_compiler_aspect(
|
|
[
|
|
Label("@pigweed//pw_rpc:pw_cc_plugin_nanopb_rpc"),
|
|
Label("//pw_rpc:nanopb_plugin"),
|
|
],
|
|
"nanopb_rpc_proto_compile_aspect",
|
|
)
|
|
nanopb_rpc_compile = _proto_compiler_rule(
|
|
[
|
|
Label("@pigweed//pw_rpc:pw_cc_plugin_nanopb_rpc"),
|
|
Label("//pw_rpc:nanopb_plugin"),
|
|
],
|
|
nanopb_rpc_compile_aspect,
|
|
)
|
|
|
|
PLUGIN_INFO = {
|
|
"nanopb": {
|
|
"compiler": nanopb_compile,
|
|
"deps": ["@com_github_nanopb_nanopb//:nanopb"],
|
|
"has_srcs": True,
|
|
# TODO: Find a way to get Nanopb to generate nested structs.
|
|
# Otherwise add the manual tag to the resulting library,
|
|
# preventing it from being built unless directly depended on.
|
|
# e.g. The 'Pigweed' message in
|
|
# pw_protobuf/pw_protobuf_test_protos/full_test.proto will fail to
|
|
# compile as it has a self referring nested message. According to
|
|
# the docs
|
|
# https://jpa.kapsi.fi/nanopb/docs/reference.html#proto-file-options
|
|
# and https://github.com/nanopb/nanopb/issues/433 it seams like it
|
|
# should be possible to configure nanopb to generate nested structs.
|
|
"additional_tags": ["manual"],
|
|
},
|
|
"nanopb_rpc": {
|
|
"compiler": nanopb_rpc_compile,
|
|
"deps": [
|
|
"@com_github_nanopb_nanopb//:nanopb",
|
|
"@pigweed//pw_rpc/nanopb:server_api",
|
|
"@pigweed//pw_rpc/nanopb:client_api",
|
|
"@pigweed//pw_rpc",
|
|
],
|
|
"has_srcs": True,
|
|
# See above todo.
|
|
"additional_tags": ["manual"],
|
|
},
|
|
"pwpb": {
|
|
"compiler": pwpb_compile,
|
|
"deps": ["@pigweed//pw_protobuf"],
|
|
"has_srcs": False,
|
|
"additional_tags": [],
|
|
},
|
|
"raw_rpc": {
|
|
"compiler": raw_rpc_compile,
|
|
"deps": [
|
|
"@pigweed//pw_rpc",
|
|
"@pigweed//pw_rpc/raw:server_api",
|
|
"@pigweed//pw_rpc/raw:client_api",
|
|
],
|
|
"has_srcs": False,
|
|
"additional_tags": [],
|
|
},
|
|
}
|
|
|
|
def pw_proto_library(name, **kwargs): # buildifier: disable=function-docstring
|
|
for plugin_name, info in PLUGIN_INFO.items():
|
|
name_pb = name + "_pb" + "." + plugin_name
|
|
additional_tags = [
|
|
tag
|
|
for tag in info["additional_tags"]
|
|
if tag not in kwargs.get("tags", [])
|
|
]
|
|
info["compiler"](
|
|
name = name_pb,
|
|
tags = additional_tags,
|
|
# Forward deps and verbose tags to implementation
|
|
verbose = kwargs.get("verbose", 0),
|
|
deps = kwargs.get("deps", []),
|
|
protos = kwargs.get("protos", []),
|
|
)
|
|
|
|
# Filter files to sources and headers
|
|
filter_files(
|
|
name = name_pb + "_srcs",
|
|
target = name_pb,
|
|
extensions = ["c", "cc", "cpp", "cxx"],
|
|
tags = additional_tags,
|
|
)
|
|
|
|
filter_files(
|
|
name = name_pb + "_hdrs",
|
|
target = name_pb,
|
|
extensions = ["h"],
|
|
tags = additional_tags,
|
|
)
|
|
|
|
# Cannot use pw_cc_library here as it will add cxxopts.
|
|
# Note that the srcs attribute here is passed in as a DefaultInfo
|
|
# object, which is not supported by pw_cc_library.
|
|
native.cc_library(
|
|
name = name + "." + plugin_name,
|
|
hdrs = [name_pb + "_hdrs"],
|
|
includes = [name_pb],
|
|
alwayslink = kwargs.get("alwayslink"),
|
|
copts = kwargs.get("copts", []),
|
|
defines = kwargs.get("defines", []),
|
|
srcs = [name_pb + "_srcs"] if info["has_srcs"] else [],
|
|
deps = info["deps"],
|
|
include_prefix = kwargs.get("include_prefix", ""),
|
|
linkopts = kwargs.get("linkopts", []),
|
|
linkstatic = kwargs.get("linkstatic", True),
|
|
local_defines = kwargs.get("local_defines", []),
|
|
nocopts = kwargs.get("nocopts", ""),
|
|
visibility = kwargs.get("visibility"),
|
|
tags = kwargs.get("tags", []) + additional_tags,
|
|
)
|
|
|
|
if "manual" in kwargs.get("tags", []):
|
|
additional_tags = []
|
|
else:
|
|
additional_tags = ["manual"]
|
|
|
|
# Combine all plugins into a single library.
|
|
native.cc_library(
|
|
name = name,
|
|
deps = [
|
|
name + "." + plugin_name
|
|
for plugin_name in PLUGIN_INFO.keys()
|
|
],
|
|
tags = kwargs.get("tags", []) + additional_tags,
|
|
**{k: v for k, v in kwargs.items() if k not in ["deps", "protos"]}
|
|
)
|