Merge changes from topics "soong_java_aidl", "soong_java_proto"

* changes:
  Shard aidl compiles into srcjars
  Shard java proto files into groups of 100
  Support deps files with no output
This commit is contained in:
Colin Cross 2019-10-07 17:33:00 +00:00 committed by Gerrit Code Review
commit 63c7727dec
7 changed files with 166 additions and 65 deletions

View File

@ -461,14 +461,14 @@ func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
flags droiddocBuilderFlags) android.Paths {
outSrcFiles := make(android.Paths, 0, len(srcFiles))
var aidlSrcs android.Paths
aidlIncludeFlags := genAidlIncludeFlags(srcFiles)
for _, srcFile := range srcFiles {
switch srcFile.Ext() {
case ".aidl":
javaFile := genAidl(ctx, srcFile, flags.aidlFlags+aidlIncludeFlags, flags.aidlDeps)
outSrcFiles = append(outSrcFiles, javaFile)
aidlSrcs = append(aidlSrcs, srcFile)
case ".logtags":
javaFile := genLogtags(ctx, srcFile)
outSrcFiles = append(outSrcFiles, javaFile)
@ -477,6 +477,12 @@ func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
}
}
// Process all aidl files together to support sharding them into one or more rules that produce srcjars.
if len(aidlSrcs) > 0 {
srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags+aidlIncludeFlags, flags.aidlDeps)
outSrcFiles = append(outSrcFiles, srcJarFiles...)
}
return outSrcFiles
}

View File

@ -15,9 +15,11 @@
package java
import (
"strconv"
"strings"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"android/soong/android"
)
@ -29,13 +31,6 @@ func init() {
}
var (
aidl = pctx.AndroidStaticRule("aidl",
blueprint.RuleParams{
Command: "${config.AidlCmd} -d$depFile $aidlFlags $in $out",
CommandDeps: []string{"${config.AidlCmd}"},
},
"depFile", "aidlFlags")
logtags = pctx.AndroidStaticRule("logtags",
blueprint.RuleParams{
Command: "$logtagsCmd -o $out $in",
@ -49,23 +44,64 @@ var (
})
)
func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string, deps android.Paths) android.Path {
javaFile := android.GenPathWithExt(ctx, "aidl", aidlFile, "java")
depFile := javaFile.String() + ".d"
func genAidl(ctx android.ModuleContext, aidlFiles android.Paths, aidlFlags string, deps android.Paths) android.Paths {
// Shard aidl files into groups of 50 to avoid having to recompile all of them if one changes and to avoid
// hitting command line length limits.
shards := android.ShardPaths(aidlFiles, 50)
ctx.Build(pctx, android.BuildParams{
Rule: aidl,
Description: "aidl " + aidlFile.Rel(),
Output: javaFile,
Input: aidlFile,
Implicits: deps,
Args: map[string]string{
"depFile": depFile,
"aidlFlags": aidlFlags,
},
})
srcJarFiles := make(android.Paths, 0, len(shards))
return javaFile
for i, shard := range shards {
srcJarFile := android.PathForModuleGen(ctx, "aidl", "aidl"+strconv.Itoa(i)+".srcjar")
srcJarFiles = append(srcJarFiles, srcJarFile)
outDir := srcJarFile.ReplaceExtension(ctx, "tmp")
rule := android.NewRuleBuilder()
rule.Command().Text("rm -rf").Flag(outDir.String())
rule.Command().Text("mkdir -p").Flag(outDir.String())
rule.Command().Text("FLAGS=' " + aidlFlags + "'")
for _, aidlFile := range shard {
depFile := srcJarFile.InSameDir(ctx, aidlFile.String()+".d")
javaFile := outDir.Join(ctx, pathtools.ReplaceExtension(aidlFile.String(), "java"))
rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "aidl")).
FlagWithDepFile("-d", depFile).
Flag("$FLAGS").
Input(aidlFile).
Output(javaFile).
Implicits(deps)
rule.Temporary(javaFile)
}
rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
// TODO(b/124333557): this can't use -srcjar for now, aidl on parcelables generates java files
// without a package statement, which causes -srcjar to put them in the top level of the zip file.
// Once aidl skips parcelables we can use -srcjar.
//Flag("-srcjar").
Flag("-write_if_changed").
FlagWithOutput("-o ", srcJarFile).
FlagWithArg("-C ", outDir.String()).
FlagWithArg("-D ", outDir.String())
rule.Command().Text("rm -rf").Flag(outDir.String())
rule.Restat()
ruleName := "aidl"
ruleDesc := "aidl"
if len(shards) > 1 {
ruleName += "_" + strconv.Itoa(i)
ruleDesc += " " + strconv.Itoa(i)
}
rule.Build(pctx, ctx, ruleName, ruleDesc)
}
return srcJarFiles
}
func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Path {
@ -98,26 +134,38 @@ func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
flags javaBuilderFlags) android.Paths {
outSrcFiles := make(android.Paths, 0, len(srcFiles))
var protoSrcs android.Paths
var aidlSrcs android.Paths
aidlIncludeFlags := genAidlIncludeFlags(srcFiles)
for _, srcFile := range srcFiles {
switch srcFile.Ext() {
case ".aidl":
javaFile := genAidl(ctx, srcFile, flags.aidlFlags+aidlIncludeFlags, flags.aidlDeps)
outSrcFiles = append(outSrcFiles, javaFile)
aidlSrcs = append(aidlSrcs, srcFile)
case ".logtags":
j.logtagsSrcs = append(j.logtagsSrcs, srcFile)
javaFile := genLogtags(ctx, srcFile)
outSrcFiles = append(outSrcFiles, javaFile)
case ".proto":
srcJarFile := genProto(ctx, srcFile, flags.proto)
outSrcFiles = append(outSrcFiles, srcJarFile)
protoSrcs = append(protoSrcs, srcFile)
default:
outSrcFiles = append(outSrcFiles, srcFile)
}
}
// Process all proto files together to support sharding them into one or more rules that produce srcjars.
if len(protoSrcs) > 0 {
srcJarFiles := genProto(ctx, protoSrcs, flags.proto)
outSrcFiles = append(outSrcFiles, srcJarFiles...)
}
// Process all aidl files together to support sharding them into one or more rules that produce srcjars.
if len(aidlSrcs) > 0 {
srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags+aidlIncludeFlags, flags.aidlDeps)
outSrcFiles = append(outSrcFiles, srcJarFiles...)
}
return outSrcFiles
}

View File

@ -18,6 +18,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"testing"
@ -811,19 +812,22 @@ func TestDroiddoc(t *testing.T) {
}
`)
inputs := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc").Inputs
barDoc := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc")
var javaSrcs []string
for _, i := range inputs {
for _, i := range barDoc.Inputs {
javaSrcs = append(javaSrcs, i.Base())
}
if len(javaSrcs) != 3 || javaSrcs[0] != "a.java" || javaSrcs[1] != "IFoo.java" || javaSrcs[2] != "IBar.java" {
t.Errorf("inputs of bar-doc must be []string{\"a.java\", \"IFoo.java\", \"IBar.java\", but was %#v.", javaSrcs)
if len(javaSrcs) != 1 || javaSrcs[0] != "a.java" {
t.Errorf("inputs of bar-doc must be []string{\"a.java\"}, but was %#v.", javaSrcs)
}
aidlRule := ctx.ModuleForTests("bar-doc", "android_common").Output(inputs[2].String())
aidlFlags := aidlRule.Args["aidlFlags"]
if !strings.Contains(aidlFlags, "-Ibar-doc") {
t.Errorf("aidl flags for IBar.aidl should contain \"-Ibar-doc\", but was %q", aidlFlags)
aidl := ctx.ModuleForTests("bar-doc", "android_common").Rule("aidl")
if g, w := barDoc.Implicits.Strings(), aidl.Output.String(); !inList(w, g) {
t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g)
}
if g, w := aidl.Implicits.Strings(), []string{"bar-doc/IBar.aidl", "bar-doc/IFoo.aidl"}; !reflect.DeepEqual(w, g) {
t.Errorf("aidl inputs must be %q, but was %q", w, g)
}
}

View File

@ -15,36 +15,61 @@
package java
import (
"path/filepath"
"strconv"
"android/soong/android"
)
func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags) android.Path {
srcJarFile := android.GenPathWithExt(ctx, "proto", protoFile, "srcjar")
func genProto(ctx android.ModuleContext, protoFiles android.Paths, flags android.ProtoFlags) android.Paths {
// Shard proto files into groups of 100 to avoid having to recompile all of them if one changes and to avoid
// hitting command line length limits.
shards := android.ShardPaths(protoFiles, 100)
outDir := srcJarFile.ReplaceExtension(ctx, "tmp")
depFile := srcJarFile.ReplaceExtension(ctx, "srcjar.d")
srcJarFiles := make(android.Paths, 0, len(shards))
rule := android.NewRuleBuilder()
for i, shard := range shards {
srcJarFile := android.PathForModuleGen(ctx, "proto", "proto"+strconv.Itoa(i)+".srcjar")
srcJarFiles = append(srcJarFiles, srcJarFile)
rule.Command().Text("rm -rf").Flag(outDir.String())
rule.Command().Text("mkdir -p").Flag(outDir.String())
outDir := srcJarFile.ReplaceExtension(ctx, "tmp")
android.ProtoRule(ctx, rule, protoFile, flags, flags.Deps, outDir, depFile, nil)
rule := android.NewRuleBuilder()
// Proto generated java files have an unknown package name in the path, so package the entire output directory
// into a srcjar.
rule.Command().
BuiltTool(ctx, "soong_zip").
Flag("-jar").
FlagWithOutput("-o ", srcJarFile).
FlagWithArg("-C ", outDir.String()).
FlagWithArg("-D ", outDir.String())
rule.Command().Text("rm -rf").Flag(outDir.String())
rule.Command().Text("mkdir -p").Flag(outDir.String())
rule.Command().Text("rm -rf").Flag(outDir.String())
for _, protoFile := range shard {
depFile := srcJarFile.InSameDir(ctx, protoFile.String()+".d")
rule.Command().Text("mkdir -p").Flag(filepath.Dir(depFile.String()))
android.ProtoRule(ctx, rule, protoFile, flags, flags.Deps, outDir, depFile, nil)
}
rule.Build(pctx, ctx, "protoc_"+protoFile.Rel(), "protoc "+protoFile.Rel())
// Proto generated java files have an unknown package name in the path, so package the entire output directory
// into a srcjar.
rule.Command().
BuiltTool(ctx, "soong_zip").
Flag("-jar").
Flag("-write_if_changed").
FlagWithOutput("-o ", srcJarFile).
FlagWithArg("-C ", outDir.String()).
FlagWithArg("-D ", outDir.String())
return srcJarFile
rule.Command().Text("rm -rf").Flag(outDir.String())
rule.Restat()
ruleName := "protoc"
ruleDesc := "protoc"
if len(shards) > 1 {
ruleName += "_" + strconv.Itoa(i)
ruleDesc += " " + strconv.Itoa(i)
}
rule.Build(pctx, ctx, ruleName, ruleDesc)
}
return srcJarFiles
}
func protoDeps(ctx android.BottomUpMutatorContext, p *android.ProtoProperties) {

View File

@ -250,7 +250,10 @@ func TestClasspath(t *testing.T) {
}
checkClasspath := func(t *testing.T, ctx *android.TestContext) {
javac := ctx.ModuleForTests("foo", variant).Rule("javac")
foo := ctx.ModuleForTests("foo", variant)
javac := foo.Rule("javac")
aidl := foo.MaybeRule("aidl")
got := javac.Args["bootClasspath"]
if got != bc {
@ -263,6 +266,9 @@ func TestClasspath(t *testing.T) {
}
var deps []string
if aidl.Rule != nil {
deps = append(deps, aidl.Output.String())
}
if len(bootclasspath) > 0 && bootclasspath[0] != `""` {
deps = append(deps, bootclasspath...)
}
@ -290,12 +296,8 @@ func TestClasspath(t *testing.T) {
if testcase.host != android.Host {
aidl := ctx.ModuleForTests("foo", variant).Rule("aidl")
aidlFlags := aidl.Args["aidlFlags"]
// Trim trailing "-I." to avoid having to specify it in every test
aidlFlags = strings.TrimSpace(strings.TrimSuffix(aidlFlags, "-I."))
if g, w := aidlFlags, testcase.aidl; g != w {
t.Errorf("want aidl flags %q, got %q", w, g)
if g, w := aidl.RuleParams.Command, testcase.aidl+" -I."; !strings.Contains(g, w) {
t.Errorf("want aidl command to contain %q, got %q", w, g)
}
}
})

View File

@ -57,10 +57,12 @@ func Parse(filename string, r io.Reader) (*Deps, error) {
return nil, fmt.Errorf("%sunsupported variable expansion: %v", pos(node), x.Target.Dump())
}
outputs := x.Target.Words()
if len(outputs) == 0 {
return nil, fmt.Errorf("%smissing output: %v", pos(node), x)
if len(outputs) > 0 {
ret.Output = outputs[0].Value(nil)
} else {
// TODO(b/141372861): put this back
//return nil, fmt.Errorf("%smissing output: %v", pos(node), x)
}
ret.Output = outputs[0].Value(nil)
if !x.Prerequisites.Const() {
return nil, fmt.Errorf("%sunsupported variable expansion: %v", pos(node), x.Prerequisites.Dump())

View File

@ -147,6 +147,20 @@ b: e`,
},
},
},
{
// TODO(b/141372861): remove this
// AIDL produces a dep file with no output file for a parcelable (b/
name: "AIDL parcelable",
input: ` : \
frameworks/base/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl
`,
output: Deps{
Output: "",
Inputs: []string{
"frameworks/base/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl",
},
},
},
}
for _, tc := range testCases {