1// Copyright 2015 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package java 16 17// This file generates the final rules for compiling all Java. All properties related to 18// compiling should have been translated into javaBuilderFlags or another argument to the Transform* 19// functions. 20 21import ( 22 "path/filepath" 23 "strings" 24 25 "github.com/google/blueprint" 26 "github.com/google/blueprint/proptools" 27 28 "android/soong/android" 29 "android/soong/remoteexec" 30) 31 32var ( 33 Signapk, SignapkRE = pctx.RemoteStaticRules("signapk", 34 blueprint.RuleParams{ 35 Command: `rm -f $out && $reTemplate${config.JavaCmd} ${config.JavaVmFlags} -Djava.library.path=$$(dirname ${config.SignapkJniLibrary}) ` + 36 `-jar ${config.SignapkCmd} $flags $certificates $in $out`, 37 CommandDeps: []string{"${config.SignapkCmd}", "${config.SignapkJniLibrary}"}, 38 }, 39 &remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "signapk"}, 40 ExecStrategy: "${config.RESignApkExecStrategy}", 41 Inputs: []string{"${config.SignapkCmd}", "$in", "$$(dirname ${config.SignapkJniLibrary})", "$implicits"}, 42 OutputFiles: []string{"$outCommaList"}, 43 ToolchainInputs: []string{"${config.JavaCmd}"}, 44 Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, 45 }, []string{"flags", "certificates"}, []string{"implicits", "outCommaList"}) 46) 47 48var combineApk = pctx.AndroidStaticRule("combineApk", 49 blueprint.RuleParams{ 50 Command: `${config.MergeZipsCmd} $out $in`, 51 CommandDeps: []string{"${config.MergeZipsCmd}"}, 52 }) 53 54func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, 55 packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string) { 56 57 unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk" 58 unsignedApk := android.PathForModuleOut(ctx, unsignedApkName) 59 60 var inputs android.Paths 61 if dexJarFile != nil { 62 inputs = append(inputs, dexJarFile) 63 } 64 inputs = append(inputs, packageFile) 65 if jniJarFile != nil { 66 inputs = append(inputs, jniJarFile) 67 } 68 ctx.Build(pctx, android.BuildParams{ 69 Rule: combineApk, 70 Inputs: inputs, 71 Output: unsignedApk, 72 Implicits: deps, 73 }) 74 SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile, lineageFile, rotationMinSdkVersion) 75} 76 77func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string) { 78 79 var certificateArgs []string 80 var deps android.Paths 81 for _, c := range certificates { 82 certificateArgs = append(certificateArgs, c.Pem.String(), c.Key.String()) 83 deps = append(deps, c.Pem, c.Key) 84 } 85 outputFiles := android.WritablePaths{signedApk} 86 var flags []string 87 if v4SignatureFile != nil { 88 outputFiles = append(outputFiles, v4SignatureFile) 89 flags = append(flags, "--enable-v4") 90 } 91 92 if lineageFile != nil { 93 flags = append(flags, "--lineage", lineageFile.String()) 94 deps = append(deps, lineageFile) 95 } 96 97 if rotationMinSdkVersion != "" { 98 flags = append(flags, "--rotation-min-sdk-version", rotationMinSdkVersion) 99 } 100 101 rule := Signapk 102 args := map[string]string{ 103 "certificates": strings.Join(certificateArgs, " "), 104 "flags": strings.Join(flags, " "), 105 } 106 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_SIGNAPK") { 107 rule = SignapkRE 108 args["implicits"] = strings.Join(deps.Strings(), ",") 109 args["outCommaList"] = strings.Join(outputFiles.Strings(), ",") 110 } 111 ctx.Build(pctx, android.BuildParams{ 112 Rule: rule, 113 Description: "signapk", 114 Outputs: outputFiles, 115 Input: unsignedApk, 116 Implicits: deps, 117 Args: args, 118 }) 119} 120 121var buildAAR = pctx.AndroidStaticRule("buildAAR", 122 blueprint.RuleParams{ 123 Command: `rm -rf ${outDir} && mkdir -p ${outDir} && ` + 124 `cp ${manifest} ${outDir}/AndroidManifest.xml && ` + 125 `cp ${classesJar} ${outDir}/classes.jar && ` + 126 `cp ${rTxt} ${outDir}/R.txt && ` + 127 `${config.SoongZipCmd} -jar -o $out -C ${outDir} -D ${outDir}`, 128 CommandDeps: []string{"${config.SoongZipCmd}"}, 129 }, 130 "manifest", "classesJar", "rTxt", "outDir") 131 132func BuildAAR(ctx android.ModuleContext, outputFile android.WritablePath, 133 classesJar, manifest, rTxt android.Path, res android.Paths) { 134 135 // TODO(ccross): uniquify and copy resources with dependencies 136 137 deps := android.Paths{manifest, rTxt} 138 classesJarPath := "" 139 if classesJar != nil { 140 deps = append(deps, classesJar) 141 classesJarPath = classesJar.String() 142 } 143 144 ctx.Build(pctx, android.BuildParams{ 145 Rule: buildAAR, 146 Description: "aar", 147 Implicits: deps, 148 Output: outputFile, 149 Args: map[string]string{ 150 "manifest": manifest.String(), 151 "classesJar": classesJarPath, 152 "rTxt": rTxt.String(), 153 "outDir": android.PathForModuleOut(ctx, "aar").String(), 154 }, 155 }) 156} 157 158var buildBundleModule = pctx.AndroidStaticRule("buildBundleModule", 159 blueprint.RuleParams{ 160 Command: `${config.MergeZipsCmd} ${out} ${in}`, 161 CommandDeps: []string{"${config.MergeZipsCmd}"}, 162 }) 163 164var bundleMungePackage = pctx.AndroidStaticRule("bundleMungePackage", 165 blueprint.RuleParams{ 166 Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} AndroidManifest.xml:manifest/AndroidManifest.xml resources.pb "res/**/*" "assets/**/*"`, 167 CommandDeps: []string{"${config.Zip2ZipCmd}"}, 168 }) 169 170var bundleMungeDexJar = pctx.AndroidStaticRule("bundleMungeDexJar", 171 blueprint.RuleParams{ 172 Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} "classes*.dex:dex/" && ` + 173 `${config.Zip2ZipCmd} -i ${in} -o ${resJar} -x "classes*.dex" "**/*:root/"`, 174 CommandDeps: []string{"${config.Zip2ZipCmd}"}, 175 }, "resJar") 176 177// Builds an app into a module suitable for input to bundletool 178func BuildBundleModule(ctx android.ModuleContext, outputFile android.WritablePath, 179 packageFile, jniJarFile, dexJarFile android.Path) { 180 181 protoResJarFile := android.PathForModuleOut(ctx, "package-res.pb.apk") 182 aapt2Convert(ctx, protoResJarFile, packageFile, "proto") 183 184 var zips android.Paths 185 186 mungedPackage := android.PathForModuleOut(ctx, "bundle", "apk.zip") 187 ctx.Build(pctx, android.BuildParams{ 188 Rule: bundleMungePackage, 189 Input: protoResJarFile, 190 Output: mungedPackage, 191 Description: "bundle apk", 192 }) 193 zips = append(zips, mungedPackage) 194 195 if dexJarFile != nil { 196 mungedDexJar := android.PathForModuleOut(ctx, "bundle", "dex.zip") 197 mungedResJar := android.PathForModuleOut(ctx, "bundle", "res.zip") 198 ctx.Build(pctx, android.BuildParams{ 199 Rule: bundleMungeDexJar, 200 Input: dexJarFile, 201 Output: mungedDexJar, 202 ImplicitOutput: mungedResJar, 203 Description: "bundle dex", 204 Args: map[string]string{ 205 "resJar": mungedResJar.String(), 206 }, 207 }) 208 zips = append(zips, mungedDexJar, mungedResJar) 209 } 210 if jniJarFile != nil { 211 zips = append(zips, jniJarFile) 212 } 213 214 ctx.Build(pctx, android.BuildParams{ 215 Rule: buildBundleModule, 216 Inputs: zips, 217 Output: outputFile, 218 Description: "bundle", 219 }) 220} 221 222func TransformJniLibsToJar( 223 ctx android.ModuleContext, 224 outputFile android.WritablePath, 225 jniLibs []jniLib, 226 prebuiltJniPackages android.Paths, 227 uncompressJNI bool) { 228 229 var deps android.Paths 230 jarArgs := []string{ 231 "-j", // junk paths, they will be added back with -P arguments 232 } 233 234 if uncompressJNI { 235 jarArgs = append(jarArgs, "-L", "0") 236 } 237 238 for _, j := range jniLibs { 239 deps = append(deps, j.path) 240 jarArgs = append(jarArgs, 241 "-P", targetToJniDir(j.target), 242 "-f", j.path.String()) 243 } 244 245 rule := zip 246 args := map[string]string{ 247 "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "), 248 } 249 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ZIP") { 250 rule = zipRE 251 args["implicits"] = strings.Join(deps.Strings(), ",") 252 } 253 var jniJarPath android.WritablePath = android.PathForModuleOut(ctx, "jniJarOutput.zip") 254 if len(prebuiltJniPackages) == 0 { 255 jniJarPath = outputFile 256 } 257 ctx.Build(pctx, android.BuildParams{ 258 Rule: rule, 259 Description: "zip jni libs", 260 Output: jniJarPath, 261 Implicits: deps, 262 Args: args, 263 }) 264 if len(prebuiltJniPackages) > 0 { 265 var mergeJniJarPath android.WritablePath = android.PathForModuleOut(ctx, "mergeJniJarOutput.zip") 266 if !uncompressJNI { 267 mergeJniJarPath = outputFile 268 } 269 ctx.Build(pctx, android.BuildParams{ 270 Rule: mergeAssetsRule, 271 Description: "merge prebuilt JNI packages", 272 Inputs: append(prebuiltJniPackages, jniJarPath), 273 Output: mergeJniJarPath, 274 }) 275 276 if uncompressJNI { 277 ctx.Build(pctx, android.BuildParams{ 278 Rule: uncompressEmbeddedJniLibsRule, 279 Input: mergeJniJarPath, 280 Output: outputFile, 281 }) 282 } 283 } 284} 285 286func (a *AndroidApp) generateJavaUsedByApex(ctx android.ModuleContext) { 287 javaApiUsedByOutputFile := android.PathForModuleOut(ctx, a.installApkName+"_using.xml") 288 javaUsedByRule := android.NewRuleBuilder(pctx, ctx) 289 javaUsedByRule.Command(). 290 Tool(android.PathForSource(ctx, "build/soong/scripts/gen_java_usedby_apex.sh")). 291 BuiltTool("dexdeps"). 292 Output(javaApiUsedByOutputFile). 293 Input(a.Library.Module.outputFile) 294 javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex") 295 a.javaApiUsedByOutputFile = javaApiUsedByOutputFile 296} 297 298func targetToJniDir(target android.Target) string { 299 return filepath.Join("lib", target.Arch.Abi[0]) 300} 301