diff --git a/cmd/merge_zips/Android.bp b/cmd/merge_zips/Android.bp index 03a5f3bea..ab658fd0d 100644 --- a/cmd/merge_zips/Android.bp +++ b/cmd/merge_zips/Android.bp @@ -16,6 +16,7 @@ blueprint_go_binary { name: "merge_zips", deps: [ "android-archive-zip", + "blueprint-pathtools", "soong-jar", ], srcs: [ diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go index 84eace608..95ff70b06 100644 --- a/cmd/merge_zips/merge_zips.go +++ b/cmd/merge_zips/merge_zips.go @@ -24,7 +24,8 @@ import ( "os" "path/filepath" "sort" - "strings" + + "github.com/google/blueprint/pathtools" "android/soong/jar" "android/soong/third_party/zip" @@ -69,8 +70,8 @@ var ( ) func init() { - flag.Var(&stripDirs, "stripDir", "the prefix of file path to be excluded from the output zip") - flag.Var(&stripFiles, "stripFile", "filenames to be excluded from the output zip, accepts wildcards") + flag.Var(&stripDirs, "stripDir", "directories to be excluded from the output zip, accepts wildcards") + flag.Var(&stripFiles, "stripFile", "files to be excluded from the output zip, accepts wildcards") flag.Var(&zipsToNotStrip, "zipToNotStrip", "the input zip file which is not applicable for stripping") } @@ -339,8 +340,12 @@ func mergeZips(readers []namedZipReader, writer *zip.Writer, manifest, entrypoin for _, namedReader := range readers { _, skipStripThisZip := zipsToNotStrip[namedReader.path] for _, file := range namedReader.reader.File { - if !skipStripThisZip && shouldStripFile(emulateJar, stripFiles, stripDirs, file.Name) { - continue + if !skipStripThisZip { + if skip, err := shouldStripEntry(emulateJar, stripFiles, stripDirs, file.Name); err != nil { + return err + } else if skip { + continue + } } if stripDirEntries && file.FileInfo().IsDir() { @@ -420,26 +425,41 @@ func pathBeforeLastSlash(path string) string { return ret } -func shouldStripFile(emulateJar bool, stripFiles, stripDirs []string, name string) bool { +func shouldStripEntry(emulateJar bool, stripFiles, stripDirs []string, name string) (bool, error) { for _, dir := range stripDirs { - if strings.HasPrefix(name, dir+"/") { - if emulateJar { - if name != jar.MetaDir && name != jar.ManifestFile { - return true + dir = filepath.Clean(dir) + patterns := []string{ + dir + "/", // the directory itself + dir + "/**/*", // files recursively in the directory + dir + "/**/*/", // directories recursively in the directory + } + + for _, pattern := range patterns { + match, err := pathtools.Match(pattern, name) + if err != nil { + return false, fmt.Errorf("%s: %s", err.Error(), pattern) + } else if match { + if emulateJar { + // When merging jar files, don't strip META-INF/MANIFEST.MF even if stripping META-INF is + // requested. + // TODO(ccross): which files does this affect? + if name != jar.MetaDir && name != jar.ManifestFile { + return true, nil + } } - } else { - return true + return true, nil } } } + for _, pattern := range stripFiles { - if match, err := filepath.Match(pattern, filepath.Base(name)); err != nil { - panic(fmt.Errorf("%s: %s", err.Error(), pattern)) + if match, err := pathtools.Match(pattern, name); err != nil { + return false, fmt.Errorf("%s: %s", err.Error(), pattern) } else if match { - return true + return true, nil } } - return false + return false, nil } func jarSort(files []fileMapping) { diff --git a/cmd/merge_zips/merge_zips_test.go b/cmd/merge_zips/merge_zips_test.go index 21a7e9a03..f91111f14 100644 --- a/cmd/merge_zips/merge_zips_test.go +++ b/cmd/merge_zips/merge_zips_test.go @@ -135,13 +135,33 @@ func TestMergeZips(t *testing.T) { stripDirEntries: true, }, { + name: "strip files", + in: [][]testZipEntry{ + {a, bDir, bbDir, bbb, bc, bd, be}, + }, + out: []testZipEntry{a, bDir, bbDir, bbb, bc}, + + stripFiles: []string{"b/d", "b/e"}, + }, + { + // merge_zips used to treat -stripFile a as stripping any file named a, it now only strips a in the + // root of the zip. name: "strip file name", in: [][]testZipEntry{ {a, bDir, ba}, }, + out: []testZipEntry{bDir, ba}, + + stripFiles: []string{"a"}, + }, + { + name: "strip files glob", + in: [][]testZipEntry{ + {a, bDir, ba}, + }, out: []testZipEntry{bDir}, - stripFiles: []string{"a"}, + stripFiles: []string{"**/a"}, }, { name: "strip dirs", @@ -152,6 +172,15 @@ func TestMergeZips(t *testing.T) { stripDirs: []string{"b"}, }, + { + name: "strip dirs glob", + in: [][]testZipEntry{ + {a, bDir, bbDir, bbb, bc, bd, be}, + }, + out: []testZipEntry{a, bDir, bc, bd, be}, + + stripDirs: []string{"b/*"}, + }, { name: "zips to not strip", in: [][]testZipEntry{ diff --git a/java/dex.go b/java/dex.go index 06ee272de..db240fc53 100644 --- a/java/dex.go +++ b/java/dex.go @@ -27,7 +27,7 @@ var d8 = pctx.AndroidStaticRule("d8", Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + `${config.D8Cmd} --output $outDir $dxFlags $in && ` + `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` + - `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`, + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ "${config.D8Cmd}", "${config.SoongZipCmd}", @@ -44,7 +44,7 @@ var r8 = pctx.AndroidStaticRule("r8", `-printmapping $outDict ` + `$dxFlags $r8Flags && ` + `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` + - `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`, + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ "${config.R8Cmd}", "${config.SoongZipCmd}", diff --git a/java/java.go b/java/java.go index 5cbd8bacc..89aa0e14f 100644 --- a/java/java.go +++ b/java/java.go @@ -1032,7 +1032,9 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path if Bool(j.properties.Renamed_kotlin_stdlib) { // Remove any kotlin-reflect related files // TODO(pszczepaniak): Support kotlin-reflect - stripFiles = append(stripFiles, "*.kotlin_module", "*.kotlin_builtin") + stripFiles = append(stripFiles, + "**/*.kotlin_module", + "**/*.kotlin_builtin") } else { // Only add kotlin-stdlib if not using (on-device) renamed stdlib // (it's expected to be on device bootclasspath)