Add java_genrules to use jars as inputs and outputs
Add a java_genrule that has the right multilib flags to be a dependency of a java rule. Make java libraries implement SourceFileProducer so that their classes jar can be used as an input to a java_genrule. Allow libs and static_libs dependencies to be a java_genrule. Test: TestJarGenrules Change-Id: Ib1b31ef9c0b7e72eeed2c9ecc4ce8a1088e0b1c9
This commit is contained in:
@@ -218,6 +218,7 @@ bootstrap_go_package {
|
|||||||
"java/app.go",
|
"java/app.go",
|
||||||
"java/builder.go",
|
"java/builder.go",
|
||||||
"java/gen.go",
|
"java/gen.go",
|
||||||
|
"java/genrule.go",
|
||||||
"java/jacoco.go",
|
"java/jacoco.go",
|
||||||
"java/java.go",
|
"java/java.go",
|
||||||
"java/proto.go",
|
"java/proto.go",
|
||||||
|
35
java/genrule.go
Normal file
35
java/genrule.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// 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 (
|
||||||
|
"android/soong/android"
|
||||||
|
"android/soong/genrule"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
android.RegisterModuleType("java_genrule", genRuleFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
// java_genrule is a genrule that can depend on other java_* objects.
|
||||||
|
// The cmd may be run multiple times, once for each of the different host/device
|
||||||
|
// variations.
|
||||||
|
func genRuleFactory() android.Module {
|
||||||
|
module := genrule.NewGenRule()
|
||||||
|
|
||||||
|
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
|
||||||
|
|
||||||
|
return module
|
||||||
|
}
|
81
java/java.go
81
java/java.go
@@ -211,6 +211,12 @@ type Module struct {
|
|||||||
compiledSrcJars android.Paths
|
compiledSrcJars android.Paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *Module) Srcs() android.Paths {
|
||||||
|
return android.Paths{j.implementationJarFile}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ android.SourceFileProducer = (*Module)(nil)
|
||||||
|
|
||||||
type Dependency interface {
|
type Dependency interface {
|
||||||
HeaderJars() android.Paths
|
HeaderJars() android.Paths
|
||||||
ImplementationJars() android.Paths
|
ImplementationJars() android.Paths
|
||||||
@@ -446,6 +452,15 @@ type deps struct {
|
|||||||
kotlinStdlib android.Paths
|
kotlinStdlib android.Paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
|
||||||
|
for _, f := range dep.Srcs() {
|
||||||
|
if f.Ext() != ".jar" {
|
||||||
|
ctx.ModuleErrorf("genrule %q must generate files ending with .jar to be used as a libs or static_libs dependency",
|
||||||
|
ctx.OtherModuleName(dep.(blueprint.Module)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
||||||
var deps deps
|
var deps deps
|
||||||
|
|
||||||
@@ -462,8 +477,46 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
|||||||
otherName := ctx.OtherModuleName(module)
|
otherName := ctx.OtherModuleName(module)
|
||||||
tag := ctx.OtherModuleDependencyTag(module)
|
tag := ctx.OtherModuleDependencyTag(module)
|
||||||
|
|
||||||
dep, _ := module.(Dependency)
|
switch dep := module.(type) {
|
||||||
if dep == nil {
|
case Dependency:
|
||||||
|
switch tag {
|
||||||
|
case bootClasspathTag:
|
||||||
|
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
|
||||||
|
case libTag:
|
||||||
|
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
|
||||||
|
case staticLibTag:
|
||||||
|
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
|
||||||
|
deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
|
||||||
|
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
|
||||||
|
case frameworkResTag:
|
||||||
|
if ctx.ModuleName() == "framework" {
|
||||||
|
// framework.jar has a one-off dependency on the R.java and Manifest.java files
|
||||||
|
// generated by framework-res.apk
|
||||||
|
deps.srcJars = append(deps.srcJars, dep.(*AndroidApp).aaptSrcJar)
|
||||||
|
}
|
||||||
|
case kotlinStdlibTag:
|
||||||
|
deps.kotlinStdlib = dep.HeaderJars()
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
|
||||||
|
}
|
||||||
|
|
||||||
|
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
|
||||||
|
case android.SourceFileProducer:
|
||||||
|
switch tag {
|
||||||
|
case libTag:
|
||||||
|
checkProducesJars(ctx, dep)
|
||||||
|
deps.classpath = append(deps.classpath, dep.Srcs()...)
|
||||||
|
case staticLibTag:
|
||||||
|
checkProducesJars(ctx, dep)
|
||||||
|
deps.classpath = append(deps.classpath, dep.Srcs()...)
|
||||||
|
deps.staticJars = append(deps.staticJars, dep.Srcs()...)
|
||||||
|
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
|
||||||
|
case android.DefaultsDepTag, android.SourceDepTag:
|
||||||
|
// Nothing to do
|
||||||
|
default:
|
||||||
|
ctx.ModuleErrorf("dependency on genrule %q may only be in srcs, libs, or static_libs", otherName)
|
||||||
|
}
|
||||||
|
default:
|
||||||
switch tag {
|
switch tag {
|
||||||
case android.DefaultsDepTag, android.SourceDepTag:
|
case android.DefaultsDepTag, android.SourceDepTag:
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
@@ -479,31 +532,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
|||||||
default:
|
default:
|
||||||
ctx.ModuleErrorf("depends on non-java module %q", otherName)
|
ctx.ModuleErrorf("depends on non-java module %q", otherName)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch tag {
|
|
||||||
case bootClasspathTag:
|
|
||||||
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
|
|
||||||
case libTag:
|
|
||||||
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
|
|
||||||
case staticLibTag:
|
|
||||||
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
|
|
||||||
deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
|
|
||||||
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
|
|
||||||
case frameworkResTag:
|
|
||||||
if ctx.ModuleName() == "framework" {
|
|
||||||
// framework.jar has a one-off dependency on the R.java and Manifest.java files
|
|
||||||
// generated by framework-res.apk
|
|
||||||
deps.srcJars = append(deps.srcJars, dep.(*AndroidApp).aaptSrcJar)
|
|
||||||
}
|
|
||||||
case kotlinStdlibTag:
|
|
||||||
deps.kotlinStdlib = dep.HeaderJars()
|
|
||||||
default:
|
|
||||||
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
|
|
||||||
}
|
|
||||||
|
|
||||||
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return deps
|
return deps
|
||||||
|
@@ -67,6 +67,7 @@ func testContext(config android.Config, bp string,
|
|||||||
ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory))
|
ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory))
|
||||||
ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
|
ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
|
||||||
ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory))
|
ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory))
|
||||||
|
ctx.RegisterModuleType("java_genrule", android.ModuleFactoryAdaptor(genRuleFactory))
|
||||||
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
|
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
|
||||||
ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory))
|
ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory))
|
||||||
ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
|
ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
|
||||||
@@ -775,6 +776,60 @@ func TestSharding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJarGenrules(t *testing.T) {
|
||||||
|
ctx := testJava(t, `
|
||||||
|
java_library {
|
||||||
|
name: "foo",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
}
|
||||||
|
|
||||||
|
java_genrule {
|
||||||
|
name: "jargen",
|
||||||
|
tool_files: ["b.java"],
|
||||||
|
cmd: "$(location b.java) $(in) $(out)",
|
||||||
|
out: ["jargen.jar"],
|
||||||
|
srcs: [":foo"],
|
||||||
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "bar",
|
||||||
|
static_libs: ["jargen"],
|
||||||
|
srcs: ["c.java"],
|
||||||
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "baz",
|
||||||
|
libs: ["jargen"],
|
||||||
|
srcs: ["c.java"],
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar")
|
||||||
|
jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar")
|
||||||
|
bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar")
|
||||||
|
baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar")
|
||||||
|
barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
|
||||||
|
|
||||||
|
if len(jargen.Inputs) != 1 || jargen.Inputs[0].String() != foo.Output.String() {
|
||||||
|
t.Errorf("expected jargen inputs [%q], got %q", foo.Output.String(), jargen.Inputs.Strings())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) {
|
||||||
|
t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) {
|
||||||
|
t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(barCombined.Inputs) != 2 ||
|
||||||
|
barCombined.Inputs[0].String() != bar.Output.String() ||
|
||||||
|
barCombined.Inputs[1].String() != jargen.Output.String() {
|
||||||
|
t.Errorf("bar combined jar inputs %v is not [%q, %q]",
|
||||||
|
barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func fail(t *testing.T, errs []error) {
|
func fail(t *testing.T, errs []error) {
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
|
Reference in New Issue
Block a user