diff --git a/java/builder.go b/java/builder.go index 017f64f8b..efe0a6bbe 100644 --- a/java/builder.go +++ b/java/builder.go @@ -41,8 +41,9 @@ var ( `${config.JavacWrapper}${config.JavacCmd} ${config.CommonJdkFlags} ` + `$javacFlags $bootClasspath $classpath ` + `-source $javaVersion -target $javaVersion ` + - `-d $outDir -s $annoDir @$out.rsp || ( rm -rf "$outDir"; exit 41 ) && ` + - `find $outDir -name "*.class" > $out`, + `-d $outDir -s $annoDir @$out.rsp && ` + + `find $outDir -type f | sort | ${config.JarArgsCmd} $outDir > $out`, + CommandDeps: []string{"${config.JavacCmd}", "${config.JarArgsCmd}"}, Rspfile: "$out.rsp", RspfileContent: "$in", }, @@ -50,17 +51,17 @@ var ( jar = pctx.AndroidStaticRule("jar", blueprint.RuleParams{ - Command: `${config.SoongZipCmd} -o $out -d $jarArgs`, - CommandDeps: []string{"${config.SoongZipCmd}"}, + Command: `${config.JarCmd} $operation ${out}.tmp $manifest $jarArgs && ${config.Zip2ZipCmd} -t -i ${out}.tmp -o ${out} && rm ${out}.tmp`, + CommandDeps: []string{"${config.JarCmd}"}, }, - "jarCmd", "jarArgs") + "operation", "manifest", "jarArgs") dx = pctx.AndroidStaticRule("dx", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + - `${config.DxCmd} --dex --output=$outDir $dxFlags $in || ( rm -rf "$outDir"; exit 41 ) && ` + - `find "$outDir" -name "classes*.dex" | sort > $out`, - CommandDeps: []string{"${config.DxCmd}"}, + `${config.DxCmd} --dex --output=$outDir $dxFlags $in && ` + + `find "$outDir" -name "classes*.dex" | sort | ${config.JarArgsCmd} ${outDir} > $out`, + CommandDeps: []string{"${config.DxCmd}", "${config.JarArgsCmd}"}, }, "outDir", "dxFlags") @@ -74,11 +75,18 @@ var ( extractPrebuilt = pctx.AndroidStaticRule("extractPrebuilt", blueprint.RuleParams{ Command: `rm -rf $outDir && unzip -qo $in -d $outDir && ` + - `find $outDir -name "*.class" > $classFile && ` + - `find $outDir -type f -a \! -name "*.class" -a \! -name "MANIFEST.MF" > $resourceFile || ` + - `(rm -rf $outDir; exit 42)`, + `find $outDir -name "*.class" | sort | ${config.JarArgsCmd} ${outDir} > $classFile && ` + + `find $outDir -type f -a \! -name "*.class" -a \! -name "MANIFEST.MF" | sort | ${config.JarArgsCmd} ${outDir} > $resourceFile`, + CommandDeps: []string{"${config.JarArgsCmd}"}, }, "outDir", "classFile", "resourceFile") + + fileListToJarArgs = pctx.AndroidStaticRule("fileListToJarArgs", + blueprint.RuleParams{ + Command: `${config.JarArgsCmd} -f $in -p ${outDir} -o $out`, + CommandDeps: []string{"${config.JarjarCmd}"}, + }, + "outDir") ) func init() { @@ -95,11 +103,15 @@ type javaBuilderFlags struct { } type jarSpec struct { - fileList, dir android.Path + android.ModuleOutPath } -func (j jarSpec) soongJarArgs() string { - return "-C " + j.dir.String() + " -l " + j.fileList.String() +func (j jarSpec) jarArgs() string { + return "@" + j.String() +} + +func (j jarSpec) path() android.Path { + return j.ModuleOutPath } func TransformJavaToClasses(ctx android.ModuleContext, srcFiles android.Paths, srcFileLists android.Paths, @@ -129,7 +141,7 @@ func TransformJavaToClasses(ctx android.ModuleContext, srcFiles android.Paths, s }, }) - return jarSpec{classFileList, classDir} + return jarSpec{classFileList} } func TransformClassesToJar(ctx android.ModuleContext, classes []jarSpec, @@ -141,13 +153,14 @@ func TransformClassesToJar(ctx android.ModuleContext, classes []jarSpec, jarArgs := []string{} for _, j := range classes { - deps = append(deps, j.fileList) - jarArgs = append(jarArgs, j.soongJarArgs()) + deps = append(deps, j.path()) + jarArgs = append(jarArgs, j.jarArgs()) } + operation := "cf" if manifest.Valid() { + operation = "cfm" deps = append(deps, manifest.Path()) - jarArgs = append(jarArgs, "-m "+manifest.String()) } ctx.ModuleBuild(pctx, android.ModuleBuildParams{ @@ -156,7 +169,9 @@ func TransformClassesToJar(ctx android.ModuleContext, classes []jarSpec, Output: outputFile, Implicits: deps, Args: map[string]string{ - "jarArgs": strings.Join(jarArgs, " "), + "jarArgs": strings.Join(jarArgs, " "), + "operation": operation, + "manifest": manifest.String(), }, }) @@ -180,7 +195,7 @@ func TransformClassesJarToDex(ctx android.ModuleContext, classesJar android.Path }, }) - return jarSpec{outputFile, outDir} + return jarSpec{outputFile} } func TransformDexToJavaLib(ctx android.ModuleContext, resources []jarSpec, @@ -191,12 +206,12 @@ func TransformDexToJavaLib(ctx android.ModuleContext, resources []jarSpec, var jarArgs []string for _, j := range resources { - deps = append(deps, j.fileList) - jarArgs = append(jarArgs, j.soongJarArgs()) + deps = append(deps, j.path()) + jarArgs = append(jarArgs, j.jarArgs()) } - deps = append(deps, dexJarSpec.fileList) - jarArgs = append(jarArgs, dexJarSpec.soongJarArgs()) + deps = append(deps, dexJarSpec.path()) + jarArgs = append(jarArgs, dexJarSpec.jarArgs()) ctx.ModuleBuild(pctx, android.ModuleBuildParams{ Rule: jar, @@ -204,7 +219,8 @@ func TransformDexToJavaLib(ctx android.ModuleContext, resources []jarSpec, Output: outputFile, Implicits: deps, Args: map[string]string{ - "jarArgs": strings.Join(jarArgs, " "), + "operation": "cf", + "jarArgs": strings.Join(jarArgs, " "), }, }) @@ -246,5 +262,21 @@ func TransformPrebuiltJarToClasses(ctx android.ModuleContext, }, }) - return jarSpec{classFileList, classDir}, jarSpec{resourceFileList, classDir} + return jarSpec{classFileList}, jarSpec{resourceFileList} +} + +func TransformFileListToJarSpec(ctx android.ModuleContext, dir, fileListFile android.Path) jarSpec { + outputFile := android.PathForModuleOut(ctx, fileListFile.Base()+".jarArgs") + + ctx.ModuleBuild(pctx, android.ModuleBuildParams{ + Rule: fileListToJarArgs, + Description: "file list to jar args", + Output: outputFile, + Input: fileListFile, + Args: map[string]string{ + "outDir": dir.String(), + }, + }) + + return jarSpec{outputFile} } diff --git a/java/config/config.go b/java/config/config.go index 44651cb4c..90d0fb51c 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -53,7 +53,8 @@ func init() { pctx.SourcePathVariable("JarCmd", "${JavaToolchain}/jar") pctx.SourcePathVariable("JavadocCmd", "${JavaToolchain}/javadoc") - pctx.StaticVariable("SoongZipCmd", filepath.Join("${bootstrap.ToolDir}", "soong_zip")) + pctx.StaticVariable("Zip2ZipCmd", filepath.Join("${bootstrap.ToolDir}", "zip2zip")) + pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh") pctx.HostBinToolVariable("DxCmd", "dx") pctx.HostJavaToolVariable("JarjarCmd", "jarjar.jar") diff --git a/java/resources.go b/java/resources.go index 60dc9349f..f1c9d0659 100644 --- a/java/resources.go +++ b/java/resources.go @@ -63,7 +63,7 @@ func ResourceDirsToJarSpecs(ctx android.ModuleContext, resourceDirs, excludeDirs pattern := filepath.Join(dir.String(), "**/*") bootstrap.GlobFile(ctx, pattern, excludes, fileListFile.String(), depFile) - jarSpecs = append(jarSpecs, jarSpec{fileListFile, dir}) + jarSpecs = append(jarSpecs, TransformFileListToJarSpec(ctx, dir, fileListFile)) } } diff --git a/scripts/jar-args.sh b/scripts/jar-args.sh new file mode 100755 index 000000000..9f05394d3 --- /dev/null +++ b/scripts/jar-args.sh @@ -0,0 +1,64 @@ +#!/bin/bash -e + +# Script that takes a list of files on stdin and converts it to arguments to jar on stdout +# Usage: +# find $dir -type f | sort | jar-args.sh $dir > jar_args.txt +# jar cf out.jar @jar_args.txt + +case $(uname) in + Linux) + extended_re=-r + ;; + Darwin) + extended_re=-E + ;; + *) echo "unknown OS:" $(uname) >&2 && exit 1;; +esac + +if [ "$1" == "--test" ]; then + in=$(mktemp) + expected=$(mktemp) + out=$(mktemp) + cat > $in < $expected < $out + + if cmp $out $expected; then + status=0 + echo "PASS" + else + status=1 + echo "FAIL" + echo "got:" + cat $out + echo "expected:" + cat $expected + fi + rm -f $in $expected $out + exit $status +fi + +# In order, the regexps: +# - Strip $1/ from the beginning of each line, and everything from lines that just have $1 +# - Escape single and double quotes, '#', ' ', and '\' +# - Prefix each non-blank line with -C $1 +sed ${extended_re} \ + -e"s,^$1(/|\$),," \ + -e"s,(['\\]),\\\\\1,g" \ + -e"s,^(.+),-C '$1' '\1',"