| Colin Cross | fabb608 | 2018-02-20 17:22:23 -0800 | [diff] [blame] | 1 | // Copyright 2018 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 |  | 
|  | 15 | package java | 
|  | 16 |  | 
|  | 17 | import ( | 
|  | 18 | "android/soong/android" | 
|  | 19 |  | 
|  | 20 | "github.com/google/blueprint" | 
|  | 21 | ) | 
|  | 22 |  | 
|  | 23 | // | 
|  | 24 | // AAR (android library) prebuilts | 
|  | 25 | // | 
|  | 26 | func init() { | 
|  | 27 | android.RegisterModuleType("android_library_import", AARImportFactory) | 
|  | 28 | } | 
|  | 29 |  | 
|  | 30 | type AARImportProperties struct { | 
|  | 31 | Aars []string | 
|  | 32 |  | 
|  | 33 | Sdk_version *string | 
|  | 34 | } | 
|  | 35 |  | 
|  | 36 | type AARImport struct { | 
|  | 37 | android.ModuleBase | 
|  | 38 | prebuilt android.Prebuilt | 
|  | 39 |  | 
|  | 40 | properties AARImportProperties | 
|  | 41 |  | 
|  | 42 | classpathFile android.WritablePath | 
|  | 43 | proguardFlags android.WritablePath | 
|  | 44 | exportPackage android.WritablePath | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | func (a *AARImport) Prebuilt() *android.Prebuilt { | 
|  | 48 | return &a.prebuilt | 
|  | 49 | } | 
|  | 50 |  | 
|  | 51 | func (a *AARImport) Name() string { | 
|  | 52 | return a.prebuilt.Name(a.ModuleBase.Name()) | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 | func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) { | 
|  | 56 | // TODO: this should use decodeSdkDep once that knows about current | 
|  | 57 | if !ctx.Config().UnbundledBuild() { | 
|  | 58 | switch String(a.properties.Sdk_version) { // TODO: Res_sdk_version? | 
|  | 59 | case "current", "system_current", "test_current", "": | 
|  | 60 | ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res") | 
|  | 61 | } | 
|  | 62 | } | 
|  | 63 | } | 
|  | 64 |  | 
|  | 65 | // Unzip an AAR into its constituent files and directories.  Any files in Outputs that don't exist in the AAR will be | 
|  | 66 | // touched to create an empty file, and any directories in $expectedDirs will be created. | 
|  | 67 | var unzipAAR = pctx.AndroidStaticRule("unzipAAR", | 
|  | 68 | blueprint.RuleParams{ | 
|  | 69 | Command: `rm -rf $outDir && mkdir -p $outDir $expectedDirs && ` + | 
|  | 70 | `unzip -qo -d $outDir $in && touch $out`, | 
|  | 71 | }, | 
|  | 72 | "expectedDirs", "outDir") | 
|  | 73 |  | 
|  | 74 | func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { | 
|  | 75 | if len(a.properties.Aars) != 1 { | 
|  | 76 | ctx.PropertyErrorf("aars", "exactly one aar is required") | 
|  | 77 | return | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | aar := android.PathForModuleSrc(ctx, a.properties.Aars[0]) | 
|  | 81 |  | 
|  | 82 | extractedAARDir := android.PathForModuleOut(ctx, "aar") | 
|  | 83 | extractedResDir := extractedAARDir.Join(ctx, "res") | 
|  | 84 | a.classpathFile = extractedAARDir.Join(ctx, "classes.jar") | 
|  | 85 | a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt") | 
|  | 86 | manifest := extractedAARDir.Join(ctx, "AndroidManifest.xml") | 
|  | 87 |  | 
|  | 88 | ctx.Build(pctx, android.BuildParams{ | 
|  | 89 | Rule:        unzipAAR, | 
|  | 90 | Input:       aar, | 
|  | 91 | Outputs:     android.WritablePaths{a.classpathFile, a.proguardFlags, manifest}, | 
|  | 92 | Description: "unzip AAR", | 
|  | 93 | Args: map[string]string{ | 
|  | 94 | "expectedDirs": extractedResDir.String(), | 
|  | 95 | "outDir":       extractedAARDir.String(), | 
|  | 96 | }, | 
|  | 97 | }) | 
|  | 98 |  | 
|  | 99 | compiledResDir := android.PathForModuleOut(ctx, "flat-res") | 
|  | 100 | aaptCompileDeps := android.Paths{a.classpathFile} | 
|  | 101 | aaptCompileDirs := android.Paths{extractedResDir} | 
|  | 102 | flata := compiledResDir.Join(ctx, "gen_res.flata") | 
|  | 103 | aapt2CompileDirs(ctx, flata, aaptCompileDirs, aaptCompileDeps) | 
|  | 104 |  | 
|  | 105 | a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk") | 
|  | 106 | srcJar := android.PathForModuleGen(ctx, "R.jar") | 
|  | 107 | proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options") | 
|  | 108 |  | 
|  | 109 | var linkDeps android.Paths | 
|  | 110 |  | 
|  | 111 | linkFlags := []string{ | 
|  | 112 | "--static-lib", | 
|  | 113 | "--no-static-lib-packages", | 
|  | 114 | "--auto-add-overlay", | 
|  | 115 | } | 
|  | 116 |  | 
|  | 117 | linkFlags = append(linkFlags, "--manifest "+manifest.String()) | 
|  | 118 | linkDeps = append(linkDeps, manifest) | 
|  | 119 |  | 
|  | 120 | // Include dirs | 
|  | 121 | ctx.VisitDirectDeps(func(module android.Module) { | 
|  | 122 | var depFiles android.Paths | 
|  | 123 | if javaDep, ok := module.(Dependency); ok { | 
|  | 124 | // TODO: shared android libraries | 
|  | 125 | if ctx.OtherModuleName(module) == "framework-res" { | 
|  | 126 | depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage} | 
|  | 127 | } | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | for _, dep := range depFiles { | 
|  | 131 | linkFlags = append(linkFlags, "-I "+dep.String()) | 
|  | 132 | } | 
|  | 133 | linkDeps = append(linkDeps, depFiles...) | 
|  | 134 | }) | 
|  | 135 |  | 
|  | 136 | sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version)) | 
|  | 137 | if sdkDep.useFiles { | 
|  | 138 | linkFlags = append(linkFlags, "-I "+sdkDep.jar.String()) | 
|  | 139 | linkDeps = append(linkDeps, sdkDep.jar) | 
|  | 140 | } | 
|  | 141 |  | 
|  | 142 | aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, | 
|  | 143 | linkFlags, linkDeps, nil, android.Paths{flata}) | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | var _ Dependency = (*AARImport)(nil) | 
|  | 147 |  | 
|  | 148 | func (a *AARImport) HeaderJars() android.Paths { | 
|  | 149 | return android.Paths{a.classpathFile} | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 | func (a *AARImport) ImplementationJars() android.Paths { | 
|  | 153 | return android.Paths{a.classpathFile} | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | func (a *AARImport) AidlIncludeDirs() android.Paths { | 
|  | 157 | return nil | 
|  | 158 | } | 
|  | 159 |  | 
|  | 160 | var _ android.PrebuiltInterface = (*Import)(nil) | 
|  | 161 |  | 
|  | 162 | func AARImportFactory() android.Module { | 
|  | 163 | module := &AARImport{} | 
|  | 164 |  | 
|  | 165 | module.AddProperties(&module.properties) | 
|  | 166 |  | 
|  | 167 | android.InitPrebuiltModule(module, &module.properties.Aars) | 
|  | 168 | android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) | 
|  | 169 | return module | 
|  | 170 | } |