aar.go 28 KB

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