Add support for .proto files in java modules
Test: m -j checkbuild
Change-Id: Ia03429948baebff85164a91a34507866c97a08ef
diff --git a/Android.bp b/Android.bp
index 0e57c12..ae31a60 100644
--- a/Android.bp
+++ b/Android.bp
@@ -209,6 +209,7 @@
"java/builder.go",
"java/gen.go",
"java/java.go",
+ "java/proto.go",
"java/resources.go",
],
testSrcs: [
diff --git a/android/proto.go b/android/proto.go
index 9bb9cfb..1c70656 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -14,22 +14,6 @@
package android
-import (
- "github.com/google/blueprint"
-)
-
-func init() {
- pctx.HostBinToolVariable("protocCmd", "aprotoc")
-}
-
-var (
- proto = pctx.AndroidStaticRule("protoc",
- blueprint.RuleParams{
- Command: "$protocCmd $protoOut=$protoOutFlags:$outDir $protoFlags $in",
- CommandDeps: []string{"$protocCmd"},
- }, "protoFlags", "protoOut", "protoOutFlags", "outDir")
-)
-
// TODO(ccross): protos are often used to communicate between multiple modules. If the only
// way to convert a proto to source is to reference it as a source file, and external modules cannot
// reference source files in other modules, then every module that owns a proto file will need to
@@ -38,30 +22,6 @@
// and then external modules could depend on the proto module but use their own settings to
// generate the source.
-func GenProto(ctx ModuleContext, protoFile Path,
- protoFlags string, protoOut, protoOutFlags string, extensions []string) WritablePaths {
-
- var outFiles WritablePaths
- for _, ext := range extensions {
- outFiles = append(outFiles, GenPathWithExt(ctx, "proto", protoFile, ext))
- }
-
- ctx.ModuleBuild(pctx, ModuleBuildParams{
- Rule: proto,
- Description: "protoc " + protoFile.Rel(),
- Outputs: outFiles,
- Input: protoFile,
- Args: map[string]string{
- "outDir": ProtoDir(ctx).String(),
- "protoOut": protoOut,
- "protoOutFlags": protoOutFlags,
- "protoFlags": protoFlags,
- },
- })
-
- return outFiles
-}
-
func ProtoFlags(ctx ModuleContext, p *ProtoProperties) []string {
var protoFlags []string
if len(p.Proto.Local_include_dirs) > 0 {
diff --git a/cc/gen.go b/cc/gen.go
index 9fc14c5..2280e0f 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -153,10 +153,9 @@
srcFiles[i] = cppFile
genLex(ctx, srcFile, cppFile)
case ".proto":
- protoFiles := android.GenProto(ctx, srcFile, buildFlags.protoFlags,
- "--cpp_out", "", []string{"pb.cc", "pb.h"})
- srcFiles[i] = protoFiles[0]
- deps = append(deps, protoFiles[1])
+ ccFile, headerFile := genProto(ctx, srcFile, buildFlags.protoFlags)
+ srcFiles[i] = ccFile
+ deps = append(deps, headerFile)
case ".aidl":
cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp")
srcFiles[i] = cppFile
diff --git a/cc/proto.go b/cc/proto.go
index 6049d44..a01951f 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -15,11 +15,46 @@
package cc
import (
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
)
+func init() {
+ pctx.HostBinToolVariable("protocCmd", "aprotoc")
+}
+
+var (
+ proto = pctx.AndroidStaticRule("protoc",
+ blueprint.RuleParams{
+ Command: "$protocCmd --cpp_out=$outDir $protoFlags $in",
+ CommandDeps: []string{"$protocCmd"},
+ }, "protoFlags", "outDir")
+)
+
+// genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns
+// the paths to the generated files.
+func genProto(ctx android.ModuleContext, protoFile android.Path,
+ protoFlags string) (ccFile, headerFile android.WritablePath) {
+
+ ccFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.cc")
+ headerFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.h")
+
+ ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+ Rule: proto,
+ Description: "protoc " + protoFile.Rel(),
+ Outputs: android.WritablePaths{ccFile, headerFile},
+ Input: protoFile,
+ Args: map[string]string{
+ "outDir": android.ProtoDir(ctx).String(),
+ "protoFlags": protoFlags,
+ },
+ })
+
+ return ccFile, headerFile
+}
+
func protoDeps(ctx BaseModuleContext, deps Deps, p *android.ProtoProperties, static bool) Deps {
var lib string
diff --git a/java/builder.go b/java/builder.go
index 95345d4..b924d65 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -127,6 +127,9 @@
desugarFlags string
aidlFlags string
javaVersion string
+
+ protoFlags string
+ protoOutFlag string
}
func TransformJavaToClasses(ctx android.ModuleContext, srcFiles, srcFileLists android.Paths,
@@ -136,7 +139,10 @@
annoDir := android.PathForModuleOut(ctx, "anno")
classJar := android.PathForModuleOut(ctx, "classes-compiled.jar")
- javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+ javacFlags := flags.javacFlags
+ if len(srcFileLists) > 0 {
+ javacFlags += " " + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+ }
deps = append(deps, srcFileLists...)
deps = append(deps, flags.bootClasspath...)
@@ -161,8 +167,8 @@
return classJar
}
-func RunErrorProne(ctx android.ModuleContext, srcFiles android.Paths, srcFileLists android.Paths,
- flags javaBuilderFlags, deps android.Paths) android.Path {
+func RunErrorProne(ctx android.ModuleContext, srcFiles, srcFileLists android.Paths,
+ flags javaBuilderFlags) android.Path {
if config.ErrorProneJar == "" {
ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
@@ -173,7 +179,12 @@
annoDir := android.PathForModuleOut(ctx, "anno-errorprone")
classFileList := android.PathForModuleOut(ctx, "classes-errorprone.list")
- javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+ javacFlags := flags.javacFlags
+ if len(srcFileLists) > 0 {
+ javacFlags += " " + android.JoinWithPrefix(srcFileLists.Strings(), "@")
+ }
+
+ var deps android.Paths
deps = append(deps, srcFileLists...)
deps = append(deps, flags.bootClasspath...)
diff --git a/java/gen.go b/java/gen.go
index e473859..e55be91 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -85,21 +85,37 @@
}
func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
- flags javaBuilderFlags) android.Paths {
+ flags javaBuilderFlags) (android.Paths, android.Paths) {
- for i, srcFile := range srcFiles {
+ var protoFiles android.Paths
+ outSrcFiles := make(android.Paths, 0, len(srcFiles))
+
+ for _, srcFile := range srcFiles {
switch srcFile.Ext() {
case ".aidl":
javaFile := genAidl(ctx, srcFile, flags.aidlFlags)
- srcFiles[i] = javaFile
+ outSrcFiles = append(outSrcFiles, javaFile)
case ".logtags":
j.logtagsSrcs = append(j.logtagsSrcs, srcFile)
javaFile := genLogtags(ctx, srcFile)
- srcFiles[i] = javaFile
+ outSrcFiles = append(outSrcFiles, javaFile)
+ case ".proto":
+ protoFiles = append(protoFiles, srcFile)
+ default:
+ outSrcFiles = append(outSrcFiles, srcFile)
}
}
- return srcFiles
+ var outSrcFileLists android.Paths
+
+ if len(protoFiles) > 0 {
+ protoFileList := genProto(ctx, protoFiles,
+ flags.protoFlags, flags.protoOutFlag, "")
+
+ outSrcFileLists = append(outSrcFileLists, protoFileList)
+ }
+
+ return outSrcFiles, outSrcFileLists
}
func LogtagsSingleton() blueprint.Singleton {
diff --git a/java/java.go b/java/java.go
index d8bc0c2..eb94806 100644
--- a/java/java.go
+++ b/java/java.go
@@ -49,7 +49,6 @@
// TODO:
// Autogenerated files:
-// Proto
// Renderscript
// Post-jar passes:
// Proguard
@@ -145,6 +144,7 @@
android.DefaultableModuleBase
properties CompilerProperties
+ protoProperties android.ProtoProperties
deviceProperties CompilerDeviceProperties
// output file suitable for inserting into the classpath of another compile
@@ -296,6 +296,24 @@
android.ExtractSourcesDeps(ctx, j.properties.Srcs)
android.ExtractSourcesDeps(ctx, j.properties.Java_resources)
+
+ if j.hasSrcExt(".proto") {
+ protoDeps(ctx, &j.protoProperties)
+ }
+}
+
+func hasSrcExt(srcs []string, ext string) bool {
+ for _, src := range srcs {
+ if filepath.Ext(src) == ext {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (j *Module) hasSrcExt(ext string) bool {
+ return hasSrcExt(j.properties.Srcs, ext)
}
func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
@@ -416,7 +434,15 @@
srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
- srcFiles = j.genSources(ctx, srcFiles, flags)
+ if hasSrcExt(srcFiles.Strings(), ".proto") {
+ flags = protoFlags(ctx, &j.protoProperties, flags)
+ }
+
+ var srcFileLists android.Paths
+
+ srcFiles, srcFileLists = j.genSources(ctx, srcFiles, flags)
+
+ srcFileLists = append(srcFileLists, deps.srcFileLists...)
ctx.VisitDirectDeps(func(module blueprint.Module) {
if gen, ok := module.(genrule.SourceFileGenerator); ok {
@@ -424,7 +450,7 @@
}
})
- deps.srcFileLists = append(deps.srcFileLists, j.ExtraSrcLists...)
+ srcFileLists = append(srcFileLists, j.ExtraSrcLists...)
var jars android.Paths
@@ -436,12 +462,12 @@
// a rebuild when error-prone is turned off).
// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
// enable error-prone without affecting the output class files.
- errorprone := RunErrorProne(ctx, srcFiles, deps.srcFileLists, flags, nil)
+ errorprone := RunErrorProne(ctx, srcFiles, srcFileLists, flags)
extraJarDeps = append(extraJarDeps, errorprone)
}
// Compile java sources into .class files
- classes := TransformJavaToClasses(ctx, srcFiles, deps.srcFileLists, flags, extraJarDeps)
+ classes := TransformJavaToClasses(ctx, srcFiles, srcFileLists, flags, extraJarDeps)
if ctx.Failed() {
return
}
@@ -629,7 +655,8 @@
module.AddProperties(
&module.Module.properties,
- &module.Module.deviceProperties)
+ &module.Module.deviceProperties,
+ &module.Module.protoProperties)
InitJavaModule(module, android.HostAndDeviceSupported)
return module
@@ -639,7 +666,9 @@
func LibraryHostFactory() android.Module {
module := &Library{}
- module.AddProperties(&module.Module.properties)
+ module.AddProperties(
+ &module.Module.properties,
+ &module.Module.protoProperties)
InitJavaModule(module, android.HostSupported)
return module
@@ -685,6 +714,7 @@
module.AddProperties(
&module.Module.properties,
&module.Module.deviceProperties,
+ &module.Module.protoProperties,
&module.binaryProperties)
InitJavaModule(module, android.HostAndDeviceSupported)
@@ -697,6 +727,7 @@
module.AddProperties(
&module.Module.properties,
&module.Module.deviceProperties,
+ &module.Module.protoProperties,
&module.binaryProperties)
InitJavaModule(module, android.HostSupported)
diff --git a/java/proto.go b/java/proto.go
new file mode 100644
index 0000000..324868a
--- /dev/null
+++ b/java/proto.go
@@ -0,0 +1,98 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// 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
+//
+// http://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.
+
+package java
+
+import (
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+func init() {
+ pctx.HostBinToolVariable("protocCmd", "aprotoc")
+}
+
+var (
+ proto = pctx.AndroidStaticRule("protoc",
+ blueprint.RuleParams{
+ Command: `rm -rf $outDir && mkdir -p $outDir && ` +
+ `$protocCmd $protoOut=$protoOutFlags:$outDir $protoFlags $in && ` +
+ `find $outDir -name "*.java" > $out`,
+ CommandDeps: []string{"$protocCmd"},
+ }, "protoFlags", "protoOut", "protoOutFlags", "outDir")
+)
+
+func genProto(ctx android.ModuleContext, protoFiles android.Paths,
+ protoFlags string, protoOut, protoOutFlags string) android.WritablePath {
+
+ protoFileList := android.PathForModuleGen(ctx, "proto.filelist")
+
+ ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+ Rule: proto,
+ Description: "protoc " + protoFiles[0].Rel(),
+ Output: protoFileList,
+ Inputs: protoFiles,
+ Args: map[string]string{
+ "outDir": android.ProtoDir(ctx).String(),
+ "protoOut": protoOut,
+ "protoOutFlags": protoOutFlags,
+ "protoFlags": protoFlags,
+ },
+ })
+
+ return protoFileList
+}
+
+func protoDeps(ctx android.BottomUpMutatorContext, p *android.ProtoProperties) {
+ switch proptools.String(p.Proto.Type) {
+ case "micro":
+ ctx.AddDependency(ctx.Module(), staticLibTag, "libprotobuf-java-micro")
+ case "nano":
+ ctx.AddDependency(ctx.Module(), staticLibTag, "libprotobuf-java-nano")
+ case "stream":
+ // TODO(ccross): add dependency on protoc-gen-java-stream binary
+ ctx.PropertyErrorf("proto.type", `"stream" not supported yet`)
+ // No library for stream protobufs
+ case "lite", "":
+ ctx.AddDependency(ctx.Module(), staticLibTag, "libprotobuf-java-lite")
+ case "full":
+ if ctx.Host() {
+ ctx.AddDependency(ctx.Module(), staticLibTag, "libprotobuf-java-full")
+ } else {
+ ctx.PropertyErrorf("proto.type", "full java protos only supported on the host")
+ }
+ default:
+ ctx.PropertyErrorf("proto.type", "unknown proto type %q",
+ proptools.String(p.Proto.Type))
+ }
+}
+
+func protoFlags(ctx android.ModuleContext, p *android.ProtoProperties, flags javaBuilderFlags) javaBuilderFlags {
+ switch proptools.String(p.Proto.Type) {
+ case "micro":
+ flags.protoOutFlag = "--javamicro_out"
+ case "nano":
+ flags.protoOutFlag = "--javanano_out"
+ case "stream":
+ flags.protoOutFlag = "--javastream_out"
+ case "lite", "":
+ flags.protoOutFlag = "--java_out"
+ default:
+ ctx.PropertyErrorf("proto.type", "unknown proto type %q",
+ proptools.String(p.Proto.Type))
+ }
+ return flags
+}