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 15package java 16 17import ( 18 "fmt" 19 "path/filepath" 20 "strings" 21 22 "android/soong/android" 23 24 "github.com/google/blueprint" 25 "github.com/google/blueprint/proptools" 26) 27 28type AndroidLibraryDependency interface { 29 Dependency 30 ExportPackage() android.Path 31 ExportedProguardFlagFiles() android.Paths 32 ExportedRRODirs() []rroDir 33 ExportedStaticPackages() android.Paths 34 ExportedManifests() android.Paths 35 ExportedAssets() android.OptionalPath 36} 37 38func init() { 39 RegisterAARBuildComponents(android.InitRegistrationContext) 40} 41 42func RegisterAARBuildComponents(ctx android.RegistrationContext) { 43 ctx.RegisterModuleType("android_library_import", AARImportFactory) 44 ctx.RegisterModuleType("android_library", AndroidLibraryFactory) 45} 46 47// 48// AAR (android library) 49// 50 51type androidLibraryProperties struct { 52 BuildAAR bool `blueprint:"mutated"` 53} 54 55type aaptProperties struct { 56 // flags passed to aapt when creating the apk 57 Aaptflags []string 58 59 // include all resource configurations, not just the product-configured 60 // ones. 61 Aapt_include_all_resources *bool 62 63 // list of directories relative to the Blueprints file containing assets. 64 // Defaults to ["assets"] if a directory called assets exists. Set to [] 65 // to disable the default. 66 Asset_dirs []string 67 68 // list of directories relative to the Blueprints file containing 69 // Android resources. Defaults to ["res"] if a directory called res exists. 70 // Set to [] to disable the default. 71 Resource_dirs []string 72 73 // list of zip files containing Android resources. 74 Resource_zips []string `android:"path"` 75 76 // path to AndroidManifest.xml. If unset, defaults to "AndroidManifest.xml". 77 Manifest *string `android:"path"` 78 79 // paths to additional manifest files to merge with main manifest. 80 Additional_manifests []string `android:"path"` 81 82 // do not include AndroidManifest from dependent libraries 83 Dont_merge_manifests *bool 84} 85 86type aapt struct { 87 aaptSrcJar android.Path 88 exportPackage android.Path 89 manifestPath android.Path 90 transitiveManifestPaths android.Paths 91 proguardOptionsFile android.Path 92 rroDirs []rroDir 93 rTxt android.Path 94 extraAaptPackagesFile android.Path 95 mergedManifestFile android.Path 96 noticeFile android.OptionalPath 97 assetPackage android.OptionalPath 98 isLibrary bool 99 useEmbeddedNativeLibs bool 100 useEmbeddedDex bool 101 usesNonSdkApis bool 102 sdkLibraries []string 103 hasNoCode bool 104 LoggingParent string 105 resourceFiles android.Paths 106 107 splitNames []string 108 splits []split 109 110 aaptProperties aaptProperties 111} 112 113type split struct { 114 name string 115 suffix string 116 path android.Path 117} 118 119func (a *aapt) ExportPackage() android.Path { 120 return a.exportPackage 121} 122 123func (a *aapt) ExportedRRODirs() []rroDir { 124 return a.rroDirs 125} 126 127func (a *aapt) ExportedManifests() android.Paths { 128 return a.transitiveManifestPaths 129} 130 131func (a *aapt) ExportedAssets() android.OptionalPath { 132 return a.assetPackage 133} 134 135func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, 136 manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths, 137 resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) { 138 139 hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code") 140 hasVersionName := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-name") 141 142 // Flags specified in Android.bp 143 linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...) 144 145 linkFlags = append(linkFlags, "--no-static-lib-packages") 146 147 // Find implicit or explicit asset and resource dirs 148 assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets") 149 resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") 150 resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips) 151 152 // Glob directories into lists of paths 153 for _, dir := range resourceDirs { 154 resDirs = append(resDirs, globbedResourceDir{ 155 dir: dir, 156 files: androidResourceGlob(ctx, dir), 157 }) 158 resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir) 159 overlayDirs = append(overlayDirs, resOverlayDirs...) 160 rroDirs = append(rroDirs, resRRODirs...) 161 } 162 163 var assetFiles android.Paths 164 for _, dir := range assetDirs { 165 assetFiles = append(assetFiles, androidResourceGlob(ctx, dir)...) 166 } 167 168 assetDirStrings := assetDirs.Strings() 169 if a.noticeFile.Valid() { 170 assetDirStrings = append(assetDirStrings, filepath.Dir(a.noticeFile.Path().String())) 171 assetFiles = append(assetFiles, a.noticeFile.Path()) 172 } 173 174 linkFlags = append(linkFlags, "--manifest "+manifestPath.String()) 175 linkDeps = append(linkDeps, manifestPath) 176 177 linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirStrings, "-A ")) 178 linkDeps = append(linkDeps, assetFiles...) 179 180 // SDK version flags 181 minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersionString(ctx) 182 if err != nil { 183 ctx.ModuleErrorf("invalid minSdkVersion: %s", err) 184 } 185 186 linkFlags = append(linkFlags, "--min-sdk-version "+minSdkVersion) 187 linkFlags = append(linkFlags, "--target-sdk-version "+minSdkVersion) 188 189 // Version code 190 if !hasVersionCode { 191 linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion()) 192 } 193 194 if !hasVersionName { 195 var versionName string 196 if ctx.ModuleName() == "framework-res" { 197 // Some builds set AppsDefaultVersionName() to include the build number ("O-123456"). aapt2 copies the 198 // version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things 199 // if it contains the build number. Use the PlatformVersionName instead. 200 versionName = ctx.Config().PlatformVersionName() 201 } else { 202 versionName = ctx.Config().AppsDefaultVersionName() 203 } 204 versionName = proptools.NinjaEscape(versionName) 205 linkFlags = append(linkFlags, "--version-name ", versionName) 206 } 207 208 linkFlags, compileFlags = android.FilterList(linkFlags, []string{"--legacy"}) 209 210 // Always set --pseudo-localize, it will be stripped out later for release 211 // builds that don't want it. 212 compileFlags = append(compileFlags, "--pseudo-localize") 213 214 return compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resourceZips 215} 216 217func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkDep sdkDep) { 218 if sdkDep.frameworkResModule != "" { 219 ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule) 220 } 221} 222 223var extractAssetsRule = pctx.AndroidStaticRule("extractAssets", 224 blueprint.RuleParams{ 225 Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} "assets/**/*"`, 226 CommandDeps: []string{"${config.Zip2ZipCmd}"}, 227 }) 228 229func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) { 230 231 transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags, sdkLibraries := 232 aaptLibs(ctx, sdkContext) 233 234 // App manifest file 235 manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml") 236 manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile) 237 238 manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, sdkLibraries, 239 a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode, 240 a.LoggingParent) 241 242 // Add additional manifest files to transitive manifests. 243 additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests) 244 a.transitiveManifestPaths = append(android.Paths{manifestPath}, additionalManifests...) 245 a.transitiveManifestPaths = append(a.transitiveManifestPaths, transitiveStaticLibManifests...) 246 247 if len(a.transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) { 248 a.mergedManifestFile = manifestMerger(ctx, a.transitiveManifestPaths[0], a.transitiveManifestPaths[1:], a.isLibrary) 249 if !a.isLibrary { 250 // Only use the merged manifest for applications. For libraries, the transitive closure of manifests 251 // will be propagated to the final application and merged there. The merged manifest for libraries is 252 // only passed to Make, which can't handle transitive dependencies. 253 manifestPath = a.mergedManifestFile 254 } 255 } else { 256 a.mergedManifestFile = manifestPath 257 } 258 259 compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath) 260 261 rroDirs = append(rroDirs, staticRRODirs...) 262 linkFlags = append(linkFlags, libFlags...) 263 linkDeps = append(linkDeps, libDeps...) 264 linkFlags = append(linkFlags, extraLinkFlags...) 265 if a.isLibrary { 266 linkFlags = append(linkFlags, "--static-lib") 267 } 268 269 packageRes := android.PathForModuleOut(ctx, "package-res.apk") 270 // the subdir "android" is required to be filtered by package names 271 srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar") 272 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options") 273 rTxt := android.PathForModuleOut(ctx, "R.txt") 274 // This file isn't used by Soong, but is generated for exporting 275 extraPackages := android.PathForModuleOut(ctx, "extra_packages") 276 277 var compiledResDirs []android.Paths 278 for _, dir := range resDirs { 279 a.resourceFiles = append(a.resourceFiles, dir.files...) 280 compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()) 281 } 282 283 for i, zip := range resZips { 284 flata := android.PathForModuleOut(ctx, fmt.Sprintf("reszip.%d.flata", i)) 285 aapt2CompileZip(ctx, flata, zip, "", compileFlags) 286 compiledResDirs = append(compiledResDirs, android.Paths{flata}) 287 } 288 289 var compiledRes, compiledOverlay android.Paths 290 291 compiledOverlay = append(compiledOverlay, transitiveStaticLibs...) 292 293 if len(transitiveStaticLibs) > 0 { 294 // If we are using static android libraries, every source file becomes an overlay. 295 // This is to emulate old AAPT behavior which simulated library support. 296 for _, compiledResDir := range compiledResDirs { 297 compiledOverlay = append(compiledOverlay, compiledResDir...) 298 } 299 } else if a.isLibrary { 300 // Otherwise, for a static library we treat all the resources equally with no overlay. 301 for _, compiledResDir := range compiledResDirs { 302 compiledRes = append(compiledRes, compiledResDir...) 303 } 304 } else if len(compiledResDirs) > 0 { 305 // Without static libraries, the first directory is our directory, which can then be 306 // overlaid by the rest. 307 compiledRes = append(compiledRes, compiledResDirs[0]...) 308 for _, compiledResDir := range compiledResDirs[1:] { 309 compiledOverlay = append(compiledOverlay, compiledResDir...) 310 } 311 } 312 313 for _, dir := range overlayDirs { 314 compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()...) 315 } 316 317 var splitPackages android.WritablePaths 318 var splits []split 319 320 for _, s := range a.splitNames { 321 suffix := strings.Replace(s, ",", "_", -1) 322 path := android.PathForModuleOut(ctx, "package_"+suffix+".apk") 323 linkFlags = append(linkFlags, "--split", path.String()+":"+s) 324 splitPackages = append(splitPackages, path) 325 splits = append(splits, split{ 326 name: s, 327 suffix: suffix, 328 path: path, 329 }) 330 } 331 332 aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages, 333 linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages) 334 335 // Extract assets from the resource package output so that they can be used later in aapt2link 336 // for modules that depend on this one. 337 if android.PrefixInList(linkFlags, "-A ") || len(assetPackages) > 0 { 338 assets := android.PathForModuleOut(ctx, "assets.zip") 339 ctx.Build(pctx, android.BuildParams{ 340 Rule: extractAssetsRule, 341 Input: packageRes, 342 Output: assets, 343 Description: "extract assets from built resource file", 344 }) 345 a.assetPackage = android.OptionalPathForPath(assets) 346 } 347 348 a.aaptSrcJar = srcJar 349 a.exportPackage = packageRes 350 a.manifestPath = manifestPath 351 a.proguardOptionsFile = proguardOptionsFile 352 a.rroDirs = rroDirs 353 a.extraAaptPackagesFile = extraPackages 354 a.rTxt = rTxt 355 a.splits = splits 356} 357 358// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths 359func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths, 360 staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries []string) { 361 362 var sharedLibs android.Paths 363 364 sdkDep := decodeSdkDep(ctx, sdkContext) 365 if sdkDep.useFiles { 366 sharedLibs = append(sharedLibs, sdkDep.jars...) 367 } 368 369 ctx.VisitDirectDeps(func(module android.Module) { 370 var exportPackage android.Path 371 aarDep, _ := module.(AndroidLibraryDependency) 372 if aarDep != nil { 373 exportPackage = aarDep.ExportPackage() 374 } 375 376 switch ctx.OtherModuleDependencyTag(module) { 377 case instrumentationForTag: 378 // Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2. 379 case libTag: 380 if exportPackage != nil { 381 sharedLibs = append(sharedLibs, exportPackage) 382 } 383 384 // If the module is (or possibly could be) a component of a java_sdk_library 385 // (including the java_sdk_library) itself then append any implicit sdk library 386 // names to the list of sdk libraries to be added to the manifest. 387 if component, ok := module.(SdkLibraryComponentDependency); ok { 388 sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...) 389 } 390 391 case frameworkResTag: 392 if exportPackage != nil { 393 sharedLibs = append(sharedLibs, exportPackage) 394 } 395 case staticLibTag: 396 if exportPackage != nil { 397 transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...) 398 transitiveStaticLibs = append(transitiveStaticLibs, exportPackage) 399 transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...) 400 sdkLibraries = append(sdkLibraries, aarDep.ExportedSdkLibs()...) 401 if aarDep.ExportedAssets().Valid() { 402 assets = append(assets, aarDep.ExportedAssets().Path()) 403 } 404 405 outer: 406 for _, d := range aarDep.ExportedRRODirs() { 407 for _, e := range staticRRODirs { 408 if d.path == e.path { 409 continue outer 410 } 411 } 412 staticRRODirs = append(staticRRODirs, d) 413 } 414 } 415 } 416 }) 417 418 deps = append(deps, sharedLibs...) 419 deps = append(deps, transitiveStaticLibs...) 420 421 if len(transitiveStaticLibs) > 0 { 422 flags = append(flags, "--auto-add-overlay") 423 } 424 425 for _, sharedLib := range sharedLibs { 426 flags = append(flags, "-I "+sharedLib.String()) 427 } 428 429 transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs) 430 transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests) 431 sdkLibraries = android.FirstUniqueStrings(sdkLibraries) 432 433 return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags, sdkLibraries 434} 435 436type AndroidLibrary struct { 437 Library 438 aapt 439 440 androidLibraryProperties androidLibraryProperties 441 442 aarFile android.WritablePath 443 444 exportedProguardFlagFiles android.Paths 445 exportedStaticPackages android.Paths 446} 447 448func (a *AndroidLibrary) ExportedProguardFlagFiles() android.Paths { 449 return a.exportedProguardFlagFiles 450} 451 452func (a *AndroidLibrary) ExportedStaticPackages() android.Paths { 453 return a.exportedStaticPackages 454} 455 456var _ AndroidLibraryDependency = (*AndroidLibrary)(nil) 457 458func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { 459 a.Module.deps(ctx) 460 sdkDep := decodeSdkDep(ctx, sdkContext(a)) 461 if sdkDep.hasFrameworkLibs() { 462 a.aapt.deps(ctx, sdkDep) 463 } 464} 465 466func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 467 a.aapt.isLibrary = true 468 a.aapt.sdkLibraries = a.exportedSdkLibs 469 a.aapt.buildActions(ctx, sdkContext(a)) 470 471 ctx.CheckbuildFile(a.proguardOptionsFile) 472 ctx.CheckbuildFile(a.exportPackage) 473 ctx.CheckbuildFile(a.aaptSrcJar) 474 475 // apps manifests are handled by aapt, don't let Module see them 476 a.properties.Manifest = nil 477 478 a.linter.mergedManifest = a.aapt.mergedManifestFile 479 a.linter.manifest = a.aapt.manifestPath 480 a.linter.resources = a.aapt.resourceFiles 481 482 a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, 483 a.proguardOptionsFile) 484 485 a.Module.compile(ctx, a.aaptSrcJar) 486 487 a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar") 488 var res android.Paths 489 if a.androidLibraryProperties.BuildAAR { 490 BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res) 491 ctx.CheckbuildFile(a.aarFile) 492 } 493 494 ctx.VisitDirectDeps(func(m android.Module) { 495 if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag { 496 a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...) 497 a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportPackage()) 498 a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportedStaticPackages()...) 499 } 500 }) 501 502 a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles) 503 a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages) 504} 505 506// android_library builds and links sources into a `.jar` file for the device along with Android resources. 507// 508// An android_library has a single variant that produces a `.jar` file containing `.class` files that were 509// compiled against the device bootclasspath, along with a `package-res.apk` file containing Android resources compiled 510// with aapt2. This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of 511// an android_app module. 512func AndroidLibraryFactory() android.Module { 513 module := &AndroidLibrary{} 514 515 module.Module.addHostAndDeviceProperties() 516 module.AddProperties( 517 &module.aaptProperties, 518 &module.androidLibraryProperties) 519 520 module.androidLibraryProperties.BuildAAR = true 521 module.Module.linter.library = true 522 523 android.InitApexModule(module) 524 InitJavaModule(module, android.DeviceSupported) 525 return module 526} 527 528// 529// AAR (android library) prebuilts 530// 531 532type AARImportProperties struct { 533 Aars []string `android:"path"` 534 535 Sdk_version *string 536 Min_sdk_version *string 537 538 Static_libs []string 539 Libs []string 540 541 // if set to true, run Jetifier against .aar file. Defaults to false. 542 Jetifier *bool 543} 544 545type AARImport struct { 546 android.ModuleBase 547 android.DefaultableModuleBase 548 android.ApexModuleBase 549 prebuilt android.Prebuilt 550 551 // Functionality common to Module and Import. 552 embeddableInModuleAndImport 553 554 properties AARImportProperties 555 556 classpathFile android.WritablePath 557 proguardFlags android.WritablePath 558 exportPackage android.WritablePath 559 extraAaptPackagesFile android.WritablePath 560 manifest android.WritablePath 561 562 exportedStaticPackages android.Paths 563} 564 565func (a *AARImport) sdkVersion() sdkSpec { 566 return sdkSpecFrom(String(a.properties.Sdk_version)) 567} 568 569func (a *AARImport) systemModules() string { 570 return "" 571} 572 573func (a *AARImport) minSdkVersion() sdkSpec { 574 if a.properties.Min_sdk_version != nil { 575 return sdkSpecFrom(*a.properties.Min_sdk_version) 576 } 577 return a.sdkVersion() 578} 579 580func (a *AARImport) targetSdkVersion() sdkSpec { 581 return a.sdkVersion() 582} 583 584func (a *AARImport) javaVersion() string { 585 return "" 586} 587 588var _ AndroidLibraryDependency = (*AARImport)(nil) 589 590func (a *AARImport) ExportPackage() android.Path { 591 return a.exportPackage 592} 593 594func (a *AARImport) ExportedProguardFlagFiles() android.Paths { 595 return android.Paths{a.proguardFlags} 596} 597 598func (a *AARImport) ExportedRRODirs() []rroDir { 599 return nil 600} 601 602func (a *AARImport) ExportedStaticPackages() android.Paths { 603 return a.exportedStaticPackages 604} 605 606func (a *AARImport) ExportedManifests() android.Paths { 607 return android.Paths{a.manifest} 608} 609 610// TODO(jungjw): Decide whether we want to implement this. 611func (a *AARImport) ExportedAssets() android.OptionalPath { 612 return android.OptionalPath{} 613} 614 615func (a *AARImport) Prebuilt() *android.Prebuilt { 616 return &a.prebuilt 617} 618 619func (a *AARImport) Name() string { 620 return a.prebuilt.Name(a.ModuleBase.Name()) 621} 622 623func (a *AARImport) JacocoReportClassesFile() android.Path { 624 return nil 625} 626 627func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) { 628 if !ctx.Config().UnbundledBuildUsePrebuiltSdks() { 629 sdkDep := decodeSdkDep(ctx, sdkContext(a)) 630 if sdkDep.useModule && sdkDep.frameworkResModule != "" { 631 ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule) 632 } 633 } 634 635 ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...) 636 ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...) 637} 638 639// Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be 640// touched to create an empty file. The res directory is not extracted, as it will be extracted in its own rule. 641var unzipAAR = pctx.AndroidStaticRule("unzipAAR", 642 blueprint.RuleParams{ 643 Command: `rm -rf $outDir && mkdir -p $outDir && ` + 644 `unzip -qoDD -d $outDir $in && rm -rf $outDir/res && touch $out`, 645 }, 646 "outDir") 647 648func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { 649 if len(a.properties.Aars) != 1 { 650 ctx.PropertyErrorf("aars", "exactly one aar is required") 651 return 652 } 653 654 aarName := ctx.ModuleName() + ".aar" 655 var aar android.Path 656 aar = android.PathForModuleSrc(ctx, a.properties.Aars[0]) 657 if Bool(a.properties.Jetifier) { 658 inputFile := aar 659 aar = android.PathForModuleOut(ctx, "jetifier", aarName) 660 TransformJetifier(ctx, aar.(android.WritablePath), inputFile) 661 } 662 663 extractedAARDir := android.PathForModuleOut(ctx, "aar") 664 a.classpathFile = extractedAARDir.Join(ctx, "classes.jar") 665 a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt") 666 a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml") 667 668 ctx.Build(pctx, android.BuildParams{ 669 Rule: unzipAAR, 670 Input: aar, 671 Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest}, 672 Description: "unzip AAR", 673 Args: map[string]string{ 674 "outDir": extractedAARDir.String(), 675 }, 676 }) 677 678 // Always set --pseudo-localize, it will be stripped out later for release 679 // builds that don't want it. 680 compileFlags := []string{"--pseudo-localize"} 681 compiledResDir := android.PathForModuleOut(ctx, "flat-res") 682 flata := compiledResDir.Join(ctx, "gen_res.flata") 683 aapt2CompileZip(ctx, flata, aar, "res", compileFlags) 684 685 a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk") 686 // the subdir "android" is required to be filtered by package names 687 srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar") 688 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options") 689 rTxt := android.PathForModuleOut(ctx, "R.txt") 690 a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages") 691 692 var linkDeps android.Paths 693 694 linkFlags := []string{ 695 "--static-lib", 696 "--no-static-lib-packages", 697 "--auto-add-overlay", 698 } 699 700 linkFlags = append(linkFlags, "--manifest "+a.manifest.String()) 701 linkDeps = append(linkDeps, a.manifest) 702 703 transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags, sdkLibraries := 704 aaptLibs(ctx, sdkContext(a)) 705 706 _ = staticLibManifests 707 _ = staticRRODirs 708 _ = sdkLibraries 709 710 linkDeps = append(linkDeps, libDeps...) 711 linkFlags = append(linkFlags, libFlags...) 712 713 overlayRes := append(android.Paths{flata}, transitiveStaticLibs...) 714 715 aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile, 716 linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil) 717} 718 719var _ Dependency = (*AARImport)(nil) 720 721func (a *AARImport) HeaderJars() android.Paths { 722 return android.Paths{a.classpathFile} 723} 724 725func (a *AARImport) ImplementationJars() android.Paths { 726 return android.Paths{a.classpathFile} 727} 728 729func (a *AARImport) ResourceJars() android.Paths { 730 return nil 731} 732 733func (a *AARImport) ImplementationAndResourcesJars() android.Paths { 734 return android.Paths{a.classpathFile} 735} 736 737func (a *AARImport) DexJarBuildPath() android.Path { 738 return nil 739} 740 741func (a *AARImport) DexJarInstallPath() android.Path { 742 return nil 743} 744 745func (a *AARImport) AidlIncludeDirs() android.Paths { 746 return nil 747} 748 749func (a *AARImport) ExportedSdkLibs() []string { 750 return nil 751} 752 753func (d *AARImport) ExportedPlugins() (android.Paths, []string) { 754 return nil, nil 755} 756 757func (a *AARImport) SrcJarArgs() ([]string, android.Paths) { 758 return nil, nil 759} 760 761func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { 762 return a.depIsInSameApex(ctx, dep) 763} 764 765func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error { 766 return nil 767} 768 769var _ android.PrebuiltInterface = (*Import)(nil) 770 771// android_library_import imports an `.aar` file into the build graph as if it was built with android_library. 772// 773// This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of 774// an android_app module. 775func AARImportFactory() android.Module { 776 module := &AARImport{} 777 778 module.AddProperties(&module.properties) 779 780 android.InitPrebuiltModule(module, &module.properties.Aars) 781 android.InitApexModule(module) 782 InitJavaModule(module, android.DeviceSupported) 783 return module 784} 785