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