• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, shrinkResources bool) {
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
75	if shrinkResources {
76		shrunkenApk := android.PathForModuleOut(ctx, "resource-shrunken", unsignedApk.Base())
77		ShrinkResources(ctx, unsignedApk, shrunkenApk)
78		unsignedApk = shrunkenApk
79	}
80	SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile, lineageFile, rotationMinSdkVersion)
81}
82
83func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string) {
84
85	var certificateArgs []string
86	var deps android.Paths
87	for _, c := range certificates {
88		certificateArgs = append(certificateArgs, c.Pem.String(), c.Key.String())
89		deps = append(deps, c.Pem, c.Key)
90	}
91	outputFiles := android.WritablePaths{signedApk}
92	var flags []string
93	if v4SignatureFile != nil {
94		outputFiles = append(outputFiles, v4SignatureFile)
95		flags = append(flags, "--enable-v4")
96	}
97
98	if lineageFile != nil {
99		flags = append(flags, "--lineage", lineageFile.String())
100		deps = append(deps, lineageFile)
101	}
102
103	if rotationMinSdkVersion != "" {
104		flags = append(flags, "--rotation-min-sdk-version", rotationMinSdkVersion)
105	}
106
107	rule := Signapk
108	args := map[string]string{
109		"certificates": strings.Join(certificateArgs, " "),
110		"flags":        strings.Join(flags, " "),
111	}
112	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_SIGNAPK") {
113		rule = SignapkRE
114		args["implicits"] = strings.Join(deps.Strings(), ",")
115		args["outCommaList"] = strings.Join(outputFiles.Strings(), ",")
116	}
117	ctx.Build(pctx, android.BuildParams{
118		Rule:        rule,
119		Description: "signapk",
120		Outputs:     outputFiles,
121		Input:       unsignedApk,
122		Implicits:   deps,
123		Args:        args,
124	})
125}
126
127var buildAAR = pctx.AndroidStaticRule("buildAAR",
128	blueprint.RuleParams{
129		Command: `rm -rf ${outDir} && mkdir -p ${outDir} && ` +
130			`cp ${manifest} ${outDir}/AndroidManifest.xml && ` +
131			`cp ${classesJar} ${outDir}/classes.jar && ` +
132			`cp ${rTxt} ${outDir}/R.txt && ` +
133			`${config.SoongZipCmd} -jar -o $out -C ${outDir} -D ${outDir}`,
134		CommandDeps: []string{"${config.SoongZipCmd}"},
135	},
136	"manifest", "classesJar", "rTxt", "outDir")
137
138func BuildAAR(ctx android.ModuleContext, outputFile android.WritablePath,
139	classesJar, manifest, rTxt android.Path, res android.Paths) {
140
141	// TODO(ccross): uniquify and copy resources with dependencies
142
143	deps := android.Paths{manifest, rTxt}
144	classesJarPath := ""
145	if classesJar != nil {
146		deps = append(deps, classesJar)
147		classesJarPath = classesJar.String()
148	}
149
150	ctx.Build(pctx, android.BuildParams{
151		Rule:        buildAAR,
152		Description: "aar",
153		Implicits:   deps,
154		Output:      outputFile,
155		Args: map[string]string{
156			"manifest":   manifest.String(),
157			"classesJar": classesJarPath,
158			"rTxt":       rTxt.String(),
159			"outDir":     android.PathForModuleOut(ctx, "aar").String(),
160		},
161	})
162}
163
164var buildBundleModule = pctx.AndroidStaticRule("buildBundleModule",
165	blueprint.RuleParams{
166		Command:     `${config.MergeZipsCmd} ${out} ${in}`,
167		CommandDeps: []string{"${config.MergeZipsCmd}"},
168	})
169
170var bundleMungePackage = pctx.AndroidStaticRule("bundleMungePackage",
171	blueprint.RuleParams{
172		Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} AndroidManifest.xml:manifest/AndroidManifest.xml resources.pb "res/**/*" "assets/**/*"`,
173		CommandDeps: []string{"${config.Zip2ZipCmd}"},
174	})
175
176var bundleMungeDexJar = pctx.AndroidStaticRule("bundleMungeDexJar",
177	blueprint.RuleParams{
178		Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} "classes*.dex:dex/" && ` +
179			`${config.Zip2ZipCmd} -i ${in} -o ${resJar} -x "classes*.dex" "**/*:root/"`,
180		CommandDeps: []string{"${config.Zip2ZipCmd}"},
181	}, "resJar")
182
183// Builds an app into a module suitable for input to bundletool
184func BuildBundleModule(ctx android.ModuleContext, outputFile android.WritablePath,
185	packageFile, jniJarFile, dexJarFile android.Path) {
186
187	protoResJarFile := android.PathForModuleOut(ctx, "package-res.pb.apk")
188	aapt2Convert(ctx, protoResJarFile, packageFile, "proto")
189
190	var zips android.Paths
191
192	mungedPackage := android.PathForModuleOut(ctx, "bundle", "apk.zip")
193	ctx.Build(pctx, android.BuildParams{
194		Rule:        bundleMungePackage,
195		Input:       protoResJarFile,
196		Output:      mungedPackage,
197		Description: "bundle apk",
198	})
199	zips = append(zips, mungedPackage)
200
201	if dexJarFile != nil {
202		mungedDexJar := android.PathForModuleOut(ctx, "bundle", "dex.zip")
203		mungedResJar := android.PathForModuleOut(ctx, "bundle", "res.zip")
204		ctx.Build(pctx, android.BuildParams{
205			Rule:           bundleMungeDexJar,
206			Input:          dexJarFile,
207			Output:         mungedDexJar,
208			ImplicitOutput: mungedResJar,
209			Description:    "bundle dex",
210			Args: map[string]string{
211				"resJar": mungedResJar.String(),
212			},
213		})
214		zips = append(zips, mungedDexJar, mungedResJar)
215	}
216	if jniJarFile != nil {
217		zips = append(zips, jniJarFile)
218	}
219
220	ctx.Build(pctx, android.BuildParams{
221		Rule:        buildBundleModule,
222		Inputs:      zips,
223		Output:      outputFile,
224		Description: "bundle",
225	})
226}
227
228const jniJarOutputPathString = "jniJarOutput.zip"
229
230func TransformJniLibsToJar(
231	ctx android.ModuleContext,
232	outputFile android.WritablePath,
233	jniLibs []jniLib,
234	prebuiltJniPackages android.Paths,
235	uncompressJNI bool) {
236
237	var deps android.Paths
238	jarArgs := []string{
239		"-j", // junk paths, they will be added back with -P arguments
240	}
241
242	if uncompressJNI {
243		jarArgs = append(jarArgs, "-L", "0")
244	}
245
246	for _, j := range jniLibs {
247		deps = append(deps, j.path)
248		jarArgs = append(jarArgs,
249			"-P", targetToJniDir(j.target),
250			"-f", j.path.String())
251	}
252
253	rule := zip
254	args := map[string]string{
255		"jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "),
256	}
257	if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ZIP") {
258		rule = zipRE
259		args["implicits"] = strings.Join(deps.Strings(), ",")
260	}
261	jniJarPath := android.PathForModuleOut(ctx, jniJarOutputPathString)
262	ctx.Build(pctx, android.BuildParams{
263		Rule:        rule,
264		Description: "zip jni libs",
265		Output:      jniJarPath,
266		Implicits:   deps,
267		Args:        args,
268	})
269	ctx.Build(pctx, android.BuildParams{
270		Rule:        mergeAssetsRule,
271		Description: "merge prebuilt JNI packages",
272		Inputs:      append(prebuiltJniPackages, jniJarPath),
273		Output:      outputFile,
274	})
275}
276
277func (a *AndroidApp) generateJavaUsedByApex(ctx android.ModuleContext) {
278	javaApiUsedByOutputFile := android.PathForModuleOut(ctx, a.installApkName+"_using.xml")
279	javaUsedByRule := android.NewRuleBuilder(pctx, ctx)
280	javaUsedByRule.Command().
281		Tool(android.PathForSource(ctx, "build/soong/scripts/gen_java_usedby_apex.sh")).
282		BuiltTool("dexdeps").
283		Output(javaApiUsedByOutputFile).
284		Input(a.Library.Module.outputFile)
285	javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex")
286	a.javaApiUsedByOutputFile = javaApiUsedByOutputFile
287}
288
289func targetToJniDir(target android.Target) string {
290	return filepath.Join("lib", target.Arch.Abi[0])
291}
292