blob: 68b7904acca817cbe33225220d132742b4a8fdeb [file] [log] [blame]
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Compile protocol buffers.
#
# Paramaeters:
# proto_in_dir
# Input directory.
# proto_out_dir
# Output directory.
# proto_lib_dirs (optional)
# Directories to search for protos a proto file depends on.
# proto_in_dir and "${sysroot}/usr/share/proto" are always included.
# sources
# The proto file paths.
# configs (optional)
# Configs applied to the generated library.
# deps (optional)
# Deps applied to the generated library.
# gen_python (optional)
# If true, generates Python binding.
# gen_grpc (optional)
# If true, generates C++ GRPC.
# gen_grpc_gmock (optional)
# If true, along with gen_grpc, generates C++ GRPC gmock objects as well.
# gen_cpp_mode (optional)
# If defined, ignores the OPTIMIZE_FOR lines in protos and generates code
# with the specified optimization mode (lite or speed). For fuzzer builds
# this defaults to speed to support libprotobuf-mutator.
# use_pic (optional)
# If true, generates a position independent code instead of position independent executable.
# standalone
# If true, generates a library that can be referred from other packages.
# Otherwise it generates a thin archive assuming it's used inside the same package only.
template("proto_library") {
action_name = "${target_name}_gen"
action_foreach(action_name) {
visibility = [ ":*" ]
forward_variables_from(invoker,
[
"proto_in_dir",
"proto_out_dir",
"gen_python",
"gen_grpc",
"gen_grpc_gmock",
"gen_cpp_mode",
# Sources might be generated by actions in deps,
# which must be explicitly specified.
"deps",
"public_deps",
"sources",
])
cc_dir = "${root_gen_dir}/${proto_out_dir}"
proto_in_dir = rebase_path(proto_in_dir)
proto_out_dir = rebase_path(proto_out_dir)
proto_lib_dirs = [
proto_in_dir,
"${sysroot}/usr/share/proto",
]
if (defined(invoker.proto_lib_dirs)) {
proto_lib_dirs += rebase_path(invoker.proto_lib_dirs)
}
if (!defined(gen_python)) {
gen_python = false
}
if (!defined(gen_grpc)) {
gen_grpc = false
}
if (gen_grpc && !defined(gen_grpc_gmock)) {
gen_grpc_gmock = false
}
if (defined(gen_cpp_mode)) {
gen_cpp_mode = "${gen_cpp_mode}:"
} else if (use.fuzzer) {
gen_cpp_mode = "speed:"
} else {
gen_cpp_mode = ""
}
script = "//common-mk/file_generator_wrapper.py"
args = [ "protoc" ]
foreach(x, proto_lib_dirs) {
args += [
"--proto_path",
x,
]
}
args += [ "${proto_in_dir}/{{source_name_part}}.proto" ]
outputs = []
if (gen_python) {
python_dir = "${root_gen_dir}/${proto_out_dir}/py"
args += [
"--python_out",
"${python_dir}",
]
outputs += [ "${python_dir}/{{source_name_part}}_pb.py" ]
}
if (gen_grpc) {
if (gen_grpc_gmock) {
args += [ "--grpc_out=generate_mock_code=true:${cc_dir}" ]
outputs += [ "${cc_dir}/{{source_name_part}}_mock.grpc.pb.h" ]
} else {
args += [ "--grpc_out=${cc_dir}" ]
}
grpc_cpp_plugin = "/usr/bin/grpc_cpp_plugin"
args += [
"--plugin=protoc-gen-grpc=${grpc_cpp_plugin}",
"--cpp_out=${gen_cpp_mode}${cc_dir}",
]
outputs += [
"${cc_dir}/{{source_name_part}}.grpc.pb.cc",
"${cc_dir}/{{source_name_part}}.grpc.pb.h",
"${cc_dir}/{{source_name_part}}.pb.cc",
"${cc_dir}/{{source_name_part}}.pb.h",
]
}
if (!gen_grpc && !gen_python) {
args += [ "--cpp_out=${gen_cpp_mode}${cc_dir}" ]
outputs += [
"${cc_dir}/{{source_name_part}}.pb.cc",
"${cc_dir}/{{source_name_part}}.pb.h",
]
}
}
all_dependent_config_name = "_${target_name}_all_dependent_config"
config(all_dependent_config_name) {
# Allows for dependents to include protoc-generated header files with relative path from
# root_gen_dir i.e. in the form of "${proto_out_dir}/<generated file basename>".
include_dirs = [ root_gen_dir ]
}
static_library(target_name) {
forward_variables_from(
invoker,
[
"defines",
"public_configs",
"public_deps",
"visibility",
# TODO(oka): we should not have to use all_dependent_pkg_deps here, because there is no
# inherent reason that all users of this target should depend on some external
# dependency. Remove this after no user uses it.
"all_dependent_pkg_deps",
])
if (defined(invoker.configs)) {
configs += invoker.configs
}
if (defined(invoker.use_pic) && invoker.use_pic) {
configs -= [ "//common-mk:pie" ]
configs += [ "//common-mk:pic" ]
}
if (defined(invoker.standalone) && invoker.standalone) {
configs -= [ "//common-mk:use_thin_archive" ]
configs += [
"//common-mk:nouse_thin_archive",
# Generated code. Cannot modify individual symbol attributes there easily.
# gnlint: disable=GnLintVisibilityFlags
"//common-mk:visibility_default",
]
}
all_dependent_configs = [ ":${all_dependent_config_name}" ]
if (defined(invoker.all_dependent_configs)) {
all_dependent_configs += invoker.all_dependent_configs
}
sources = get_target_outputs(":${action_name}")
deps = [ ":${action_name}" ]
if (defined(invoker.deps)) {
deps += invoker.deps
}
cflags_cc = [
# Protobuf 3.7.0 introduced generated code that is sometimes unreachable.
"-Wno-unreachable-code",
# Protobuf 3.11.4 generates deprecated declarations which lead to warnings
# that shouldn't be treated as errors in generated code.
"-Wno-deprecated-declarations",
]
}
}
# Compile protocol buffers to Go.
#
# Parameters:
# proto_in_dir
# Input directory.
# proto_out_dir
# Output directory. Relative to gen directory.
# sources
# The proto file paths.
# gen_grpc (optional)
# If true, generates Go GRPC.
# import_mapping (optional)
# List of mapping to convert imports in .proto file to go package names.
# The format is "foo/bar.proto=quux/shme".
# proto_lib_dirs (optional)
# Directories to search for protos a proto file depends on.
# proto_in_dir and "${sysroot}/usr/share/proto" are added by default.
template("goproto_library") {
action(target_name) {
forward_variables_from(invoker,
[
"proto_out_dir",
"sources",
])
# For go, it is necessary to generate the code in one command line,
# otherwise file descriptor var name will conflict.
# cf) https://github.com/golang/protobuf/issues/109
proto_in_dir = rebase_path(invoker.proto_in_dir)
# Build protoc command line to run.
script = "//common-mk/file_generator_wrapper.py"
proto_lib_dirs = [
proto_in_dir,
"${sysroot}/usr/share/proto",
]
if (defined(invoker.proto_lib_dirs)) {
proto_lib_dirs += rebase_path(invoker.proto_lib_dirs)
}
go_plugin_parameters = []
if (defined(invoker.gen_grpc) && invoker.gen_grpc) {
go_plugin_parameters += [ "plugins=grpc" ]
}
if (defined(invoker.import_mapping)) {
foreach(x, invoker.import_mapping) {
go_plugin_parameters += [ "M" + x ]
}
}
go_out_prefix = string_join(",", go_plugin_parameters)
args = [ "protoc" ]
foreach(x, proto_lib_dirs) {
args += [
"--proto_path",
x,
]
}
args += [
"--go_out",
# go_out_prefix can be empty, so we can always add a colon here.
"${go_out_prefix}:${root_gen_dir}/${proto_out_dir}",
]
foreach(source, sources) {
args += [ rebase_path(source) ]
}
# Output dependency.
outputs = []
foreach(source, invoker.sources) {
name = get_path_info(source, "name")
outputs += [ "${root_gen_dir}/${proto_out_dir}/${name}.pb.go" ]
}
}
}