123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134 |
- // Copyright 2018 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package java
- import (
- "fmt"
- "path/filepath"
- "strconv"
- "strings"
- "android/soong/android"
- "android/soong/bazel"
- "android/soong/dexpreopt"
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
- )
- type AndroidLibraryDependency interface {
- LibraryDependency
- ExportPackage() android.Path
- ExportedRRODirs() []rroDir
- ExportedStaticPackages() android.Paths
- ExportedManifests() android.Paths
- ExportedAssets() android.OptionalPath
- SetRROEnforcedForDependent(enforce bool)
- IsRROEnforced(ctx android.BaseModuleContext) bool
- }
- func init() {
- RegisterAARBuildComponents(android.InitRegistrationContext)
- }
- func RegisterAARBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("android_library_import", AARImportFactory)
- ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
- ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
- })
- }
- //
- // AAR (android library)
- //
- type androidLibraryProperties struct {
- BuildAAR bool `blueprint:"mutated"`
- }
- type aaptProperties struct {
- // flags passed to aapt when creating the apk
- Aaptflags []string
- // include all resource configurations, not just the product-configured
- // ones.
- Aapt_include_all_resources *bool
- // list of directories relative to the Blueprints file containing assets.
- // Defaults to ["assets"] if a directory called assets exists. Set to []
- // to disable the default.
- Asset_dirs []string
- // list of directories relative to the Blueprints file containing
- // Android resources. Defaults to ["res"] if a directory called res exists.
- // Set to [] to disable the default.
- Resource_dirs []string
- // list of zip files containing Android resources.
- Resource_zips []string `android:"path"`
- // path to AndroidManifest.xml. If unset, defaults to "AndroidManifest.xml".
- Manifest *string `android:"path"`
- // paths to additional manifest files to merge with main manifest.
- Additional_manifests []string `android:"path"`
- // do not include AndroidManifest from dependent libraries
- Dont_merge_manifests *bool
- // true if RRO is enforced for any of the dependent modules
- RROEnforcedForDependent bool `blueprint:"mutated"`
- }
- type aapt struct {
- aaptSrcJar android.Path
- exportPackage android.Path
- manifestPath android.Path
- transitiveManifestPaths android.Paths
- proguardOptionsFile android.Path
- rroDirs []rroDir
- rTxt android.Path
- extraAaptPackagesFile android.Path
- mergedManifestFile android.Path
- noticeFile android.OptionalPath
- assetPackage android.OptionalPath
- isLibrary bool
- defaultManifestVersion string
- useEmbeddedNativeLibs bool
- useEmbeddedDex bool
- usesNonSdkApis bool
- hasNoCode bool
- LoggingParent string
- resourceFiles android.Paths
- splitNames []string
- splits []split
- aaptProperties aaptProperties
- }
- type split struct {
- name string
- suffix string
- path android.Path
- }
- // Propagate RRO enforcement flag to static lib dependencies transitively.
- func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
- m := ctx.Module()
- if d, ok := m.(AndroidLibraryDependency); ok && d.IsRROEnforced(ctx) {
- ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
- if a, ok := d.(AndroidLibraryDependency); ok {
- a.SetRROEnforcedForDependent(true)
- }
- })
- }
- }
- func (a *aapt) ExportPackage() android.Path {
- return a.exportPackage
- }
- func (a *aapt) ExportedRRODirs() []rroDir {
- return a.rroDirs
- }
- func (a *aapt) ExportedManifests() android.Paths {
- return a.transitiveManifestPaths
- }
- func (a *aapt) ExportedAssets() android.OptionalPath {
- return a.assetPackage
- }
- func (a *aapt) SetRROEnforcedForDependent(enforce bool) {
- a.aaptProperties.RROEnforcedForDependent = enforce
- }
- func (a *aapt) IsRROEnforced(ctx android.BaseModuleContext) bool {
- // True if RRO is enforced for this module or...
- return ctx.Config().EnforceRROForModule(ctx.ModuleName()) ||
- // if RRO is enforced for any of its dependents.
- a.aaptProperties.RROEnforcedForDependent
- }
- func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkContext,
- manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
- resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
- hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code")
- hasVersionName := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-name")
- // Flags specified in Android.bp
- linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
- linkFlags = append(linkFlags, "--no-static-lib-packages")
- // Find implicit or explicit asset and resource dirs
- assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
- resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
- resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips)
- // Glob directories into lists of paths
- for _, dir := range resourceDirs {
- resDirs = append(resDirs, globbedResourceDir{
- dir: dir,
- files: androidResourceGlob(ctx, dir),
- })
- resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, a, dir)
- overlayDirs = append(overlayDirs, resOverlayDirs...)
- rroDirs = append(rroDirs, resRRODirs...)
- }
- var assetDeps android.Paths
- for i, dir := range assetDirs {
- // Add a dependency on every file in the asset directory. This ensures the aapt2
- // rule will be rerun if one of the files in the asset directory is modified.
- assetDeps = append(assetDeps, androidResourceGlob(ctx, dir)...)
- // Add a dependency on a file that contains a list of all the files in the asset directory.
- // This ensures the aapt2 rule will be run if a file is removed from the asset directory,
- // or a file is added whose timestamp is older than the output of aapt2.
- assetFileListFile := android.PathForModuleOut(ctx, "asset_dir_globs", strconv.Itoa(i)+".glob")
- androidResourceGlobList(ctx, dir, assetFileListFile)
- assetDeps = append(assetDeps, assetFileListFile)
- }
- assetDirStrings := assetDirs.Strings()
- if a.noticeFile.Valid() {
- assetDirStrings = append(assetDirStrings, filepath.Dir(a.noticeFile.Path().String()))
- assetDeps = append(assetDeps, a.noticeFile.Path())
- }
- linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
- linkDeps = append(linkDeps, manifestPath)
- linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirStrings, "-A "))
- linkDeps = append(linkDeps, assetDeps...)
- // Returns the effective version for {min|target}_sdk_version
- effectiveVersionString := func(sdkVersion android.SdkSpec, minSdkVersion android.ApiLevel) string {
- // If {min|target}_sdk_version is current, use sdk_version to determine the effective level
- // This is necessary for vendor modules.
- // The effective version does not _only_ depend on {min|target}_sdk_version(level),
- // but also on the sdk_version (kind+level)
- if minSdkVersion.IsCurrent() {
- ret, err := sdkVersion.EffectiveVersionString(ctx)
- if err != nil {
- ctx.ModuleErrorf("invalid sdk_version: %s", err)
- }
- return ret
- }
- ret, err := minSdkVersion.EffectiveVersionString(ctx)
- if err != nil {
- ctx.ModuleErrorf("invalid min_sdk_version: %s", err)
- }
- return ret
- }
- // SDK version flags
- sdkVersion := sdkContext.SdkVersion(ctx)
- minSdkVersion := effectiveVersionString(sdkVersion, sdkContext.MinSdkVersion(ctx))
- linkFlags = append(linkFlags, "--min-sdk-version "+minSdkVersion)
- // Use minSdkVersion for target-sdk-version, even if `target_sdk_version` is set
- // This behavior has been copied from Make.
- linkFlags = append(linkFlags, "--target-sdk-version "+minSdkVersion)
- // Version code
- if !hasVersionCode {
- linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion().String())
- }
- if !hasVersionName {
- var versionName string
- if ctx.ModuleName() == "framework-res" {
- // Some builds set AppsDefaultVersionName() to include the build number ("O-123456"). aapt2 copies the
- // version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things
- // if it contains the build number. Use the PlatformVersionName instead.
- versionName = ctx.Config().PlatformVersionName()
- } else {
- versionName = ctx.Config().AppsDefaultVersionName()
- }
- versionName = proptools.NinjaEscape(versionName)
- linkFlags = append(linkFlags, "--version-name ", versionName)
- }
- linkFlags, compileFlags = android.FilterList(linkFlags, []string{"--legacy"})
- // Always set --pseudo-localize, it will be stripped out later for release
- // builds that don't want it.
- compileFlags = append(compileFlags, "--pseudo-localize")
- return compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resourceZips
- }
- func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkDep sdkDep) {
- if sdkDep.frameworkResModule != "" {
- ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule)
- }
- }
- var extractAssetsRule = pctx.AndroidStaticRule("extractAssets",
- blueprint.RuleParams{
- Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} "assets/**/*"`,
- CommandDeps: []string{"${config.Zip2ZipCmd}"},
- })
- func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext,
- classLoaderContexts dexpreopt.ClassLoaderContextMap, excludedLibs []string,
- enforceDefaultTargetSdkVersion bool, extraLinkFlags ...string) {
- transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags :=
- aaptLibs(ctx, sdkContext, classLoaderContexts)
- // Exclude any libraries from the supplied list.
- classLoaderContexts = classLoaderContexts.ExcludeLibs(excludedLibs)
- // App manifest file
- manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
- manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
- manifestPath := ManifestFixer(ctx, manifestSrcPath, ManifestFixerParams{
- SdkContext: sdkContext,
- ClassLoaderContexts: classLoaderContexts,
- IsLibrary: a.isLibrary,
- DefaultManifestVersion: a.defaultManifestVersion,
- UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs,
- UsesNonSdkApis: a.usesNonSdkApis,
- UseEmbeddedDex: a.useEmbeddedDex,
- HasNoCode: a.hasNoCode,
- LoggingParent: a.LoggingParent,
- EnforceDefaultTargetSdkVersion: enforceDefaultTargetSdkVersion,
- })
- // Add additional manifest files to transitive manifests.
- additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
- a.transitiveManifestPaths = append(android.Paths{manifestPath}, additionalManifests...)
- a.transitiveManifestPaths = append(a.transitiveManifestPaths, transitiveStaticLibManifests...)
- if len(a.transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
- a.mergedManifestFile = manifestMerger(ctx, a.transitiveManifestPaths[0], a.transitiveManifestPaths[1:], a.isLibrary)
- if !a.isLibrary {
- // Only use the merged manifest for applications. For libraries, the transitive closure of manifests
- // will be propagated to the final application and merged there. The merged manifest for libraries is
- // only passed to Make, which can't handle transitive dependencies.
- manifestPath = a.mergedManifestFile
- }
- } else {
- a.mergedManifestFile = manifestPath
- }
- compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath)
- rroDirs = append(rroDirs, staticRRODirs...)
- linkFlags = append(linkFlags, libFlags...)
- linkDeps = append(linkDeps, libDeps...)
- linkFlags = append(linkFlags, extraLinkFlags...)
- if a.isLibrary {
- linkFlags = append(linkFlags, "--static-lib")
- }
- packageRes := android.PathForModuleOut(ctx, "package-res.apk")
- // the subdir "android" is required to be filtered by package names
- srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar")
- proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
- rTxt := android.PathForModuleOut(ctx, "R.txt")
- // This file isn't used by Soong, but is generated for exporting
- extraPackages := android.PathForModuleOut(ctx, "extra_packages")
- var compiledResDirs []android.Paths
- for _, dir := range resDirs {
- a.resourceFiles = append(a.resourceFiles, dir.files...)
- compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths())
- }
- for i, zip := range resZips {
- flata := android.PathForModuleOut(ctx, fmt.Sprintf("reszip.%d.flata", i))
- aapt2CompileZip(ctx, flata, zip, "", compileFlags)
- compiledResDirs = append(compiledResDirs, android.Paths{flata})
- }
- var compiledRes, compiledOverlay android.Paths
- compiledOverlay = append(compiledOverlay, transitiveStaticLibs...)
- if len(transitiveStaticLibs) > 0 {
- // If we are using static android libraries, every source file becomes an overlay.
- // This is to emulate old AAPT behavior which simulated library support.
- for _, compiledResDir := range compiledResDirs {
- compiledOverlay = append(compiledOverlay, compiledResDir...)
- }
- } else if a.isLibrary {
- // Otherwise, for a static library we treat all the resources equally with no overlay.
- for _, compiledResDir := range compiledResDirs {
- compiledRes = append(compiledRes, compiledResDir...)
- }
- } else if len(compiledResDirs) > 0 {
- // Without static libraries, the first directory is our directory, which can then be
- // overlaid by the rest.
- compiledRes = append(compiledRes, compiledResDirs[0]...)
- for _, compiledResDir := range compiledResDirs[1:] {
- compiledOverlay = append(compiledOverlay, compiledResDir...)
- }
- }
- for _, dir := range overlayDirs {
- compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()...)
- }
- var splitPackages android.WritablePaths
- var splits []split
- for _, s := range a.splitNames {
- suffix := strings.Replace(s, ",", "_", -1)
- path := android.PathForModuleOut(ctx, "package_"+suffix+".apk")
- linkFlags = append(linkFlags, "--split", path.String()+":"+s)
- splitPackages = append(splitPackages, path)
- splits = append(splits, split{
- name: s,
- suffix: suffix,
- path: path,
- })
- }
- aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
- linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages)
- // Extract assets from the resource package output so that they can be used later in aapt2link
- // for modules that depend on this one.
- if android.PrefixInList(linkFlags, "-A ") || len(assetPackages) > 0 {
- assets := android.PathForModuleOut(ctx, "assets.zip")
- ctx.Build(pctx, android.BuildParams{
- Rule: extractAssetsRule,
- Input: packageRes,
- Output: assets,
- Description: "extract assets from built resource file",
- })
- a.assetPackage = android.OptionalPathForPath(assets)
- }
- a.aaptSrcJar = srcJar
- a.exportPackage = packageRes
- a.manifestPath = manifestPath
- a.proguardOptionsFile = proguardOptionsFile
- a.rroDirs = rroDirs
- a.extraAaptPackagesFile = extraPackages
- a.rTxt = rTxt
- a.splits = splits
- }
- // aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
- func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
- transitiveStaticLibs, transitiveStaticLibManifests android.Paths, staticRRODirs []rroDir, assets, deps android.Paths, flags []string) {
- var sharedLibs android.Paths
- if classLoaderContexts == nil {
- // Not all callers need to compute class loader context, those who don't just pass nil.
- // Create a temporary class loader context here (it will be computed, but not used).
- classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
- }
- sdkDep := decodeSdkDep(ctx, sdkContext)
- if sdkDep.useFiles {
- sharedLibs = append(sharedLibs, sdkDep.jars...)
- }
- ctx.VisitDirectDeps(func(module android.Module) {
- depTag := ctx.OtherModuleDependencyTag(module)
- var exportPackage android.Path
- aarDep, _ := module.(AndroidLibraryDependency)
- if aarDep != nil {
- exportPackage = aarDep.ExportPackage()
- }
- switch depTag {
- case instrumentationForTag:
- // Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
- case sdkLibTag, libTag:
- if exportPackage != nil {
- sharedLibs = append(sharedLibs, exportPackage)
- }
- case frameworkResTag:
- if exportPackage != nil {
- sharedLibs = append(sharedLibs, exportPackage)
- }
- case staticLibTag:
- if exportPackage != nil {
- transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
- transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
- transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
- if aarDep.ExportedAssets().Valid() {
- assets = append(assets, aarDep.ExportedAssets().Path())
- }
- outer:
- for _, d := range aarDep.ExportedRRODirs() {
- for _, e := range staticRRODirs {
- if d.path == e.path {
- continue outer
- }
- }
- staticRRODirs = append(staticRRODirs, d)
- }
- }
- }
- addCLCFromDep(ctx, module, classLoaderContexts)
- })
- deps = append(deps, sharedLibs...)
- deps = append(deps, transitiveStaticLibs...)
- if len(transitiveStaticLibs) > 0 {
- flags = append(flags, "--auto-add-overlay")
- }
- for _, sharedLib := range sharedLibs {
- flags = append(flags, "-I "+sharedLib.String())
- }
- transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
- transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
- return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags
- }
- type AndroidLibrary struct {
- Library
- aapt
- android.BazelModuleBase
- androidLibraryProperties androidLibraryProperties
- aarFile android.WritablePath
- exportedStaticPackages android.Paths
- }
- var _ android.OutputFileProducer = (*AndroidLibrary)(nil)
- // For OutputFileProducer interface
- func (a *AndroidLibrary) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case ".aar":
- return []android.Path{a.aarFile}, nil
- default:
- return a.Library.OutputFiles(tag)
- }
- }
- func (a *AndroidLibrary) ExportedStaticPackages() android.Paths {
- return a.exportedStaticPackages
- }
- var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
- func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
- a.Module.deps(ctx)
- sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
- if sdkDep.hasFrameworkLibs() {
- a.aapt.deps(ctx, sdkDep)
- }
- a.usesLibrary.deps(ctx, false)
- }
- func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- a.aapt.isLibrary = true
- a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
- a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil, false)
- a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
- ctx.CheckbuildFile(a.proguardOptionsFile)
- ctx.CheckbuildFile(a.exportPackage)
- ctx.CheckbuildFile(a.aaptSrcJar)
- // apps manifests are handled by aapt, don't let Module see them
- a.properties.Manifest = nil
- a.linter.mergedManifest = a.aapt.mergedManifestFile
- a.linter.manifest = a.aapt.manifestPath
- a.linter.resources = a.aapt.resourceFiles
- a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
- a.proguardOptionsFile)
- a.Module.compile(ctx, a.aaptSrcJar)
- a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar")
- var res android.Paths
- if a.androidLibraryProperties.BuildAAR {
- BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
- ctx.CheckbuildFile(a.aarFile)
- }
- a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles,
- android.PathsForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files)...)
- ctx.VisitDirectDeps(func(m android.Module) {
- if ctx.OtherModuleDependencyTag(m) == staticLibTag {
- if lib, ok := m.(LibraryDependency); ok {
- a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
- }
- if alib, ok := m.(AndroidLibraryDependency); ok {
- a.exportedStaticPackages = append(a.exportedStaticPackages, alib.ExportPackage())
- a.exportedStaticPackages = append(a.exportedStaticPackages, alib.ExportedStaticPackages()...)
- }
- }
- })
- a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
- a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
- prebuiltJniPackages := android.Paths{}
- ctx.VisitDirectDeps(func(module android.Module) {
- if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
- prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
- }
- })
- if len(prebuiltJniPackages) > 0 {
- ctx.SetProvider(JniPackageProvider, JniPackageInfo{
- JniPackages: prebuiltJniPackages,
- })
- }
- }
- // android_library builds and links sources into a `.jar` file for the device along with Android resources.
- //
- // An android_library has a single variant that produces a `.jar` file containing `.class` files that were
- // compiled against the device bootclasspath, along with a `package-res.apk` file containing Android resources compiled
- // with aapt2. This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of
- // an android_app module.
- func AndroidLibraryFactory() android.Module {
- module := &AndroidLibrary{}
- module.Module.addHostAndDeviceProperties()
- module.AddProperties(
- &module.aaptProperties,
- &module.androidLibraryProperties)
- module.androidLibraryProperties.BuildAAR = true
- module.Module.linter.library = true
- android.InitApexModule(module)
- InitJavaModule(module, android.DeviceSupported)
- android.InitBazelModule(module)
- return module
- }
- //
- // AAR (android library) prebuilts
- //
- // Properties for android_library_import
- type AARImportProperties struct {
- // ARR (android library prebuilt) filepath. Exactly one ARR is required.
- Aars []string `android:"path"`
- // If not blank, set to the version of the sdk to compile against.
- // Defaults to private.
- // Values are of one of the following forms:
- // 1) numerical API level, "current", "none", or "core_platform"
- // 2) An SDK kind with an API level: "<sdk kind>_<API level>"
- // See build/soong/android/sdk_version.go for the complete and up to date list of SDK kinds.
- // If the SDK kind is empty, it will be set to public
- Sdk_version *string
- // If not blank, set the minimum version of the sdk that the compiled artifacts will run against.
- // Defaults to sdk_version if not set. See sdk_version for possible values.
- Min_sdk_version *string
- // List of java static libraries that the included ARR (android library prebuilts) has dependencies to.
- Static_libs []string
- // List of java libraries that the included ARR (android library prebuilts) has dependencies to.
- Libs []string
- // If set to true, run Jetifier against .aar file. Defaults to false.
- Jetifier *bool
- // If true, extract JNI libs from AAR archive. These libs will be accessible to android_app modules and
- // will be passed transitively through android_libraries to an android_app.
- //TODO(b/241138093) evaluate whether we can have this flag default to true for Bazel conversion
- Extract_jni *bool
- }
- type AARImport struct {
- android.ModuleBase
- android.DefaultableModuleBase
- android.ApexModuleBase
- android.BazelModuleBase
- prebuilt android.Prebuilt
- // Functionality common to Module and Import.
- embeddableInModuleAndImport
- providesTransitiveHeaderJars
- properties AARImportProperties
- classpathFile android.WritablePath
- proguardFlags android.WritablePath
- exportPackage android.WritablePath
- extraAaptPackagesFile android.WritablePath
- manifest android.WritablePath
- assetsPackage android.WritablePath
- exportedStaticPackages android.Paths
- hideApexVariantFromMake bool
- aarPath android.Path
- jniPackages android.Paths
- sdkVersion android.SdkSpec
- minSdkVersion android.ApiLevel
- }
- var _ android.OutputFileProducer = (*AARImport)(nil)
- // For OutputFileProducer interface
- func (a *AARImport) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case ".aar":
- return []android.Path{a.aarPath}, nil
- case "":
- return []android.Path{a.classpathFile}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
- }
- func (a *AARImport) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpecFrom(ctx, String(a.properties.Sdk_version))
- }
- func (a *AARImport) SystemModules() string {
- return ""
- }
- func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
- if a.properties.Min_sdk_version != nil {
- return android.ApiLevelFrom(ctx, *a.properties.Min_sdk_version)
- }
- return a.SdkVersion(ctx).ApiLevel
- }
- func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
- return android.SdkSpecFrom(ctx, "").ApiLevel
- }
- func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
- return a.SdkVersion(ctx).ApiLevel
- }
- func (a *AARImport) javaVersion() string {
- return ""
- }
- var _ AndroidLibraryDependency = (*AARImport)(nil)
- func (a *AARImport) ExportPackage() android.Path {
- return a.exportPackage
- }
- func (a *AARImport) ExportedProguardFlagFiles() android.Paths {
- return android.Paths{a.proguardFlags}
- }
- func (a *AARImport) ExportedRRODirs() []rroDir {
- return nil
- }
- func (a *AARImport) ExportedStaticPackages() android.Paths {
- return a.exportedStaticPackages
- }
- func (a *AARImport) ExportedManifests() android.Paths {
- return android.Paths{a.manifest}
- }
- func (a *AARImport) ExportedAssets() android.OptionalPath {
- return android.OptionalPathForPath(a.assetsPackage)
- }
- // RRO enforcement is not available on aar_import since its RRO dirs are not
- // exported.
- func (a *AARImport) SetRROEnforcedForDependent(enforce bool) {
- }
- // RRO enforcement is not available on aar_import since its RRO dirs are not
- // exported.
- func (a *AARImport) IsRROEnforced(ctx android.BaseModuleContext) bool {
- return false
- }
- func (a *AARImport) Prebuilt() *android.Prebuilt {
- return &a.prebuilt
- }
- func (a *AARImport) Name() string {
- return a.prebuilt.Name(a.ModuleBase.Name())
- }
- func (a *AARImport) JacocoReportClassesFile() android.Path {
- return nil
- }
- func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
- if !ctx.Config().AlwaysUsePrebuiltSdks() {
- sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
- if sdkDep.useModule && sdkDep.frameworkResModule != "" {
- ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule)
- }
- }
- ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...)
- ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...)
- }
- type JniPackageInfo struct {
- // List of zip files containing JNI libraries
- // Zip files should have directory structure jni/<arch>/*.so
- JniPackages android.Paths
- }
- var JniPackageProvider = blueprint.NewProvider(JniPackageInfo{})
- // Unzip an AAR and extract the JNI libs for $archString.
- var extractJNI = pctx.AndroidStaticRule("extractJNI",
- blueprint.RuleParams{
- Command: `rm -rf $out $outDir && touch $out && ` +
- `unzip -qoDD -d $outDir $in "jni/${archString}/*" && ` +
- `jni_files=$$(find $outDir/jni -type f) && ` +
- // print error message if there are no JNI libs for this arch
- `[ -n "$$jni_files" ] || (echo "ERROR: no JNI libs found for arch ${archString}" && exit 1) && ` +
- `${config.SoongZipCmd} -o $out -P 'lib/${archString}' ` +
- `-C $outDir/jni/${archString} $$(echo $$jni_files | xargs -n1 printf " -f %s")`,
- CommandDeps: []string{"${config.SoongZipCmd}"},
- },
- "outDir", "archString")
- // Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be
- // touched to create an empty file. The res directory is not extracted, as it will be extracted in its own rule.
- var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
- blueprint.RuleParams{
- Command: `rm -rf $outDir && mkdir -p $outDir && ` +
- `unzip -qoDD -d $outDir $in && rm -rf $outDir/res && touch $out && ` +
- `${config.Zip2ZipCmd} -i $in -o $assetsPackage 'assets/**/*' && ` +
- `${config.MergeZipsCmd} $combinedClassesJar $$(ls $outDir/classes.jar 2> /dev/null) $$(ls $outDir/libs/*.jar 2> /dev/null)`,
- CommandDeps: []string{"${config.MergeZipsCmd}", "${config.Zip2ZipCmd}"},
- },
- "outDir", "combinedClassesJar", "assetsPackage")
- func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if len(a.properties.Aars) != 1 {
- ctx.PropertyErrorf("aars", "exactly one aar is required")
- return
- }
- a.sdkVersion = a.SdkVersion(ctx)
- a.minSdkVersion = a.MinSdkVersion(ctx)
- a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
- aarName := ctx.ModuleName() + ".aar"
- a.aarPath = android.PathForModuleSrc(ctx, a.properties.Aars[0])
- if Bool(a.properties.Jetifier) {
- inputFile := a.aarPath
- a.aarPath = android.PathForModuleOut(ctx, "jetifier", aarName)
- TransformJetifier(ctx, a.aarPath.(android.WritablePath), inputFile)
- }
- extractedAARDir := android.PathForModuleOut(ctx, "aar")
- a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar")
- a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
- a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml")
- a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip")
- ctx.Build(pctx, android.BuildParams{
- Rule: unzipAAR,
- Input: a.aarPath,
- Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage},
- Description: "unzip AAR",
- Args: map[string]string{
- "outDir": extractedAARDir.String(),
- "combinedClassesJar": a.classpathFile.String(),
- "assetsPackage": a.assetsPackage.String(),
- },
- })
- // Always set --pseudo-localize, it will be stripped out later for release
- // builds that don't want it.
- compileFlags := []string{"--pseudo-localize"}
- compiledResDir := android.PathForModuleOut(ctx, "flat-res")
- flata := compiledResDir.Join(ctx, "gen_res.flata")
- aapt2CompileZip(ctx, flata, a.aarPath, "res", compileFlags)
- a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
- // the subdir "android" is required to be filtered by package names
- srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar")
- proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
- rTxt := android.PathForModuleOut(ctx, "R.txt")
- a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages")
- var linkDeps android.Paths
- linkFlags := []string{
- "--static-lib",
- "--no-static-lib-packages",
- "--auto-add-overlay",
- }
- linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
- linkDeps = append(linkDeps, a.manifest)
- transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags :=
- aaptLibs(ctx, android.SdkContext(a), nil)
- _ = staticLibManifests
- _ = staticRRODirs
- linkDeps = append(linkDeps, libDeps...)
- linkFlags = append(linkFlags, libFlags...)
- overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
- aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
- linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil)
- // Merge this import's assets with its dependencies' assets (if there are any).
- if len(transitiveAssets) > 0 {
- mergedAssets := android.PathForModuleOut(ctx, "merged-assets.zip")
- inputZips := append(android.Paths{a.assetsPackage}, transitiveAssets...)
- ctx.Build(pctx, android.BuildParams{
- Rule: mergeAssetsRule,
- Inputs: inputZips,
- Output: mergedAssets,
- Description: "merge assets from dependencies and self",
- })
- a.assetsPackage = mergedAssets
- }
- a.collectTransitiveHeaderJars(ctx)
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(a.classpathFile),
- TransitiveLibsHeaderJars: a.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
- ImplementationJars: android.PathsIfNonNil(a.classpathFile),
- })
- if proptools.Bool(a.properties.Extract_jni) {
- for _, t := range ctx.MultiTargets() {
- arch := t.Arch.Abi[0]
- path := android.PathForModuleOut(ctx, arch+"_jni.zip")
- a.jniPackages = append(a.jniPackages, path)
- outDir := android.PathForModuleOut(ctx, "aarForJni")
- aarPath := android.PathForModuleSrc(ctx, a.properties.Aars[0])
- ctx.Build(pctx, android.BuildParams{
- Rule: extractJNI,
- Input: aarPath,
- Outputs: android.WritablePaths{path},
- Description: "extract JNI from AAR",
- Args: map[string]string{
- "outDir": outDir.String(),
- "archString": arch,
- },
- })
- }
- ctx.SetProvider(JniPackageProvider, JniPackageInfo{
- JniPackages: a.jniPackages,
- })
- }
- }
- func (a *AARImport) HeaderJars() android.Paths {
- return android.Paths{a.classpathFile}
- }
- func (a *AARImport) ImplementationAndResourcesJars() android.Paths {
- return android.Paths{a.classpathFile}
- }
- func (a *AARImport) DexJarBuildPath() android.Path {
- return nil
- }
- func (a *AARImport) DexJarInstallPath() android.Path {
- return nil
- }
- func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
- return nil
- }
- var _ android.ApexModule = (*AARImport)(nil)
- // Implements android.ApexModule
- func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- return a.depIsInSameApex(ctx, dep)
- }
- // Implements android.ApexModule
- func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- return nil
- }
- var _ android.PrebuiltInterface = (*AARImport)(nil)
- // android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
- //
- // This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of
- // an android_app module.
- func AARImportFactory() android.Module {
- module := &AARImport{}
- module.AddProperties(&module.properties)
- android.InitPrebuiltModule(module, &module.properties.Aars)
- android.InitApexModule(module)
- InitJavaModuleMultiTargets(module, android.DeviceSupported)
- android.InitBazelModule(module)
- return module
- }
- type bazelAapt struct {
- Manifest bazel.Label
- Resource_files bazel.LabelListAttribute
- }
- type bazelAndroidLibrary struct {
- *javaLibraryAttributes
- *bazelAapt
- }
- type bazelAndroidLibraryImport struct {
- Aar bazel.Label
- Deps bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
- Sdk_version bazel.StringAttribute
- }
- func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) *bazelAapt {
- manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
- resourceFiles := bazel.LabelList{
- Includes: []bazel.Label{},
- }
- for _, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") {
- files := android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir))
- resourceFiles.Includes = append(resourceFiles.Includes, files...)
- }
- return &bazelAapt{
- android.BazelLabelForModuleSrcSingle(ctx, manifest),
- bazel.MakeLabelListAttribute(resourceFiles),
- }
- }
- func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- aars := android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Aars, []string{})
- exportableStaticLibs := []string{}
- // TODO(b/240716882): investigate and handle static_libs deps that are not imports. They are not supported for export by Bazel.
- for _, depName := range a.properties.Static_libs {
- if dep, ok := ctx.ModuleFromName(depName); ok {
- switch dep.(type) {
- case *AARImport, *Import:
- exportableStaticLibs = append(exportableStaticLibs, depName)
- }
- }
- }
- name := android.RemoveOptionalPrebuiltPrefix(a.Name())
- deps := android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(append(a.properties.Static_libs, a.properties.Libs...))))
- exports := android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(exportableStaticLibs))
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "aar_import",
- Bzl_load_location: "//build/bazel/rules/android:aar_import.bzl",
- },
- android.CommonAttributes{Name: name},
- &bazelAndroidLibraryImport{
- Aar: aars.Includes[0],
- Deps: bazel.MakeLabelListAttribute(deps),
- Exports: bazel.MakeLabelListAttribute(exports),
- Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
- },
- )
- neverlink := true
- ctx.CreateBazelTargetModule(
- AndroidLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: name + "-neverlink"},
- &bazelAndroidLibrary{
- javaLibraryAttributes: &javaLibraryAttributes{
- Neverlink: bazel.BoolAttribute{Value: &neverlink},
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
- },
- },
- },
- )
- }
- func AndroidLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
- return bazel.BazelTargetModuleProperties{
- Rule_class: "android_library",
- Bzl_load_location: "//build/bazel/rules/android:android_library.bzl",
- }
- }
- func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, bp2buildInfo := a.convertLibraryAttrsBp2Build(ctx)
- depLabels := bp2buildInfo.DepLabels
- deps := depLabels.Deps
- if !commonAttrs.Srcs.IsEmpty() {
- deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
- } else if !depLabels.Deps.IsEmpty() {
- ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
- }
- name := a.Name()
- props := AndroidLibraryBazelTargetModuleProperties()
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: name},
- &bazelAndroidLibrary{
- &javaLibraryAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- Exports: depLabels.StaticDeps,
- },
- a.convertAaptAttrsWithBp2Build(ctx),
- },
- )
- neverlink := true
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: name + "-neverlink"},
- &bazelAndroidLibrary{
- javaLibraryAttributes: &javaLibraryAttributes{
- Neverlink: bazel.BoolAttribute{Value: &neverlink},
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: a.deviceProperties.Sdk_version},
- Java_version: bazel.StringAttribute{Value: a.properties.Java_version},
- },
- },
- },
- )
- }
|