github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/java/aar.go (about)

     1  // Copyright 2018 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package java
    16  
    17  import (
    18  	"android/soong/android"
    19  	"strings"
    20  
    21  	"github.com/google/blueprint"
    22  	"github.com/google/blueprint/proptools"
    23  )
    24  
    25  type AndroidLibraryDependency interface {
    26  	Dependency
    27  	ExportPackage() android.Path
    28  	ExportedProguardFlagFiles() android.Paths
    29  	ExportedStaticPackages() android.Paths
    30  }
    31  
    32  func init() {
    33  	android.RegisterModuleType("android_library_import", AARImportFactory)
    34  	android.RegisterModuleType("android_library", AndroidLibraryFactory)
    35  }
    36  
    37  //
    38  // AAR (android library)
    39  //
    40  
    41  type androidLibraryProperties struct {
    42  	BuildAAR bool `blueprint:"mutated"`
    43  }
    44  
    45  type aaptProperties struct {
    46  	// flags passed to aapt when creating the apk
    47  	Aaptflags []string
    48  
    49  	// list of directories relative to the Blueprints file containing assets.
    50  	// Defaults to "assets"
    51  	Asset_dirs []string
    52  
    53  	// list of directories relative to the Blueprints file containing
    54  	// Android resources
    55  	Resource_dirs []string
    56  
    57  	// path to AndroidManifest.xml.  If unset, defaults to "AndroidManifest.xml".
    58  	Manifest *string
    59  }
    60  
    61  type aapt struct {
    62  	aaptSrcJar            android.Path
    63  	exportPackage         android.Path
    64  	manifestPath          android.Path
    65  	proguardOptionsFile   android.Path
    66  	rroDirs               android.Paths
    67  	rTxt                  android.Path
    68  	extraAaptPackagesFile android.Path
    69  
    70  	aaptProperties aaptProperties
    71  }
    72  
    73  func (a *aapt) ExportPackage() android.Path {
    74  	return a.exportPackage
    75  }
    76  
    77  func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkVersion string) (flags []string, deps android.Paths,
    78  	resDirs, overlayDirs []globbedResourceDir, overlayFiles, rroDirs android.Paths, manifestPath android.Path) {
    79  
    80  	hasVersionCode := false
    81  	hasVersionName := false
    82  	for _, f := range a.aaptProperties.Aaptflags {
    83  		if strings.HasPrefix(f, "--version-code") {
    84  			hasVersionCode = true
    85  		} else if strings.HasPrefix(f, "--version-name") {
    86  			hasVersionName = true
    87  		}
    88  	}
    89  
    90  	var linkFlags []string
    91  
    92  	// Flags specified in Android.bp
    93  	linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
    94  
    95  	linkFlags = append(linkFlags, "--no-static-lib-packages")
    96  
    97  	// Find implicit or explicit asset and resource dirs
    98  	assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
    99  	resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
   100  
   101  	var linkDeps android.Paths
   102  
   103  	// Glob directories into lists of paths
   104  	for _, dir := range resourceDirs {
   105  		resDirs = append(resDirs, globbedResourceDir{
   106  			dir:   dir,
   107  			files: androidResourceGlob(ctx, dir),
   108  		})
   109  		resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
   110  		overlayDirs = append(overlayDirs, resOverlayDirs...)
   111  		rroDirs = append(rroDirs, resRRODirs...)
   112  	}
   113  
   114  	var assetFiles android.Paths
   115  	for _, dir := range assetDirs {
   116  		assetFiles = append(assetFiles, androidResourceGlob(ctx, dir)...)
   117  	}
   118  
   119  	// App manifest file
   120  	manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
   121  	manifestPath = android.PathForModuleSrc(ctx, manifestFile)
   122  	linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
   123  	linkDeps = append(linkDeps, manifestPath)
   124  
   125  	linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
   126  	linkDeps = append(linkDeps, assetFiles...)
   127  
   128  	transitiveStaticLibs, libDeps, libFlags := aaptLibs(ctx, sdkVersion)
   129  
   130  	overlayFiles = append(overlayFiles, transitiveStaticLibs...)
   131  	linkDeps = append(linkDeps, libDeps...)
   132  	linkFlags = append(linkFlags, libFlags...)
   133  
   134  	// SDK version flags
   135  	switch sdkVersion {
   136  	case "", "current", "system_current", "test_current":
   137  		sdkVersion = proptools.NinjaEscape([]string{ctx.Config().DefaultAppTargetSdk()})[0]
   138  	}
   139  
   140  	linkFlags = append(linkFlags, "--min-sdk-version "+sdkVersion)
   141  	linkFlags = append(linkFlags, "--target-sdk-version "+sdkVersion)
   142  
   143  	// Version code
   144  	if !hasVersionCode {
   145  		linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion())
   146  	}
   147  
   148  	if !hasVersionName {
   149  		var versionName string
   150  		if ctx.ModuleName() == "framework-res" {
   151  			// Some builds set AppsDefaultVersionName() to include the build number ("O-123456").  aapt2 copies the
   152  			// version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things
   153  			// if it contains the build number.  Use the PlatformVersionName instead.
   154  			versionName = ctx.Config().PlatformVersionName()
   155  		} else {
   156  			versionName = ctx.Config().AppsDefaultVersionName()
   157  		}
   158  		versionName = proptools.NinjaEscape([]string{versionName})[0]
   159  		linkFlags = append(linkFlags, "--version-name ", versionName)
   160  	}
   161  
   162  	return linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath
   163  }
   164  
   165  func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkVersion string) {
   166  	if !ctx.Config().UnbundledBuild() {
   167  		sdkDep := decodeSdkDep(ctx, sdkVersion)
   168  		if sdkDep.frameworkResModule != "" {
   169  			ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
   170  		}
   171  	}
   172  }
   173  
   174  func (a *aapt) buildActions(ctx android.ModuleContext, sdkVersion string, extraLinkFlags ...string) {
   175  	linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath := a.aapt2Flags(ctx, sdkVersion)
   176  
   177  	linkFlags = append(linkFlags, extraLinkFlags...)
   178  
   179  	packageRes := android.PathForModuleOut(ctx, "package-res.apk")
   180  	srcJar := android.PathForModuleGen(ctx, "R.jar")
   181  	proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
   182  	rTxt := android.PathForModuleOut(ctx, "R.txt")
   183  	// This file isn't used by Soong, but is generated for exporting
   184  	extraPackages := android.PathForModuleOut(ctx, "extra_packages")
   185  
   186  	var compiledRes, compiledOverlay android.Paths
   187  	for _, dir := range resDirs {
   188  		compiledRes = append(compiledRes, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
   189  	}
   190  	for _, dir := range overlayDirs {
   191  		compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
   192  	}
   193  
   194  	compiledOverlay = append(compiledOverlay, overlayFiles...)
   195  
   196  	aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
   197  		linkFlags, linkDeps, compiledRes, compiledOverlay)
   198  
   199  	a.aaptSrcJar = srcJar
   200  	a.exportPackage = packageRes
   201  	a.manifestPath = manifestPath
   202  	a.proguardOptionsFile = proguardOptionsFile
   203  	a.rroDirs = rroDirs
   204  	a.extraAaptPackagesFile = extraPackages
   205  	a.rTxt = rTxt
   206  }
   207  
   208  // aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
   209  func aaptLibs(ctx android.ModuleContext, sdkVersion string) (transitiveStaticLibs, deps android.Paths,
   210  	flags []string) {
   211  
   212  	var sharedLibs android.Paths
   213  
   214  	sdkDep := decodeSdkDep(ctx, sdkVersion)
   215  	if sdkDep.useFiles {
   216  		sharedLibs = append(sharedLibs, sdkDep.jar)
   217  	}
   218  
   219  	ctx.VisitDirectDeps(func(module android.Module) {
   220  		var exportPackage android.Path
   221  		aarDep, _ := module.(AndroidLibraryDependency)
   222  		if aarDep != nil {
   223  			exportPackage = aarDep.ExportPackage()
   224  		}
   225  
   226  		switch ctx.OtherModuleDependencyTag(module) {
   227  		case libTag, frameworkResTag:
   228  			if exportPackage != nil {
   229  				sharedLibs = append(sharedLibs, exportPackage)
   230  			}
   231  		case staticLibTag:
   232  			if exportPackage != nil {
   233  				transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
   234  				transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
   235  			}
   236  		}
   237  	})
   238  
   239  	deps = append(deps, sharedLibs...)
   240  	deps = append(deps, transitiveStaticLibs...)
   241  
   242  	if len(transitiveStaticLibs) > 0 {
   243  		flags = append(flags, "--auto-add-overlay")
   244  	}
   245  
   246  	for _, sharedLib := range sharedLibs {
   247  		flags = append(flags, "-I "+sharedLib.String())
   248  	}
   249  
   250  	transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
   251  
   252  	return transitiveStaticLibs, deps, flags
   253  }
   254  
   255  type AndroidLibrary struct {
   256  	Library
   257  	aapt
   258  
   259  	androidLibraryProperties androidLibraryProperties
   260  
   261  	aarFile android.WritablePath
   262  
   263  	exportedProguardFlagFiles android.Paths
   264  	exportedStaticPackages    android.Paths
   265  }
   266  
   267  func (a *AndroidLibrary) ExportedProguardFlagFiles() android.Paths {
   268  	return a.exportedProguardFlagFiles
   269  }
   270  
   271  func (a *AndroidLibrary) ExportedStaticPackages() android.Paths {
   272  	return a.exportedStaticPackages
   273  }
   274  
   275  var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
   276  
   277  func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
   278  	a.Module.deps(ctx)
   279  	if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
   280  		a.aapt.deps(ctx, String(a.deviceProperties.Sdk_version))
   281  	}
   282  }
   283  
   284  func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
   285  	a.aapt.buildActions(ctx, String(a.deviceProperties.Sdk_version), "--static-lib")
   286  
   287  	ctx.CheckbuildFile(a.proguardOptionsFile)
   288  	ctx.CheckbuildFile(a.exportPackage)
   289  	ctx.CheckbuildFile(a.aaptSrcJar)
   290  
   291  	// apps manifests are handled by aapt, don't let Module see them
   292  	a.properties.Manifest = nil
   293  
   294  	a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
   295  		a.proguardOptionsFile)
   296  
   297  	a.Module.compile(ctx, a.aaptSrcJar)
   298  
   299  	a.aarFile = android.PathForOutput(ctx, ctx.ModuleName()+".aar")
   300  	var res android.Paths
   301  	if a.androidLibraryProperties.BuildAAR {
   302  		BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
   303  		ctx.CheckbuildFile(a.aarFile)
   304  	}
   305  
   306  	ctx.VisitDirectDeps(func(m android.Module) {
   307  		if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
   308  			a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
   309  			a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportPackage())
   310  			a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportedStaticPackages()...)
   311  		}
   312  	})
   313  
   314  	a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
   315  	a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
   316  }
   317  
   318  func AndroidLibraryFactory() android.Module {
   319  	module := &AndroidLibrary{}
   320  
   321  	module.AddProperties(
   322  		&module.Module.properties,
   323  		&module.Module.deviceProperties,
   324  		&module.Module.protoProperties,
   325  		&module.aaptProperties,
   326  		&module.androidLibraryProperties)
   327  
   328  	module.androidLibraryProperties.BuildAAR = true
   329  
   330  	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
   331  	return module
   332  }
   333  
   334  //
   335  // AAR (android library) prebuilts
   336  //
   337  
   338  type AARImportProperties struct {
   339  	Aars []string
   340  
   341  	Sdk_version *string
   342  
   343  	Static_libs []string
   344  	Libs        []string
   345  }
   346  
   347  type AARImport struct {
   348  	android.ModuleBase
   349  	prebuilt android.Prebuilt
   350  
   351  	properties AARImportProperties
   352  
   353  	classpathFile         android.WritablePath
   354  	proguardFlags         android.WritablePath
   355  	exportPackage         android.WritablePath
   356  	extraAaptPackagesFile android.WritablePath
   357  
   358  	exportedStaticPackages android.Paths
   359  }
   360  
   361  var _ AndroidLibraryDependency = (*AARImport)(nil)
   362  
   363  func (a *AARImport) ExportPackage() android.Path {
   364  	return a.exportPackage
   365  }
   366  
   367  func (a *AARImport) ExportedProguardFlagFiles() android.Paths {
   368  	return android.Paths{a.proguardFlags}
   369  }
   370  
   371  func (a *AARImport) ExportedStaticPackages() android.Paths {
   372  	return a.exportedStaticPackages
   373  }
   374  
   375  func (a *AARImport) Prebuilt() *android.Prebuilt {
   376  	return &a.prebuilt
   377  }
   378  
   379  func (a *AARImport) Name() string {
   380  	return a.prebuilt.Name(a.ModuleBase.Name())
   381  }
   382  
   383  func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
   384  	if !ctx.Config().UnbundledBuild() {
   385  		sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version))
   386  		if sdkDep.useModule && sdkDep.frameworkResModule != "" {
   387  			ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
   388  		}
   389  	}
   390  
   391  	ctx.AddDependency(ctx.Module(), libTag, a.properties.Libs...)
   392  	ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Static_libs...)
   393  }
   394  
   395  // Unzip an AAR into its constituent files and directories.  Any files in Outputs that don't exist in the AAR will be
   396  // touched to create an empty file, and any directories in $expectedDirs will be created.
   397  var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
   398  	blueprint.RuleParams{
   399  		Command: `rm -rf $outDir && mkdir -p $outDir $expectedDirs && ` +
   400  			`unzip -qo -d $outDir $in && touch $out`,
   401  	},
   402  	"expectedDirs", "outDir")
   403  
   404  func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
   405  	if len(a.properties.Aars) != 1 {
   406  		ctx.PropertyErrorf("aars", "exactly one aar is required")
   407  		return
   408  	}
   409  
   410  	aar := android.PathForModuleSrc(ctx, a.properties.Aars[0])
   411  
   412  	extractedAARDir := android.PathForModuleOut(ctx, "aar")
   413  	extractedResDir := extractedAARDir.Join(ctx, "res")
   414  	a.classpathFile = extractedAARDir.Join(ctx, "classes.jar")
   415  	a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
   416  	manifest := extractedAARDir.Join(ctx, "AndroidManifest.xml")
   417  
   418  	ctx.Build(pctx, android.BuildParams{
   419  		Rule:        unzipAAR,
   420  		Input:       aar,
   421  		Outputs:     android.WritablePaths{a.classpathFile, a.proguardFlags, manifest},
   422  		Description: "unzip AAR",
   423  		Args: map[string]string{
   424  			"expectedDirs": extractedResDir.String(),
   425  			"outDir":       extractedAARDir.String(),
   426  		},
   427  	})
   428  
   429  	compiledResDir := android.PathForModuleOut(ctx, "flat-res")
   430  	aaptCompileDeps := android.Paths{a.classpathFile}
   431  	aaptCompileDirs := android.Paths{extractedResDir}
   432  	flata := compiledResDir.Join(ctx, "gen_res.flata")
   433  	aapt2CompileDirs(ctx, flata, aaptCompileDirs, aaptCompileDeps)
   434  
   435  	a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
   436  	srcJar := android.PathForModuleGen(ctx, "R.jar")
   437  	proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
   438  	rTxt := android.PathForModuleOut(ctx, "R.txt")
   439  	a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages")
   440  
   441  	var linkDeps android.Paths
   442  
   443  	linkFlags := []string{
   444  		"--static-lib",
   445  		"--no-static-lib-packages",
   446  		"--auto-add-overlay",
   447  	}
   448  
   449  	linkFlags = append(linkFlags, "--manifest "+manifest.String())
   450  	linkDeps = append(linkDeps, manifest)
   451  
   452  	transitiveStaticLibs, libDeps, libFlags := aaptLibs(ctx, String(a.properties.Sdk_version))
   453  
   454  	linkDeps = append(linkDeps, libDeps...)
   455  	linkFlags = append(linkFlags, libFlags...)
   456  
   457  	overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
   458  
   459  	aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
   460  		linkFlags, linkDeps, nil, overlayRes)
   461  }
   462  
   463  var _ Dependency = (*AARImport)(nil)
   464  
   465  func (a *AARImport) HeaderJars() android.Paths {
   466  	return android.Paths{a.classpathFile}
   467  }
   468  
   469  func (a *AARImport) ImplementationJars() android.Paths {
   470  	return android.Paths{a.classpathFile}
   471  }
   472  
   473  func (a *AARImport) AidlIncludeDirs() android.Paths {
   474  	return nil
   475  }
   476  
   477  var _ android.PrebuiltInterface = (*Import)(nil)
   478  
   479  func AARImportFactory() android.Module {
   480  	module := &AARImport{}
   481  
   482  	module.AddProperties(&module.properties)
   483  
   484  	android.InitPrebuiltModule(module, &module.properties.Aars)
   485  	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
   486  	return module
   487  }