Rust: WriteFileRule instead of printf for protos

Use WriteFileRule instead of a rule that calls printf for generating the
module source file for rust_protobuf.

Bug: 171361369
Test: rust_protobuf modules compile
Change-Id: Ie83a30e19d7d09875f3d209662526783862d8ea0
diff --git a/rust/builder.go b/rust/builder.go
index 6079e30..8ec2da2 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -189,6 +189,7 @@
 	implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
 	implicits = append(implicits, deps.StaticLibs...)
 	implicits = append(implicits, deps.SharedLibs...)
+	implicits = append(implicits, deps.srcProviderFiles...)
 
 	if deps.CrtBegin.Valid() {
 		implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path())
diff --git a/rust/library.go b/rust/library.go
index 971588d..9005f0c 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -430,6 +430,7 @@
 	if library.sourceProvider != nil {
 		// Assume the first source from the source provider is the library entry point.
 		srcPath = library.sourceProvider.Srcs()[0]
+		deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...)
 	} else {
 		srcPath, _ = srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
 	}
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 0e79089..4fba34f 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -46,7 +46,7 @@
 var _ SourceProvider = (*protobufDecorator)(nil)
 
 type ProtobufProperties struct {
-	// List of realtive 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
 	Protos []string `android:"path,arch_variant"`
 
 	// List of additional flags to pass to aprotoc
@@ -80,6 +80,10 @@
 
 	protoFiles := android.PathsForModuleSrc(ctx, proto.Properties.Protos)
 
+	if len(protoFiles) == 0 {
+		ctx.PropertyErrorf("protos", "at least one protobuf must be defined.")
+	}
+
 	// Add exported dependency include paths
 	for _, include := range deps.depIncludePaths {
 		protoFlags.Flags = append(protoFlags.Flags, "-I"+include.String())
@@ -91,7 +95,7 @@
 	stemFile := android.PathForModuleOut(ctx, "mod_"+stem+".rs")
 
 	// stemFile must be first here as the first path in BaseSourceProvider.OutputFiles is the library entry-point.
-	outputs := android.WritablePaths{stemFile}
+	var outputs android.WritablePaths
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 	for _, protoFile := range protoFiles {
@@ -112,14 +116,12 @@
 		outputs = append(outputs, ruleOutputs...)
 	}
 
-	rule.Command().
-		Implicits(outputs.Paths()).
-		Text("printf '" + proto.genModFileContents(ctx, protoNames) + "' >").
-		Output(stemFile)
+	android.WriteFileRule(ctx, stemFile, proto.genModFileContents(ctx, protoNames))
 
 	rule.Build("protoc_"+ctx.ModuleName(), "protoc "+ctx.ModuleName())
 
-	proto.BaseSourceProvider.OutputFiles = outputs.Paths()
+	// stemFile must be first here as the first path in BaseSourceProvider.OutputFiles is the library entry-point.
+	proto.BaseSourceProvider.OutputFiles = append(android.Paths{stemFile}, outputs.Paths()...)
 
 	// mod_stem.rs is the entry-point for our library modules, so this is what we return.
 	return stemFile
@@ -145,7 +147,7 @@
 			"}")
 	}
 
-	return strings.Join(lines, "\\n")
+	return strings.Join(lines, "\n")
 }
 
 func (proto *protobufDecorator) setupPlugin(ctx ModuleContext, protoFlags android.ProtoFlags, outDir android.ModuleOutPath) (android.Paths, android.ProtoFlags) {
diff --git a/rust/rust.go b/rust/rust.go
index 38caad3..6cbcd7d 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -260,7 +260,8 @@
 	CrtEnd   android.OptionalPath
 
 	// Paths to generated source files
-	SrcDeps android.Paths
+	SrcDeps          android.Paths
+	srcProviderFiles android.Paths
 }
 
 type RustLibraries []RustLibrary