Merge "Skip MIPS headers when generating NDK prebuilts"
diff --git a/Android.bp b/Android.bp
index e89f908..d32c957 100644
--- a/Android.bp
+++ b/Android.bp
@@ -213,6 +213,7 @@
"java/app.go",
"java/builder.go",
"java/gen.go",
+ "java/jacoco.go",
"java/java.go",
"java/proto.go",
"java/resources.go",
diff --git a/android/variable.go b/android/variable.go
index 4272817..13b5abf 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -189,6 +189,7 @@
Override_rs_driver *string `json:",omitempty"`
DeviceKernelHeaders []string `json:",omitempty"`
+ DistDir *string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/cc/builder.go b/cc/builder.go
index a81dc89..b5f4c5c 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -196,11 +196,19 @@
_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
- // Abidiff check turned on in advice-only mode. Builds will not fail on abi incompatibilties / extensions.
- sAbiDiff = pctx.AndroidStaticRule("sAbiDiff",
- blueprint.RuleParams{
- Command: "$sAbiDiffer $allowFlags -lib $libName -arch $arch -check-all-apis -o ${out} -new $in -old $referenceDump",
- CommandDeps: []string{"$sAbiDiffer"},
+ sAbiDiff = pctx.AndroidRuleFunc("sAbiDiff",
+ func(config android.Config) (blueprint.RuleParams, error) {
+
+ commandStr := "($sAbiDiffer $allowFlags -lib $libName -arch $arch -check-all-apis -o ${out} -new $in -old $referenceDump)"
+ distDir := config.ProductVariables.DistDir
+ if distDir != nil && *distDir != "" {
+ distAbiDiffDir := *distDir + "/abidiffs/"
+ commandStr += " || (mkdir -p " + distAbiDiffDir + " && cp ${out} " + distAbiDiffDir + " && exit 1)"
+ }
+ return blueprint.RuleParams{
+ Command: commandStr,
+ CommandDeps: []string{"$sAbiDiffer"},
+ }, nil
},
"allowFlags", "referenceDump", "libName", "arch")
diff --git a/cc/cc.go b/cc/cc.go
index 384b240..e18b2cc 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -326,9 +326,12 @@
flags Flags
// When calling a linker, if module A depends on module B, then A must precede B in its command
- // line invocation. staticDepsInLinkOrder stores the proper ordering of all of the transitive
+ // line invocation. depsInLinkOrder stores the proper ordering of all of the transitive
// deps of this module
- staticDepsInLinkOrder android.Paths
+ depsInLinkOrder android.Paths
+
+ // only non-nil when this is a shared library that reuses the objects of a static library
+ staticVariant *Module
}
func (c *Module) Init() android.Module {
@@ -537,7 +540,8 @@
// orderDeps reorders dependencies into a list such that if module A depends on B, then
// A will precede B in the resultant list.
// This is convenient for passing into a linker.
-func orderDeps(directDeps []android.Path, transitiveDeps map[android.Path][]android.Path) (orderedAllDeps []android.Path, orderedDeclaredDeps []android.Path) {
+// Note that directSharedDeps should be the analogous static library for each shared lib dep
+func orderDeps(directStaticDeps []android.Path, directSharedDeps []android.Path, allTransitiveDeps map[android.Path][]android.Path) (orderedAllDeps []android.Path, orderedDeclaredDeps []android.Path) {
// If A depends on B, then
// Every list containing A will also contain B later in the list
// So, after concatenating all lists, the final instance of B will have come from the same
@@ -545,38 +549,46 @@
// So, the final instance of B will be later in the concatenation than the final A
// So, keeping only the final instance of A and of B ensures that A is earlier in the output
// list than B
- for _, dep := range directDeps {
+ for _, dep := range directStaticDeps {
orderedAllDeps = append(orderedAllDeps, dep)
- orderedAllDeps = append(orderedAllDeps, transitiveDeps[dep]...)
+ orderedAllDeps = append(orderedAllDeps, allTransitiveDeps[dep]...)
+ }
+ for _, dep := range directSharedDeps {
+ orderedAllDeps = append(orderedAllDeps, dep)
+ orderedAllDeps = append(orderedAllDeps, allTransitiveDeps[dep]...)
}
orderedAllDeps = android.LastUniquePaths(orderedAllDeps)
- // We don't want to add any new dependencies into directDeps (to allow the caller to
+ // We don't want to add any new dependencies into directStaticDeps (to allow the caller to
// intentionally exclude or replace any unwanted transitive dependencies), so we limit the
- // resultant list to only what the caller has chosen to include in directDeps
- _, orderedDeclaredDeps = android.FilterPathList(orderedAllDeps, directDeps)
+ // resultant list to only what the caller has chosen to include in directStaticDeps
+ _, orderedDeclaredDeps = android.FilterPathList(orderedAllDeps, directStaticDeps)
return orderedAllDeps, orderedDeclaredDeps
}
-func orderStaticModuleDeps(module *Module, deps []*Module) (results []android.Path) {
- // make map of transitive dependencies
- transitiveStaticDepNames := make(map[android.Path][]android.Path, len(deps))
- for _, dep := range deps {
- transitiveStaticDepNames[dep.outputFile.Path()] = dep.staticDepsInLinkOrder
+func orderStaticModuleDeps(module *Module, staticDeps []*Module, sharedDeps []*Module) (results []android.Path) {
+ // convert Module to Path
+ allTransitiveDeps := make(map[android.Path][]android.Path, len(staticDeps))
+ staticDepFiles := []android.Path{}
+ for _, dep := range staticDeps {
+ allTransitiveDeps[dep.outputFile.Path()] = dep.depsInLinkOrder
+ staticDepFiles = append(staticDepFiles, dep.outputFile.Path())
}
- // get the output file for each declared dependency
- depFiles := []android.Path{}
- for _, dep := range deps {
- depFiles = append(depFiles, dep.outputFile.Path())
+ sharedDepFiles := []android.Path{}
+ for _, sharedDep := range sharedDeps {
+ staticAnalogue := sharedDep.staticVariant
+ if staticAnalogue != nil {
+ allTransitiveDeps[staticAnalogue.outputFile.Path()] = staticAnalogue.depsInLinkOrder
+ sharedDepFiles = append(sharedDepFiles, staticAnalogue.outputFile.Path())
+ }
}
// reorder the dependencies based on transitive dependencies
- module.staticDepsInLinkOrder, results = orderDeps(depFiles, transitiveStaticDepNames)
+ module.depsInLinkOrder, results = orderDeps(staticDepFiles, sharedDepFiles, allTransitiveDeps)
return results
-
}
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
@@ -1026,6 +1038,7 @@
var depPaths PathDeps
directStaticDeps := []*Module{}
+ directSharedDeps := []*Module{}
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
@@ -1092,6 +1105,7 @@
// re-exporting flags
if depTag == reuseObjTag {
if l, ok := ccDep.compiler.(libraryInterface); ok {
+ c.staticVariant = ccDep
objs, flags, deps := l.reuseObjs()
depPaths.Objs = depPaths.Objs.Append(objs)
depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, flags...)
@@ -1130,6 +1144,7 @@
ptr = &depPaths.SharedLibs
depPtr = &depPaths.SharedLibsDeps
depFile = ccDep.linker.(libraryInterface).toc()
+ directSharedDeps = append(directSharedDeps, ccDep)
case lateSharedDepTag, ndkLateStubDepTag:
ptr = &depPaths.LateSharedLibs
depPtr = &depPaths.LateSharedLibsDeps
@@ -1221,7 +1236,7 @@
})
// use the ordered dependencies as this module's dependencies
- depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps)...)
+ depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps, directSharedDeps)...)
// Dedup exported flags from dependencies
depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index bdc8c17..148b4dd 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -289,7 +289,11 @@
var staticLinkDepOrderTestCases = []struct {
// This is a string representation of a map[moduleName][]moduleDependency .
// It models the dependencies declared in an Android.bp file.
- in string
+ inStatic string
+
+ // This is a string representation of a map[moduleName][]moduleDependency .
+ // It models the dependencies declared in an Android.bp file.
+ inShared string
// allOrdered is a string representation of a map[moduleName][]moduleDependency .
// The keys of allOrdered specify which modules we would like to check.
@@ -305,82 +309,99 @@
}{
// Simple tests
{
- in: "",
+ inStatic: "",
outOrdered: "",
},
{
- in: "a:",
+ inStatic: "a:",
outOrdered: "a:",
},
{
- in: "a:b; b:",
+ inStatic: "a:b; b:",
outOrdered: "a:b; b:",
},
// Tests of reordering
{
// diamond example
- in: "a:d,b,c; b:d; c:d; d:",
+ inStatic: "a:d,b,c; b:d; c:d; d:",
outOrdered: "a:b,c,d; b:d; c:d; d:",
},
{
// somewhat real example
- in: "bsdiff_unittest:b,c,d,e,f,g,h,i; e:b",
+ inStatic: "bsdiff_unittest:b,c,d,e,f,g,h,i; e:b",
outOrdered: "bsdiff_unittest:c,d,e,b,f,g,h,i; e:b",
},
{
// multiple reorderings
- in: "a:b,c,d,e; d:b; e:c",
+ inStatic: "a:b,c,d,e; d:b; e:c",
outOrdered: "a:d,b,e,c; d:b; e:c",
},
{
// should reorder without adding new transitive dependencies
- in: "bin:lib2,lib1; lib1:lib2,liboptional",
+ inStatic: "bin:lib2,lib1; lib1:lib2,liboptional",
allOrdered: "bin:lib1,lib2,liboptional; lib1:lib2,liboptional",
outOrdered: "bin:lib1,lib2; lib1:lib2,liboptional",
},
{
// multiple levels of dependencies
- in: "a:b,c,d,e,f,g,h; f:b,c,d; b:c,d; c:d",
+ inStatic: "a:b,c,d,e,f,g,h; f:b,c,d; b:c,d; c:d",
allOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
outOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
},
+ // shared dependencies
+ {
+ // Note that this test doesn't recurse, to minimize the amount of logic it tests.
+ // So, we don't actually have to check that a shared dependency of c will change the order
+ // of a library that depends statically on b and on c. We only need to check that if c has
+ // a shared dependency on b, that that shows up in allOrdered.
+ inShared: "c:b",
+ allOrdered: "c:b",
+ outOrdered: "c:",
+ },
+ {
+ // This test doesn't actually include any shared dependencies but it's a reminder of what
+ // the second phase of the above test would look like
+ inStatic: "a:b,c; c:b",
+ allOrdered: "a:c,b; c:b",
+ outOrdered: "a:c,b; c:b",
+ },
// tiebreakers for when two modules specifying different orderings and there is no dependency
// to dictate an order
{
// if the tie is between two modules at the end of a's deps, then a's order wins
- in: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
+ inStatic: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
outOrdered: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
},
{
// if the tie is between two modules at the start of a's deps, then c's order is used
- in: "a1:d,e,b1,c1; b1:d,e; c1:e,d; a2:d,e,b2,c2; b2:d,e; c2:d,e",
+ inStatic: "a1:d,e,b1,c1; b1:d,e; c1:e,d; a2:d,e,b2,c2; b2:d,e; c2:d,e",
outOrdered: "a1:b1,c1,e,d; b1:d,e; c1:e,d; a2:b2,c2,d,e; b2:d,e; c2:d,e",
},
// Tests involving duplicate dependencies
{
// simple duplicate
- in: "a:b,c,c,b",
+ inStatic: "a:b,c,c,b",
outOrdered: "a:c,b",
},
{
// duplicates with reordering
- in: "a:b,c,d,c; c:b",
+ inStatic: "a:b,c,d,c; c:b",
outOrdered: "a:d,c,b",
},
// Tests to confirm the nonexistence of infinite loops.
// These cases should never happen, so as long as the test terminates and the
// result is deterministic then that should be fine.
{
- in: "a:a",
+ inStatic: "a:a",
outOrdered: "a:a",
},
{
- in: "a:b; b:c; c:a",
+ inStatic: "a:b; b:c; c:a",
allOrdered: "a:b,c; b:c,a; c:a,b",
outOrdered: "a:b; b:c; c:a",
},
{
- in: "a:b,c; b:c,a; c:a,b",
+ inStatic: "a:b,c; b:c,a; c:a,b",
allOrdered: "a:c,a,b; b:a,b,c; c:b,c,a",
outOrdered: "a:c,b; b:a,c; c:b,a",
},
@@ -427,43 +448,47 @@
return modulesInOrder, allDeps
}
-func TestStaticLinkDependencyOrdering(t *testing.T) {
+func TestLinkReordering(t *testing.T) {
for _, testCase := range staticLinkDepOrderTestCases {
errs := []string{}
// parse testcase
- _, givenTransitiveDeps := parseModuleDeps(testCase.in)
+ _, givenTransitiveDeps := parseModuleDeps(testCase.inStatic)
expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered)
if testCase.allOrdered == "" {
// allow the test case to skip specifying allOrdered
testCase.allOrdered = testCase.outOrdered
}
_, expectedAllDeps := parseModuleDeps(testCase.allOrdered)
+ _, givenAllSharedDeps := parseModuleDeps(testCase.inShared)
// For each module whose post-reordered dependencies were specified, validate that
// reordering the inputs produces the expected outputs.
for _, moduleName := range expectedModuleNames {
moduleDeps := givenTransitiveDeps[moduleName]
- orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenTransitiveDeps)
+ givenSharedDeps := givenAllSharedDeps[moduleName]
+ orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenSharedDeps, givenTransitiveDeps)
correctAllOrdered := expectedAllDeps[moduleName]
if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) {
errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+
- "\nInput: %q"+
+ "\nin static:%q"+
+ "\nin shared:%q"+
"\nmodule: %v"+
"\nexpected: %s"+
"\nactual: %s",
- testCase.in, moduleName, correctAllOrdered, orderedAllDeps))
+ testCase.inStatic, testCase.inShared, moduleName, correctAllOrdered, orderedAllDeps))
}
correctOutputDeps := expectedTransitiveDeps[moduleName]
if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) {
errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+
- "\nInput: %q"+
+ "\nin static:%q"+
+ "\nin shared:%q"+
"\nmodule: %v"+
"\nexpected: %s"+
"\nactual: %s",
- testCase.in, moduleName, correctOutputDeps, orderedDeclaredDeps))
+ testCase.inStatic, testCase.inShared, moduleName, correctOutputDeps, orderedDeclaredDeps))
}
}
@@ -493,7 +518,7 @@
return paths
}
-func TestLibDeps(t *testing.T) {
+func TestStaticLibDepReordering(t *testing.T) {
ctx := testCc(t, `
cc_library {
name: "a",
@@ -514,7 +539,7 @@
variant := "android_arm64_armv8-a_core_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- actual := moduleA.staticDepsInLinkOrder
+ actual := moduleA.depsInLinkOrder
expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"})
if !reflect.DeepEqual(actual, expected) {
@@ -527,6 +552,37 @@
}
}
+func TestStaticLibDepReorderingWithShared(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library {
+ name: "a",
+ static_libs: ["b", "c"],
+ }
+ cc_library {
+ name: "b",
+ }
+ cc_library {
+ name: "c",
+ shared_libs: ["b"],
+ }
+
+ `)
+
+ variant := "android_arm64_armv8-a_core_static"
+ moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
+ actual := moduleA.depsInLinkOrder
+ expected := getOutputPaths(ctx, variant, []string{"c", "b"})
+
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("staticDeps orderings did not account for shared libs"+
+ "\nactual: %v"+
+ "\nexpected: %v",
+ actual,
+ expected,
+ )
+ }
+}
+
var compilerFlagsTestCases = []struct {
in string
out bool
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index 207b161..556dad0 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -54,13 +54,14 @@
}
var (
- sortEntries = flag.Bool("s", false, "sort entries (defaults to the order from the input zip files)")
- emulateJar = flag.Bool("j", false, "sort zip entries using jar ordering (META-INF first)")
- stripDirs fileList
- stripFiles fileList
- zipsToNotStrip = make(zipsToNotStripSet)
- stripDirEntries = flag.Bool("D", false, "strip directory entries from the output zip file")
- manifest = flag.String("m", "", "manifest file to insert in jar")
+ sortEntries = flag.Bool("s", false, "sort entries (defaults to the order from the input zip files)")
+ emulateJar = flag.Bool("j", false, "sort zip entries using jar ordering (META-INF first)")
+ stripDirs fileList
+ stripFiles fileList
+ zipsToNotStrip = make(zipsToNotStripSet)
+ stripDirEntries = flag.Bool("D", false, "strip directory entries from the output zip file")
+ manifest = flag.String("m", "", "manifest file to insert in jar")
+ ignoreDuplicates = flag.Bool("ignore-duplicates", false, "take each entry from the first zip it exists in and don't warn")
)
func init() {
@@ -118,7 +119,7 @@
}
// do merge
- err = mergeZips(readers, writer, *manifest, *sortEntries, *emulateJar, *stripDirEntries)
+ err = mergeZips(readers, writer, *manifest, *sortEntries, *emulateJar, *stripDirEntries, *ignoreDuplicates)
if err != nil {
log.Fatal(err)
}
@@ -210,7 +211,7 @@
}
func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest string,
- sortEntries, emulateJar, stripDirEntries bool) error {
+ sortEntries, emulateJar, stripDirEntries, ignoreDuplicates bool) error {
sourceByDest := make(map[string]zipSource, 0)
orderedMappings := []fileMapping{}
@@ -266,6 +267,9 @@
return fmt.Errorf("Directory/file mismatch at %v from %v and %v\n",
dest, existingSource, source)
}
+ if ignoreDuplicates {
+ continue
+ }
if emulateJar &&
file.Name == jar.ManifestFile || file.Name == jar.ModuleInfoClass {
// Skip manifest and module info files that are not from the first input file
diff --git a/cmd/zip2zip/Android.bp b/cmd/zip2zip/Android.bp
index 6420219..68d8bc7 100644
--- a/cmd/zip2zip/Android.bp
+++ b/cmd/zip2zip/Android.bp
@@ -15,8 +15,9 @@
blueprint_go_binary {
name: "zip2zip",
deps: [
- "android-archive-zip",
- "soong-jar",
+ "android-archive-zip",
+ "blueprint-pathtools",
+ "soong-jar",
],
srcs: [
"zip2zip.go",
diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go
index f48d458..e8ea9b9 100644
--- a/cmd/zip2zip/zip2zip.go
+++ b/cmd/zip2zip/zip2zip.go
@@ -24,6 +24,8 @@
"strings"
"time"
+ "github.com/google/blueprint/pathtools"
+
"android/soong/jar"
"android/soong/third_party/zip"
)
@@ -36,8 +38,14 @@
setTime = flag.Bool("t", false, "set timestamps to 2009-01-01 00:00:00")
staticTime = time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
+
+ excludes excludeArgs
)
+func init() {
+ flag.Var(&excludes, "x", "exclude a filespec from the output")
+}
+
func main() {
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "usage: zip2zip -i zipfile -o zipfile [-s|-j] [-t] [filespec]...")
@@ -45,15 +53,14 @@
fmt.Fprintln(os.Stderr, " filespec:")
fmt.Fprintln(os.Stderr, " <name>")
fmt.Fprintln(os.Stderr, " <in_name>:<out_name>")
- fmt.Fprintln(os.Stderr, " <glob>:<out_dir>/")
+ fmt.Fprintln(os.Stderr, " <glob>[:<out_dir>]")
fmt.Fprintln(os.Stderr, "")
- fmt.Fprintln(os.Stderr, "<glob> uses the rules at https://golang.org/pkg/path/filepath/#Match")
- fmt.Fprintln(os.Stderr, "As a special exception, '**' is supported to specify all files in the input zip.")
+ fmt.Fprintln(os.Stderr, "<glob> uses the rules at https://godoc.org/github.com/google/blueprint/pathtools/#Match")
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "Files will be copied with their existing compression from the input zipfile to")
fmt.Fprintln(os.Stderr, "the output zipfile, in the order of filespec arguments.")
fmt.Fprintln(os.Stderr, "")
- fmt.Fprintln(os.Stderr, "If no filepsec is provided all files are copied (equivalent to '**').")
+ fmt.Fprintln(os.Stderr, "If no filepsec is provided all files and directories are copied.")
}
flag.Parse()
@@ -85,7 +92,9 @@
}
}()
- if err := zip2zip(&reader.Reader, writer, *sortGlobs, *sortJava, *setTime, flag.Args()); err != nil {
+ if err := zip2zip(&reader.Reader, writer, *sortGlobs, *sortJava, *setTime,
+ flag.Args(), excludes); err != nil {
+
log.Fatal(err)
}
}
@@ -95,91 +104,126 @@
newName string
}
-func zip2zip(reader *zip.Reader, writer *zip.Writer, sortGlobs, sortJava, setTime bool, args []string) error {
- if len(args) == 0 {
- // If no filespec is provided, default to copying everything
- args = []string{"**"}
- }
- for _, arg := range args {
- var input string
- var output string
+func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTime bool,
+ includes []string, excludes []string) error {
+ matches := []pair{}
+
+ sortMatches := func(matches []pair) {
+ if sortJava {
+ sort.SliceStable(matches, func(i, j int) bool {
+ return jar.EntryNamesLess(matches[i].newName, matches[j].newName)
+ })
+ } else if sortOutput {
+ sort.SliceStable(matches, func(i, j int) bool {
+ return matches[i].newName < matches[j].newName
+ })
+ }
+ }
+
+ for _, include := range includes {
// Reserve escaping for future implementation, so make sure no
// one is using \ and expecting a certain behavior.
- if strings.Contains(arg, "\\") {
+ if strings.Contains(include, "\\") {
return fmt.Errorf("\\ characters are not currently supported")
}
- args := strings.SplitN(arg, ":", 2)
- input = args[0]
- if len(args) == 2 {
- output = args[1]
- }
+ input, output := includeSplit(include)
- matches := []pair{}
- if strings.IndexAny(input, "*?[") >= 0 {
- matchAll := input == "**"
- if !matchAll && strings.Contains(input, "**") {
- return fmt.Errorf("** is only supported on its own, not with other characters")
- }
+ var includeMatches []pair
- for _, file := range reader.File {
- match := matchAll
-
- if !match {
- var err error
- match, err = filepath.Match(input, file.Name)
- if err != nil {
- return err
- }
- }
-
- if match {
- var newName string
- if output == "" {
- newName = file.Name
- } else {
+ for _, file := range reader.File {
+ var newName string
+ if match, err := pathtools.Match(input, file.Name); err != nil {
+ return err
+ } else if match {
+ if output == "" {
+ newName = file.Name
+ } else {
+ if pathtools.IsGlob(input) {
+ // If the input is a glob then the output is a directory.
_, name := filepath.Split(file.Name)
newName = filepath.Join(output, name)
+ } else {
+ // Otherwise it is a file.
+ newName = output
}
- matches = append(matches, pair{file, newName})
}
- }
-
- if sortJava {
- jarSort(matches)
- } else if sortGlobs {
- sort.SliceStable(matches, func(i, j int) bool {
- return matches[i].newName < matches[j].newName
- })
- }
- } else {
- if output == "" {
- output = input
- }
- for _, file := range reader.File {
- if input == file.Name {
- matches = append(matches, pair{file, output})
- break
- }
+ includeMatches = append(includeMatches, pair{file, newName})
}
}
- for _, match := range matches {
- if setTime {
- match.File.SetModTime(staticTime)
- }
- if err := writer.CopyFrom(match.File, match.newName); err != nil {
+ sortMatches(includeMatches)
+ matches = append(matches, includeMatches...)
+ }
+
+ if len(includes) == 0 {
+ // implicitly match everything
+ for _, file := range reader.File {
+ matches = append(matches, pair{file, file.Name})
+ }
+ sortMatches(matches)
+ }
+
+ var matchesAfterExcludes []pair
+ seen := make(map[string]*zip.File)
+
+ for _, match := range matches {
+ // Filter out matches whose original file name matches an exclude filter
+ excluded := false
+ for _, exclude := range excludes {
+ if excludeMatch, err := pathtools.Match(exclude, match.File.Name); err != nil {
return err
+ } else if excludeMatch {
+ excluded = true
+ break
}
}
+
+ if excluded {
+ continue
+ }
+
+ // Check for duplicate output names, ignoring ones that come from the same input zip entry.
+ if prev, exists := seen[match.newName]; exists {
+ if prev != match.File {
+ return fmt.Errorf("multiple entries for %q with different contents", match.newName)
+ }
+ continue
+ }
+ seen[match.newName] = match.File
+
+ matchesAfterExcludes = append(matchesAfterExcludes, match)
+ }
+
+ for _, match := range matchesAfterExcludes {
+ if setTime {
+ match.File.SetModTime(staticTime)
+ }
+ if err := writer.CopyFrom(match.File, match.newName); err != nil {
+ return err
+ }
}
return nil
}
-func jarSort(files []pair) {
- sort.SliceStable(files, func(i, j int) bool {
- return jar.EntryNamesLess(files[i].newName, files[j].newName)
- })
+func includeSplit(s string) (string, string) {
+ split := strings.SplitN(s, ":", 2)
+ if len(split) == 2 {
+ return split[0], split[1]
+ } else {
+ return split[0], ""
+ }
+}
+
+type excludeArgs []string
+
+func (e *excludeArgs) String() string {
+ return strings.Join(*e, " ")
+}
+
+func (e *excludeArgs) Set(s string) error {
+ *e = append(*e, s)
+ return nil
}
diff --git a/cmd/zip2zip/zip2zip_test.go b/cmd/zip2zip/zip2zip_test.go
index 53c8ce2..212ab28 100644
--- a/cmd/zip2zip/zip2zip_test.go
+++ b/cmd/zip2zip/zip2zip_test.go
@@ -30,6 +30,7 @@
sortGlobs bool
sortJava bool
args []string
+ excludes []string
outputFiles []string
err error
@@ -41,13 +42,6 @@
err: fmt.Errorf("\\ characters are not currently supported"),
},
- {
- name: "unsupported **",
-
- args: []string{"a/**:b"},
-
- err: fmt.Errorf("** is only supported on its own, not with other characters"),
- },
{ // This is modelled after the update package build rules in build/make/core/Makefile
name: "filter globs",
@@ -95,16 +89,19 @@
name: "sort all",
inputFiles: []string{
+ "RADIO/",
"RADIO/a",
+ "IMAGES/",
"IMAGES/system.img",
"IMAGES/b.txt",
"IMAGES/recovery.img",
"IMAGES/vendor.img",
+ "OTA/",
"OTA/b",
"OTA/android-info.txt",
},
sortGlobs: true,
- args: []string{"**"},
+ args: []string{"**/*"},
outputFiles: []string{
"IMAGES/b.txt",
@@ -120,11 +117,14 @@
name: "sort all implicit",
inputFiles: []string{
+ "RADIO/",
"RADIO/a",
+ "IMAGES/",
"IMAGES/system.img",
"IMAGES/b.txt",
"IMAGES/recovery.img",
"IMAGES/vendor.img",
+ "OTA/",
"OTA/b",
"OTA/android-info.txt",
},
@@ -132,12 +132,15 @@
args: nil,
outputFiles: []string{
+ "IMAGES/",
"IMAGES/b.txt",
"IMAGES/recovery.img",
"IMAGES/system.img",
"IMAGES/vendor.img",
+ "OTA/",
"OTA/android-info.txt",
"OTA/b",
+ "RADIO/",
"RADIO/a",
},
},
@@ -177,7 +180,7 @@
"b",
"a",
},
- args: []string{"a:a2", "**"},
+ args: []string{"a:a2", "**/*"},
outputFiles: []string{
"a2",
@@ -185,6 +188,69 @@
"a",
},
},
+ {
+ name: "multiple matches",
+
+ inputFiles: []string{
+ "a/a",
+ },
+ args: []string{"a/a", "a/*"},
+
+ outputFiles: []string{
+ "a/a",
+ },
+ },
+ {
+ name: "multiple conflicting matches",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ args: []string{"a/b:a/a", "a/*"},
+
+ err: fmt.Errorf(`multiple entries for "a/a" with different contents`),
+ },
+ {
+ name: "excludes",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ args: nil,
+ excludes: []string{"a/a"},
+
+ outputFiles: []string{
+ "a/b",
+ },
+ },
+ {
+ name: "excludes with include",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ args: []string{"a/*"},
+ excludes: []string{"a/a"},
+
+ outputFiles: []string{
+ "a/b",
+ },
+ },
+ {
+ name: "excludes with glob",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ args: []string{"a/*"},
+ excludes: []string{"a/*"},
+
+ outputFiles: nil,
+ },
}
func errorString(e error) string {
@@ -216,7 +282,7 @@
}
outputWriter := zip.NewWriter(outputBuf)
- err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false, testCase.args)
+ err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false, testCase.args, testCase.excludes)
if errorString(testCase.err) != errorString(err) {
t.Fatalf("Unexpected error:\n got: %q\nwant: %q", errorString(err), errorString(testCase.err))
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 1c0526a..df83faa 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -36,12 +36,16 @@
}
if library.dexJarFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", library.dexJarFile.String())
- if library.deviceProperties.Dex_preopt == nil || *library.deviceProperties.Dex_preopt == false {
+ if library.deviceProperties.Dex_preopt != nil && *library.deviceProperties.Dex_preopt == false {
fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
}
}
fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", String(library.deviceProperties.Sdk_version))
fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", library.headerJarFile.String())
+
+ if library.jacocoReportClassesFile != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", library.jacocoReportClassesFile.String())
+ }
},
},
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
diff --git a/java/app.go b/java/app.go
index 05cc975..68e4d5c 100644
--- a/java/app.go
+++ b/java/app.go
@@ -54,6 +54,8 @@
// list of directories relative to the Blueprints file containing
// Android resources
Resource_dirs []string
+
+ Instrumentation_for *string
}
type AndroidApp struct {
@@ -119,6 +121,10 @@
// a.properties.Proguard.Enabled = true
//}
+ if String(a.appProperties.Instrumentation_for) == "" {
+ a.properties.Instrument = true
+ }
+
a.Module.compile(ctx)
aaptPackageFlags := append([]string(nil), aaptFlags...)
diff --git a/java/config/config.go b/java/config/config.go
index 3cd2841..49481be 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -28,6 +28,16 @@
DefaultBootclasspathLibraries = []string{"core-oj", "core-libart"}
DefaultSystemModules = "core-system-modules"
DefaultLibraries = []string{"ext", "framework", "okhttp"}
+
+ DefaultJacocoExcludeFilter = []string{"org.junit.*", "org.jacoco.*", "org.mockito.*"}
+
+ InstrumentFrameworkModules = []string{
+ "framework",
+ "telephony-common",
+ "services",
+ "android.car",
+ "android.car7",
+ }
)
func init() {
@@ -74,6 +84,7 @@
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
pctx.HostBinToolVariable("MergeZipsCmd", "merge_zips")
+ pctx.HostBinToolVariable("Zip2ZipCmd", "zip2zip")
pctx.VariableFunc("DxCmd", func(config interface{}) (string, error) {
if config.(android.Config).IsEnvFalse("USE_D8") {
if config.(android.Config).UnbundledBuild() || config.(android.Config).IsPdkBuild() {
@@ -117,4 +128,6 @@
}
return "", nil
})
+
+ pctx.HostJavaToolVariable("JacocoCLIJar", "jacoco-cli.jar")
}
diff --git a/java/config/makevars.go b/java/config/makevars.go
index dabf2e7..b9009f3 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -62,4 +62,7 @@
ctx.Strict("SOONG_JAVAC_WRAPPER", "${SoongJavacWrapper}")
ctx.Strict("EXTRACT_SRCJARS", "${ExtractSrcJarsCmd}")
+
+ ctx.Strict("JACOCO_CLI_JAR", "${JacocoCLIJar}")
+ ctx.Strict("DEFAULT_JACOCO_EXCLUDE_FILTER", strings.Join(DefaultJacocoExcludeFilter, ","))
}
diff --git a/java/jacoco.go b/java/jacoco.go
new file mode 100644
index 0000000..b26b046
--- /dev/null
+++ b/java/jacoco.go
@@ -0,0 +1,108 @@
+// 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
+
+// Rules for instrumenting classes using jacoco
+
+import (
+ "strings"
+
+ "github.com/google/blueprint"
+
+ "android/soong/android"
+)
+
+var (
+ jacoco = pctx.AndroidStaticRule("jacoco", blueprint.RuleParams{
+ Command: `${config.Zip2ZipCmd} -i $in -o $strippedJar $stripSpec && ` +
+ `${config.JavaCmd} -jar ${config.JacocoCLIJar} instrument -quiet -dest $instrumentedJar $strippedJar && ` +
+ `${config.Ziptime} $instrumentedJar && ` +
+ `${config.MergeZipsCmd} --ignore-duplicates -j $out $instrumentedJar $in`,
+ CommandDeps: []string{
+ "${config.Zip2ZipCmd}",
+ "${config.JavaCmd}",
+ "${config.JacocoCLIJar}",
+ "${config.Ziptime}",
+ "${config.MergeZipsCmd}",
+ },
+ },
+ "strippedJar", "stripSpec", "instrumentedJar")
+)
+
+func jacocoInstrumentJar(ctx android.ModuleContext, outputJar, strippedJar android.WritablePath,
+ inputJar android.Path, stripSpec string) {
+ instrumentedJar := android.PathForModuleOut(ctx, "jacoco/instrumented.jar")
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: jacoco,
+ Description: "jacoco",
+ Output: outputJar,
+ ImplicitOutput: strippedJar,
+ Input: inputJar,
+ Args: map[string]string{
+ "strippedJar": strippedJar.String(),
+ "stripSpec": stripSpec,
+ "instrumentedJar": instrumentedJar.String(),
+ },
+ })
+}
+
+func (j *Module) jacocoStripSpecs(ctx android.ModuleContext) string {
+ includes := jacocoFiltersToSpecs(ctx,
+ j.properties.Jacoco.Include_filter, "jacoco.include_filter")
+ excludes := jacocoFiltersToSpecs(ctx,
+ j.properties.Jacoco.Exclude_filter, "jacoco.exclude_filter")
+
+ specs := ""
+ if len(excludes) > 0 {
+ specs += android.JoinWithPrefix(excludes, "-x") + " "
+ }
+
+ if len(includes) > 0 {
+ specs += strings.Join(includes, " ")
+ } else {
+ specs += "**/*.class"
+ }
+
+ return specs
+}
+
+func jacocoFiltersToSpecs(ctx android.ModuleContext, filters []string, property string) []string {
+ specs := make([]string, len(filters))
+ for i, f := range filters {
+ specs[i] = jacocoFilterToSpec(ctx, f, property)
+ }
+ return specs
+}
+
+func jacocoFilterToSpec(ctx android.ModuleContext, filter string, property string) string {
+ wildcard := strings.HasSuffix(filter, "*")
+ filter = strings.TrimSuffix(filter, "*")
+ recursiveWildcard := wildcard && (strings.HasSuffix(filter, ".") || filter == "")
+
+ if strings.ContainsRune(filter, '*') {
+ ctx.PropertyErrorf(property, "'*' is only supported as the last character in a filter")
+ }
+
+ spec := strings.Replace(filter, ".", "/", -1)
+
+ if recursiveWildcard {
+ spec += "**/*.class"
+ } else if wildcard {
+ spec += "*.class"
+ }
+
+ return spec
+}
diff --git a/java/java.go b/java/java.go
index b2bd2b0..417cf74 100644
--- a/java/java.go
+++ b/java/java.go
@@ -51,9 +51,6 @@
// Renderscript
// Post-jar passes:
// Proguard
-// Jacoco
-// Jarjar
-// Dex
// Rmtypedefs
// DroidDoc
// Findbugs
@@ -127,6 +124,26 @@
// List of javac flags that should only be used when passing -source 1.9
Javacflags []string
}
+
+ Jacoco struct {
+ // List of classes to include for instrumentation with jacoco to collect coverage
+ // information at runtime when building with coverage enabled. If unset defaults to all
+ // classes.
+ // Supports '*' as the last character of an entry in the list as a wildcard match.
+ // If preceded by '.' it matches all classes in the package and subpackages, otherwise
+ // it matches classes in the package that have the class name as a prefix.
+ Include_filter []string
+
+ // List of classes to exclude from instrumentation with jacoco to collect coverage
+ // information at runtime when building with coverage enabled. Overrides classes selected
+ // by the include_filter property.
+ // Supports '*' as the last character of an entry in the list as a wildcard match.
+ // If preceded by '.' it matches all classes in the package and subpackages, otherwise
+ // it matches classes in the package that have the class name as a prefix.
+ Exclude_filter []string
+ }
+
+ Instrument bool `blueprint:"mutated"`
}
type CompilerDeviceProperties struct {
@@ -177,6 +194,9 @@
// output file containing classes.dex
dexJarFile android.Path
+ // output file containing uninstrumented classes that will be instrumented by jacoco
+ jacocoReportClassesFile android.Path
+
// output file suitable for installing or running
outputFile android.Path
@@ -718,6 +738,20 @@
}
if ctx.Device() && j.installable() {
+ outputFile = j.desugar(ctx, flags, outputFile, jarName)
+ }
+
+ if ctx.AConfig().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+ if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
+ j.properties.Instrument = true
+ }
+ }
+
+ if ctx.AConfig().IsEnvTrue("EMMA_INSTRUMENT") && j.properties.Instrument {
+ outputFile = j.instrument(ctx, flags, outputFile, jarName)
+ }
+
+ if ctx.Device() && j.installable() {
outputFile = j.compileDex(ctx, flags, outputFile, jarName)
if ctx.Failed() {
return
@@ -766,6 +800,42 @@
return headerJar
}
+func (j *Module) desugar(ctx android.ModuleContext, flags javaBuilderFlags,
+ classesJar android.Path, jarName string) android.Path {
+
+ desugarFlags := []string{
+ "--min_sdk_version " + j.minSdkVersionNumber(ctx),
+ "--desugar_try_with_resources_if_needed=false",
+ "--allow_empty_bootclasspath",
+ }
+
+ if inList("--core-library", j.deviceProperties.Dxflags) {
+ desugarFlags = append(desugarFlags, "--core_library")
+ }
+
+ flags.desugarFlags = strings.Join(desugarFlags, " ")
+
+ desugarJar := android.PathForModuleOut(ctx, "desugar", jarName)
+ TransformDesugar(ctx, desugarJar, classesJar, flags)
+
+ return desugarJar
+}
+
+func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
+ classesJar android.Path, jarName string) android.Path {
+
+ specs := j.jacocoStripSpecs(ctx)
+
+ jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco", "jacoco-report-classes.jar")
+ instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName)
+
+ jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)
+
+ j.jacocoReportClassesFile = jacocoReportClassesFile
+
+ return instrumentedJar
+}
+
func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
classesJar android.Path, jarName string) android.Path {
@@ -792,47 +862,29 @@
"--dump-width=1000")
}
- var minSdkVersion string
- switch String(j.deviceProperties.Sdk_version) {
- case "", "current", "test_current", "system_current":
- minSdkVersion = strconv.Itoa(ctx.AConfig().DefaultAppTargetSdkInt())
- default:
- minSdkVersion = String(j.deviceProperties.Sdk_version)
- }
-
- dxFlags = append(dxFlags, "--min-sdk-version="+minSdkVersion)
+ dxFlags = append(dxFlags, "--min-sdk-version="+j.minSdkVersionNumber(ctx))
flags.dxFlags = strings.Join(dxFlags, " ")
- desugarFlags := []string{
- "--min_sdk_version " + minSdkVersion,
- "--desugar_try_with_resources_if_needed=false",
- "--allow_empty_bootclasspath",
- }
-
- if inList("--core-library", dxFlags) {
- desugarFlags = append(desugarFlags, "--core_library")
- }
-
- flags.desugarFlags = strings.Join(desugarFlags, " ")
-
- desugarJar := android.PathForModuleOut(ctx, "desugar", jarName)
- TransformDesugar(ctx, desugarJar, classesJar, flags)
- if ctx.Failed() {
- return nil
- }
-
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
- TransformClassesJarToDexJar(ctx, javalibJar, desugarJar, flags)
- if ctx.Failed() {
- return nil
- }
+ TransformClassesJarToDexJar(ctx, javalibJar, classesJar, flags)
j.dexJarFile = javalibJar
return javalibJar
}
+// Returns a sdk version as a string that is guaranteed to be a parseable as a number. For
+// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns "10000".
+func (j *Module) minSdkVersionNumber(ctx android.ModuleContext) string {
+ switch String(j.deviceProperties.Sdk_version) {
+ case "", "current", "test_current", "system_current":
+ return strconv.Itoa(ctx.AConfig().DefaultAppTargetSdkInt())
+ default:
+ return String(j.deviceProperties.Sdk_version)
+ }
+}
+
func (j *Module) installable() bool {
return j.properties.Installable == nil || *j.properties.Installable
}
diff --git a/java/java_test.go b/java/java_test.go
index e1c90ee..143e82c 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -52,10 +52,11 @@
os.Exit(run())
}
func testJava(t *testing.T, bp string) *android.TestContext {
- return testJavaWithEnv(t, bp, nil)
+ return testJavaWithEnvFs(t, bp, nil, nil)
}
-func testJavaWithEnv(t *testing.T, bp string, env map[string]string) *android.TestContext {
+func testJavaWithEnvFs(t *testing.T, bp string,
+ env map[string]string, fs map[string][]byte) *android.TestContext {
config := android.TestArchConfig(buildDir, env)
ctx := android.NewTestArchContext()
@@ -112,17 +113,17 @@
}
}
- ctx.MockFileSystem(map[string][]byte{
- "Android.bp": []byte(bp),
- "a.java": nil,
- "b.java": nil,
- "c.java": nil,
- "b.kt": nil,
- "a.jar": nil,
- "b.jar": nil,
- "res/a": nil,
- "res/b": nil,
- "res2/a": nil,
+ mockFS := map[string][]byte{
+ "Android.bp": []byte(bp),
+ "a.java": nil,
+ "b.java": nil,
+ "c.java": nil,
+ "b.kt": nil,
+ "a.jar": nil,
+ "b.jar": nil,
+ "java-res/a": nil,
+ "java-res/b": nil,
+ "java-res2/a": nil,
"prebuilts/sdk/14/android.jar": nil,
"prebuilts/sdk/14/framework.aidl": nil,
@@ -132,7 +133,13 @@
"prebuilts/sdk/system_current/framework.aidl": nil,
"prebuilts/sdk/test_current/android.jar": nil,
"prebuilts/sdk/test_current/framework.aidl": nil,
- })
+ }
+
+ for k, v := range fs {
+ mockFS[k] = v
+ }
+
+ ctx.MockFileSystem(mockFS)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
fail(t, errs)
@@ -394,7 +401,7 @@
// Test again with javac 1.9
t.Run("1.9", func(t *testing.T) {
- ctx := testJavaWithEnv(t, bp, map[string]string{"EXPERIMENTAL_USE_OPENJDK9": "true"})
+ ctx := testJavaWithEnvFs(t, bp, map[string]string{"EXPERIMENTAL_USE_OPENJDK9": "true"}, nil)
javac := ctx.ModuleForTests("foo", variant).Rule("javac")
got := javac.Args["bootClasspath"]
@@ -497,14 +504,14 @@
{
// Test that a module with java_resource_dirs includes the files
name: "resource dirs",
- prop: `java_resource_dirs: ["res"]`,
- args: "-C res -f res/a -f res/b",
+ prop: `java_resource_dirs: ["java-res"]`,
+ args: "-C java-res -f java-res/a -f java-res/b",
},
{
// 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 -f res/b",
+ prop: `java_resources: ["java-res/a", "java-res/b"]`,
+ args: "-C . -f java-res/a -f java-res/b",
},
{
// Test that a module with a filegroup in java_resources includes the files with the
@@ -514,10 +521,10 @@
extra: `
filegroup {
name: "foo-res",
- path: "res",
- srcs: ["res/a", "res/b"],
+ path: "java-res",
+ srcs: ["java-res/a", "java-res/b"],
}`,
- args: "-C res -f res/a -f res/b",
+ args: "-C java-res -f java-res/a -f java-res/b",
},
{
// Test that a module with "include_srcs: true" includes its source files in the resources jar
@@ -562,21 +569,21 @@
java_library {
name: "foo",
srcs: ["a.java"],
- java_resource_dirs: ["res", "res2"],
- exclude_java_resource_dirs: ["res2"],
+ java_resource_dirs: ["java-res", "java-res2"],
+ exclude_java_resource_dirs: ["java-res2"],
}
java_library {
name: "bar",
srcs: ["a.java"],
- java_resources: ["res/*"],
- exclude_java_resources: ["res/b"],
+ java_resources: ["java-res/*"],
+ exclude_java_resources: ["java-res/b"],
}
`)
fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar")
- expected := "-C res -f res/a -f res/b"
+ expected := "-C java-res -f java-res/a -f java-res/b"
if fooRes.Args["jarArgs"] != expected {
t.Errorf("foo resource jar args %q is not %q",
fooRes.Args["jarArgs"], expected)
@@ -585,7 +592,7 @@
barRes := ctx.ModuleForTests("bar", "android_common").Output("res/bar.jar")
- expected = "-C . -f res/a"
+ expected = "-C . -f java-res/a"
if barRes.Args["jarArgs"] != expected {
t.Errorf("bar resource jar args %q is not %q",
barRes.Args["jarArgs"], expected)
@@ -606,7 +613,7 @@
genrule {
name: "gen",
- tool_files: ["res/a"],
+ tool_files: ["java-res/a"],
out: ["gen.java"],
}
`)