diff --git a/android/paths.go b/android/paths.go index 4a49d556a..69a7b0d7c 100644 --- a/android/paths.go +++ b/android/paths.go @@ -247,6 +247,9 @@ func PathsForModuleSrc(ctx ModuleContext, paths []string) Paths { // each string. func pathsForModuleSrcFromFullPath(ctx ModuleContext, paths []string) Paths { prefix := filepath.Join(ctx.AConfig().srcDir, ctx.ModuleDir()) + "/" + if prefix == "./" { + prefix = "" + } ret := make(Paths, 0, len(paths)) for _, p := range paths { path := filepath.Clean(p) diff --git a/java/java.go b/java/java.go index 06ba44db8..dbb755b9f 100644 --- a/java/java.go +++ b/java/java.go @@ -75,6 +75,12 @@ type CompilerProperties struct { // list of directories that should be excluded from java_resource_dirs Exclude_java_resource_dirs []string `android:"arch_variant"` + // list of files to use as Java resources + Java_resources []string `android:"arch_variant"` + + // list of files that should be excluded from java_resources + Exclude_java_resources []string `android:"arch_variant"` + // don't build against the default libraries (legacy-test, core-junit, // ext, and framework for device targets) No_standard_libs *bool @@ -100,6 +106,9 @@ type CompilerProperties struct { // If set to false, don't allow this module to be installed. Defaults to true. Installable *bool + // If set to true, include sources used to compile the module in to the final jar + Include_srcs *bool + // List of modules to use as annotation processors Annotation_processors []string @@ -275,6 +284,7 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { ctx.AddDependency(ctx.Module(), libTag, j.properties.Annotation_processors...) android.ExtractSourcesDeps(ctx, j.properties.Srcs) + android.ExtractSourcesDeps(ctx, j.properties.Java_resources) } func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath, @@ -426,7 +436,23 @@ func (j *Module) compile(ctx android.ModuleContext) { jars = append(jars, classes) } - resArgs, resDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs) + dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs) + fileArgs, fileDeps := ResourceFilesToJarArgs(ctx, j.properties.Java_resources, j.properties.Exclude_java_resources) + + var resArgs []string + var resDeps android.Paths + + resArgs = append(resArgs, dirArgs...) + resDeps = append(resDeps, dirDeps...) + + resArgs = append(resArgs, fileArgs...) + resDeps = append(resDeps, fileDeps...) + + if proptools.Bool(j.properties.Include_srcs) { + srcArgs, srcDeps := ResourceFilesToJarArgs(ctx, j.properties.Srcs, j.properties.Exclude_srcs) + resArgs = append(resArgs, srcArgs...) + resDeps = append(resDeps, srcDeps...) + } if len(resArgs) > 0 { // Combine classes + resources into classes-full-debug.jar diff --git a/java/java_test.go b/java/java_test.go index a757a9f02..7154f5e37 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -16,6 +16,7 @@ package java import ( "android/soong/android" + "android/soong/genrule" "fmt" "io/ioutil" "os" @@ -59,6 +60,7 @@ func testJava(t *testing.T, bp string) *android.TestContext { ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory)) ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory)) ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory)) + ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory)) ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators) ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) @@ -92,6 +94,8 @@ func testJava(t *testing.T, bp string) *android.TestContext { "c.java": nil, "a.jar": nil, "b.jar": nil, + "res/a": nil, + "res/b": nil, "prebuilts/sdk/14/android.jar": nil, "prebuilts/sdk/14/framework.aidl": nil, }) @@ -360,6 +364,76 @@ func TestDefaults(t *testing.T) { } } +func TestResources(t *testing.T) { + var table = []struct { + name string + prop string + extra string + args string + }{ + { + // Test that a module with java_resource_dirs includes a file list file + name: "resource dirs", + prop: `java_resource_dirs: ["res"]`, + args: "-C res -l ", + }, + { + // Test that a module with java_resources includes the files + name: "resource files", + prop: `java_resources: ["res/a", "res/b"]`, + args: "-C . -f res/a -C . -f res/b", + }, + { + // Test that a module with a filegroup in java_resources includes the files with the + // path prefix + name: "resource filegroup", + prop: `java_resources: [":foo-res"]`, + extra: ` + filegroup { + name: "foo-res", + path: "res", + srcs: ["res/a", "res/b"], + }`, + args: "-C res -f res/a -C res -f res/b", + }, + { + // Test that a module with "include_srcs: true" includes its source files in the resources jar + name: "include sources", + prop: `include_srcs: true`, + args: "-C . -f a.java -C . -f b.java -C . -f c.java", + }, + } + + for _, test := range table { + t.Run(test.name, func(t *testing.T) { + ctx := testJava(t, ` + java_library { + name: "foo", + srcs: [ + "a.java", + "b.java", + "c.java", + ], + `+test.prop+`, + } + `+test.extra) + + foo := ctx.ModuleForTests("foo", "android_common").Output("classes.jar") + fooRes := ctx.ModuleForTests("foo", "android_common").Output("res.jar") + + if !inList(fooRes.Output.String(), foo.Inputs.Strings()) { + t.Errorf("foo combined jars %v does not contain %q", + foo.Inputs.Strings(), fooRes.Output.String()) + } + + if !strings.Contains(fooRes.Args["jarArgs"], test.args) { + t.Errorf("foo resource jar args %q does not contain %q", + fooRes.Args["jarArgs"], test.args) + } + }) + } +} + func fail(t *testing.T, errs []error) { if len(errs) > 0 { for _, err := range errs { diff --git a/java/resources.go b/java/resources.go index 4969d4894..9f5e5e0ce 100644 --- a/java/resources.go +++ b/java/resources.go @@ -15,7 +15,9 @@ package java import ( + "fmt" "path/filepath" + "strings" "github.com/google/blueprint/bootstrap" @@ -71,3 +73,20 @@ func ResourceDirsToJarArgs(ctx android.ModuleContext, return args, deps } + +func ResourceFilesToJarArgs(ctx android.ModuleContext, + res, exclude []string) (args []string, deps android.Paths) { + files := ctx.ExpandSources(res, exclude) + + for _, f := range files { + rel := f.Rel() + path := f.String() + if !strings.HasSuffix(path, rel) { + panic(fmt.Errorf("path %q does not end with %q", path, rel)) + } + path = filepath.Clean(strings.TrimSuffix(path, rel)) + args = append(args, "-C", filepath.Clean(path), "-f", f.String()) + } + + return args, files +}