Merge rust_protobuf and rust_grpcio module types.
To allow grpc protobufs to include non-grpc protos in a singular
library, we need to allow them to be defined as part of the same module.
This CL merges the two previously distinct module types into
rust_protobuf, and adds a new property for declaring which protos
contain grpc definitions.
Bug: 172952239
Test: rust_grpcio modules converted to rust_protobuf modules and build.
Test: Example rust_protobuf module with both proto types builds.
Change-Id: I0e627fd97bc6f74de89d309e3344694a1e76586d
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 4fba34f..b91fea8 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -31,24 +31,22 @@
type PluginType int
-const (
- Protobuf PluginType = iota
- Grpc
-)
-
func init() {
android.RegisterModuleType("rust_protobuf", RustProtobufFactory)
android.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)
- android.RegisterModuleType("rust_grpcio", RustGrpcioFactory)
- android.RegisterModuleType("rust_grpcio_host", RustGrpcioHostFactory)
}
var _ SourceProvider = (*protobufDecorator)(nil)
type ProtobufProperties struct {
- // List of relative paths to proto files that will be used to generate the source
+ // List of relative paths to proto files that will be used to generate the source.
+ // Either this or grpc_protos must be defined.
Protos []string `android:"path,arch_variant"`
+ // List of relative paths to GRPC-containing proto files that will be used to generate the source.
+ // Either this or protos must be defined.
+ Grpc_protos []string `android:"path,arch_variant"`
+
// List of additional flags to pass to aprotoc
Proto_flags []string `android:"arch_variant"`
@@ -60,33 +58,54 @@
*BaseSourceProvider
Properties ProtobufProperties
- plugin PluginType
+ protoNames []string
+ grpcNames []string
+
+ grpcProtoFlags android.ProtoFlags
+ protoFlags android.ProtoFlags
}
func (proto *protobufDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
var protoFlags android.ProtoFlags
- var pluginPaths android.Paths
- var protoNames []string
+ var grpcProtoFlags android.ProtoFlags
+ var commonProtoFlags []string
- protoFlags.OutTypeFlag = "--rust_out"
outDir := android.PathForModuleOut(ctx)
-
- pluginPaths, protoFlags = proto.setupPlugin(ctx, protoFlags, outDir)
-
- protoFlags.Flags = append(protoFlags.Flags, defaultProtobufFlags...)
- protoFlags.Flags = append(protoFlags.Flags, proto.Properties.Proto_flags...)
-
- protoFlags.Deps = append(protoFlags.Deps, pluginPaths...)
-
protoFiles := android.PathsForModuleSrc(ctx, proto.Properties.Protos)
+ grpcFiles := android.PathsForModuleSrc(ctx, proto.Properties.Grpc_protos)
+ protoPluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
- if len(protoFiles) == 0 {
- ctx.PropertyErrorf("protos", "at least one protobuf must be defined.")
+ commonProtoFlags = append(commonProtoFlags, defaultProtobufFlags...)
+ commonProtoFlags = append(commonProtoFlags, proto.Properties.Proto_flags...)
+ commonProtoFlags = append(commonProtoFlags, "--plugin=protoc-gen-rust="+protoPluginPath.String())
+
+ if len(protoFiles) > 0 {
+ protoFlags.OutTypeFlag = "--rust_out"
+ protoFlags.Flags = append(protoFlags.Flags, commonProtoFlags...)
+
+ protoFlags.Deps = append(protoFlags.Deps, protoPluginPath)
+ }
+
+ if len(grpcFiles) > 0 {
+ grpcPath := ctx.Config().HostToolPath(ctx, "grpc_rust_plugin")
+
+ grpcProtoFlags.OutTypeFlag = "--rust_out"
+ grpcProtoFlags.Flags = append(grpcProtoFlags.Flags, "--grpc_out="+outDir.String())
+ grpcProtoFlags.Flags = append(grpcProtoFlags.Flags, "--plugin=protoc-gen-grpc="+grpcPath.String())
+ grpcProtoFlags.Flags = append(grpcProtoFlags.Flags, commonProtoFlags...)
+
+ grpcProtoFlags.Deps = append(grpcProtoFlags.Deps, grpcPath, protoPluginPath)
+ }
+
+ if len(protoFiles) == 0 && len(grpcFiles) == 0 {
+ ctx.PropertyErrorf("protos",
+ "at least one protobuf must be defined in either protos or grpc_protos.")
}
// Add exported dependency include paths
for _, include := range deps.depIncludePaths {
protoFlags.Flags = append(protoFlags.Flags, "-I"+include.String())
+ grpcProtoFlags.Flags = append(grpcProtoFlags.Flags, "-I"+include.String())
}
stem := proto.BaseSourceProvider.getStem(ctx)
@@ -98,25 +117,50 @@
var outputs android.WritablePaths
rule := android.NewRuleBuilder(pctx, ctx)
+
for _, protoFile := range protoFiles {
- protoName := strings.TrimSuffix(protoFile.Base(), ".proto")
- protoNames = append(protoNames, protoName)
-
- protoOut := android.PathForModuleOut(ctx, protoName+".rs")
- ruleOutputs := android.WritablePaths{android.WritablePath(protoOut)}
-
- if proto.plugin == Grpc {
- grpcOut := android.PathForModuleOut(ctx, protoName+grpcSuffix+".rs")
- ruleOutputs = append(ruleOutputs, android.WritablePath(grpcOut))
+ // Since we're iterating over the protoFiles already, make sure they're not redeclared in grpcFiles
+ if android.InList(protoFile.String(), grpcFiles.Strings()) {
+ ctx.PropertyErrorf("protos",
+ "A proto can only be added once to either grpc_protos or protos. %q is declared in both properties",
+ protoFile.String())
}
+ protoName := strings.TrimSuffix(protoFile.Base(), ".proto")
+ proto.protoNames = append(proto.protoNames, protoName)
+
+ protoOut := android.PathForModuleOut(ctx, protoName+".rs")
depFile := android.PathForModuleOut(ctx, protoName+".d")
+ ruleOutputs := android.WritablePaths{protoOut, depFile}
+
android.ProtoRule(rule, protoFile, protoFlags, protoFlags.Deps, outDir, depFile, ruleOutputs)
outputs = append(outputs, ruleOutputs...)
}
- android.WriteFileRule(ctx, stemFile, proto.genModFileContents(ctx, protoNames))
+ for _, grpcFile := range grpcFiles {
+ grpcName := strings.TrimSuffix(grpcFile.Base(), ".proto")
+ proto.grpcNames = append(proto.grpcNames, grpcName)
+
+ // GRPC protos produce two files, a proto.rs and a proto_grpc.rs
+ protoOut := android.WritablePath(android.PathForModuleOut(ctx, grpcName+".rs"))
+ grpcOut := android.WritablePath(android.PathForModuleOut(ctx, grpcName+grpcSuffix+".rs"))
+ depFile := android.PathForModuleOut(ctx, grpcName+".d")
+
+ ruleOutputs := android.WritablePaths{protoOut, grpcOut, depFile}
+
+ android.ProtoRule(rule, grpcFile, grpcProtoFlags, grpcProtoFlags.Deps, outDir, depFile, ruleOutputs)
+ outputs = append(outputs, ruleOutputs...)
+ }
+
+ // Check that all proto base filenames are unique as outputs are written to the same directory.
+ baseFilenames := append(proto.protoNames, proto.grpcNames...)
+ if len(baseFilenames) != len(android.FirstUniqueStrings(baseFilenames)) {
+ ctx.PropertyErrorf("protos", "proto filenames must be unique across 'protos' and 'grpc_protos' "+
+ "to be used in the same rust_protobuf module. For example, foo.proto and src/foo.proto will conflict.")
+ }
+
+ android.WriteFileRule(ctx, stemFile, proto.genModFileContents())
rule.Build("protoc_"+ctx.ModuleName(), "protoc "+ctx.ModuleName())
@@ -127,19 +171,19 @@
return stemFile
}
-func (proto *protobufDecorator) genModFileContents(ctx ModuleContext, protoNames []string) string {
+func (proto *protobufDecorator) genModFileContents() string {
lines := []string{
"// @Soong generated Source",
}
- for _, protoName := range protoNames {
+ for _, protoName := range proto.protoNames {
lines = append(lines, fmt.Sprintf("pub mod %s;", protoName))
-
- if proto.plugin == Grpc {
- lines = append(lines, fmt.Sprintf("pub mod %s%s;", protoName, grpcSuffix))
- }
}
- if proto.plugin == Grpc {
+ for _, grpcName := range proto.grpcNames {
+ lines = append(lines, fmt.Sprintf("pub mod %s;", grpcName))
+ lines = append(lines, fmt.Sprintf("pub mod %s%s;", grpcName, grpcSuffix))
+ }
+ if len(proto.grpcNames) > 0 {
lines = append(
lines,
"pub mod empty {",
@@ -150,27 +194,6 @@
return strings.Join(lines, "\n")
}
-func (proto *protobufDecorator) setupPlugin(ctx ModuleContext, protoFlags android.ProtoFlags, outDir android.ModuleOutPath) (android.Paths, android.ProtoFlags) {
- pluginPaths := []android.Path{}
-
- if proto.plugin == Protobuf {
- pluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
- pluginPaths = append(pluginPaths, pluginPath)
- protoFlags.Flags = append(protoFlags.Flags, "--plugin="+pluginPath.String())
- } else if proto.plugin == Grpc {
- grpcPath := ctx.Config().HostToolPath(ctx, "grpc_rust_plugin")
- protobufPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
- pluginPaths = append(pluginPaths, grpcPath, protobufPath)
- protoFlags.Flags = append(protoFlags.Flags, "--grpc_out="+outDir.String())
- protoFlags.Flags = append(protoFlags.Flags, "--plugin=protoc-gen-grpc="+grpcPath.String())
- protoFlags.Flags = append(protoFlags.Flags, "--plugin=protoc-gen-rust="+protobufPath.String())
- } else {
- ctx.ModuleErrorf("Unknown protobuf plugin type requested")
- }
-
- return pluginPaths, protoFlags
-}
-
func (proto *protobufDecorator) SourceProviderProps() []interface{} {
return append(proto.BaseSourceProvider.SourceProviderProps(), &proto.Properties)
}
@@ -180,7 +203,7 @@
deps.Rustlibs = append(deps.Rustlibs, "libprotobuf")
deps.HeaderLibs = append(deps.SharedLibs, proto.Properties.Header_libs...)
- if proto.plugin == Grpc {
+ if len(proto.Properties.Grpc_protos) > 0 {
deps.Rustlibs = append(deps.Rustlibs, "libgrpcio", "libfutures")
deps.HeaderLibs = append(deps.HeaderLibs, "libprotobuf-cpp-full")
}
@@ -203,34 +226,10 @@
return module.Init()
}
-func RustGrpcioFactory() android.Module {
- module, _ := NewRustGrpcio(android.HostAndDeviceSupported)
- return module.Init()
-}
-
-// A host-only variant of rust_protobuf. Refer to rust_protobuf for more details.
-func RustGrpcioHostFactory() android.Module {
- module, _ := NewRustGrpcio(android.HostSupported)
- return module.Init()
-}
-
func NewRustProtobuf(hod android.HostOrDeviceSupported) (*Module, *protobufDecorator) {
protobuf := &protobufDecorator{
BaseSourceProvider: NewSourceProvider(),
Properties: ProtobufProperties{},
- plugin: Protobuf,
- }
-
- module := NewSourceProviderModule(hod, protobuf, false)
-
- return module, protobuf
-}
-
-func NewRustGrpcio(hod android.HostOrDeviceSupported) (*Module, *protobufDecorator) {
- protobuf := &protobufDecorator{
- BaseSourceProvider: NewSourceProvider(),
- Properties: ProtobufProperties{},
- plugin: Grpc,
}
module := NewSourceProviderModule(hod, protobuf, false)