From fabb608b27878dd76b1bbb49eff03467ec4688ac Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 20 Feb 2018 17:22:23 -0800 Subject: [PATCH] Soong AAR prebuilt support Add support for android_library_import modules that take an aar file. Bug: 73724997 Test: m checkbuild Change-Id: I670b56f0a3b7501d9478a6064a04d0cb9c1bb611 --- Android.bp | 1 + java/aapt2.go | 17 +++++ java/aar.go | 170 ++++++++++++++++++++++++++++++++++++++++++++++ java/androidmk.go | 18 +++++ java/app.go | 4 +- 5 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 java/aar.go diff --git a/Android.bp b/Android.bp index f2bc5fb91..1d2c5167f 100644 --- a/Android.bp +++ b/Android.bp @@ -215,6 +215,7 @@ bootstrap_go_package { ], srcs: [ "java/aapt2.go", + "java/aar.go", "java/androidmk.go", "java/app_builder.go", "java/app.go", diff --git a/java/aapt2.go b/java/aapt2.go index 84e3729fe..fd7388e15 100644 --- a/java/aapt2.go +++ b/java/aapt2.go @@ -81,6 +81,8 @@ func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Pat Outputs: outPaths, Args: map[string]string{ "outDir": android.PathForModuleOut(ctx, "aapt2", dir.String()).String(), + // Always set --pseudo-localize, it will be stripped out later for release + // builds that don't want it. "cFlags": "--pseudo-localize", }, }) @@ -92,6 +94,21 @@ func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Pat return ret } +func aapt2CompileDirs(ctx android.ModuleContext, flata android.WritablePath, dirs android.Paths, deps android.Paths) { + ctx.Build(pctx, android.BuildParams{ + Rule: aapt2CompileRule, + Description: "aapt2 compile dirs", + Implicits: deps, + Output: flata, + Args: map[string]string{ + "outDir": flata.String(), + // Always set --pseudo-localize, it will be stripped out later for release + // builds that don't want it. + "cFlags": "--pseudo-localize " + android.JoinWithPrefix(dirs.Strings(), "--dir "), + }, + }) +} + var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link", blueprint.RuleParams{ Command: `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions $inFlags && ` + diff --git a/java/aar.go b/java/aar.go new file mode 100644 index 000000000..0df3632b9 --- /dev/null +++ b/java/aar.go @@ -0,0 +1,170 @@ +// Copyright 2018 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 + +import ( + "android/soong/android" + + "github.com/google/blueprint" +) + +// +// AAR (android library) prebuilts +// +func init() { + android.RegisterModuleType("android_library_import", AARImportFactory) +} + +type AARImportProperties struct { + Aars []string + + Sdk_version *string +} + +type AARImport struct { + android.ModuleBase + prebuilt android.Prebuilt + + properties AARImportProperties + + classpathFile android.WritablePath + proguardFlags android.WritablePath + exportPackage android.WritablePath +} + +func (a *AARImport) Prebuilt() *android.Prebuilt { + return &a.prebuilt +} + +func (a *AARImport) Name() string { + return a.prebuilt.Name(a.ModuleBase.Name()) +} + +func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) { + // TODO: this should use decodeSdkDep once that knows about current + if !ctx.Config().UnbundledBuild() { + switch String(a.properties.Sdk_version) { // TODO: Res_sdk_version? + case "current", "system_current", "test_current", "": + ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res") + } + } +} + +// Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be +// touched to create an empty file, and any directories in $expectedDirs will be created. +var unzipAAR = pctx.AndroidStaticRule("unzipAAR", + blueprint.RuleParams{ + Command: `rm -rf $outDir && mkdir -p $outDir $expectedDirs && ` + + `unzip -qo -d $outDir $in && touch $out`, + }, + "expectedDirs", "outDir") + +func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if len(a.properties.Aars) != 1 { + ctx.PropertyErrorf("aars", "exactly one aar is required") + return + } + + aar := android.PathForModuleSrc(ctx, a.properties.Aars[0]) + + extractedAARDir := android.PathForModuleOut(ctx, "aar") + extractedResDir := extractedAARDir.Join(ctx, "res") + a.classpathFile = extractedAARDir.Join(ctx, "classes.jar") + a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt") + manifest := extractedAARDir.Join(ctx, "AndroidManifest.xml") + + ctx.Build(pctx, android.BuildParams{ + Rule: unzipAAR, + Input: aar, + Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, manifest}, + Description: "unzip AAR", + Args: map[string]string{ + "expectedDirs": extractedResDir.String(), + "outDir": extractedAARDir.String(), + }, + }) + + compiledResDir := android.PathForModuleOut(ctx, "flat-res") + aaptCompileDeps := android.Paths{a.classpathFile} + aaptCompileDirs := android.Paths{extractedResDir} + flata := compiledResDir.Join(ctx, "gen_res.flata") + aapt2CompileDirs(ctx, flata, aaptCompileDirs, aaptCompileDeps) + + a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk") + srcJar := android.PathForModuleGen(ctx, "R.jar") + proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options") + + var linkDeps android.Paths + + linkFlags := []string{ + "--static-lib", + "--no-static-lib-packages", + "--auto-add-overlay", + } + + linkFlags = append(linkFlags, "--manifest "+manifest.String()) + linkDeps = append(linkDeps, manifest) + + // Include dirs + ctx.VisitDirectDeps(func(module android.Module) { + var depFiles android.Paths + if javaDep, ok := module.(Dependency); ok { + // TODO: shared android libraries + if ctx.OtherModuleName(module) == "framework-res" { + depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage} + } + } + + for _, dep := range depFiles { + linkFlags = append(linkFlags, "-I "+dep.String()) + } + linkDeps = append(linkDeps, depFiles...) + }) + + sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version)) + if sdkDep.useFiles { + linkFlags = append(linkFlags, "-I "+sdkDep.jar.String()) + linkDeps = append(linkDeps, sdkDep.jar) + } + + aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, + linkFlags, linkDeps, nil, android.Paths{flata}) +} + +var _ Dependency = (*AARImport)(nil) + +func (a *AARImport) HeaderJars() android.Paths { + return android.Paths{a.classpathFile} +} + +func (a *AARImport) ImplementationJars() android.Paths { + return android.Paths{a.classpathFile} +} + +func (a *AARImport) AidlIncludeDirs() android.Paths { + return nil +} + +var _ android.PrebuiltInterface = (*Import)(nil) + +func AARImportFactory() android.Module { + module := &AARImport{} + + module.AddProperties(&module.properties) + + android.InitPrebuiltModule(module, &module.properties.Aars) + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + return module +} diff --git a/java/androidmk.go b/java/androidmk.go index bb1a13c56..3658636f8 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -112,6 +112,24 @@ func (prebuilt *Import) AndroidMk() android.AndroidMkData { } } +func (prebuilt *AARImport) AndroidMk() android.AndroidMkData { + return android.AndroidMkData{ + Class: "JAVA_LIBRARIES", + OutputFile: android.OptionalPathForPath(prebuilt.classpathFile), + Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", + Extra: []android.AndroidMkExtraFunc{ + func(w io.Writer, outputFile android.Path) { + fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true") + fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false") + fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.classpathFile.String()) + fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", prebuilt.exportPackage.String()) + fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=", prebuilt.proguardFlags.String()) + fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", String(prebuilt.properties.Sdk_version)) + }, + }, + } +} + func (binary *Binary) AndroidMk() android.AndroidMkData { if !binary.isWrapperVariant { diff --git a/java/app.go b/java/app.go index dc7f84876..34f05b736 100644 --- a/java/app.go +++ b/java/app.go @@ -34,7 +34,7 @@ func init() { // AndroidManifest.xml merging // package splits -type androidAppProperties struct { +type appProperties struct { // path to a certificate, or the name of a certificate in the default // certificate directory, or blank to use the default product certificate Certificate *string @@ -71,7 +71,7 @@ type androidAppProperties struct { type AndroidApp struct { Module - appProperties androidAppProperties + appProperties appProperties aaptSrcJar android.Path exportPackage android.Path