Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fabb608b authored by Colin Cross's avatar Colin Cross
Browse files

Soong AAR prebuilt support

Add support for android_library_import modules that take an
aar file.

Bug: 73724997
Test: m checkbuild
Change-Id: I670b56f0a3b7501d9478a6064a04d0cb9c1bb611
parent 9ca69429
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -215,6 +215,7 @@ bootstrap_go_package {
    ],
    srcs: [
        "java/aapt2.go",
        "java/aar.go",
        "java/androidmk.go",
        "java/app_builder.go",
        "java/app.go",
+17 −0
Original line number Diff line number Diff line
@@ -81,6 +81,8 @@ func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Pat
			Outputs:     outPaths,
			Args: map[string]string{
				"outDir": android.PathForModuleOut(ctx, "aapt2", dir.String()).String(),
				// Always set --pseudo-localize, it will be stripped out later for release
				// builds that don't want it.
				"cFlags": "--pseudo-localize",
			},
		})
@@ -92,6 +94,21 @@ func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Pat
	return ret
}

func aapt2CompileDirs(ctx android.ModuleContext, flata android.WritablePath, dirs android.Paths, deps android.Paths) {
	ctx.Build(pctx, android.BuildParams{
		Rule:        aapt2CompileRule,
		Description: "aapt2 compile dirs",
		Implicits:   deps,
		Output:      flata,
		Args: map[string]string{
			"outDir": flata.String(),
			// Always set --pseudo-localize, it will be stripped out later for release
			// builds that don't want it.
			"cFlags": "--pseudo-localize " + android.JoinWithPrefix(dirs.Strings(), "--dir "),
		},
	})
}

var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
	blueprint.RuleParams{
		Command: `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions $inFlags && ` +

java/aar.go

0 → 100644
+170 −0
Original line number Diff line number Diff line
// 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 (
	"android/soong/android"

	"github.com/google/blueprint"
)

//
// AAR (android library) prebuilts
//
func init() {
	android.RegisterModuleType("android_library_import", AARImportFactory)
}

type AARImportProperties struct {
	Aars []string

	Sdk_version *string
}

type AARImport struct {
	android.ModuleBase
	prebuilt android.Prebuilt

	properties AARImportProperties

	classpathFile android.WritablePath
	proguardFlags android.WritablePath
	exportPackage android.WritablePath
}

func (a *AARImport) Prebuilt() *android.Prebuilt {
	return &a.prebuilt
}

func (a *AARImport) Name() string {
	return a.prebuilt.Name(a.ModuleBase.Name())
}

func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
	// TODO: this should use decodeSdkDep once that knows about current
	if !ctx.Config().UnbundledBuild() {
		switch String(a.properties.Sdk_version) { // TODO: Res_sdk_version?
		case "current", "system_current", "test_current", "":
			ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
		}
	}
}

// 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, and any directories in $expectedDirs will be created.
var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
	blueprint.RuleParams{
		Command: `rm -rf $outDir && mkdir -p $outDir $expectedDirs && ` +
			`unzip -qo -d $outDir $in && touch $out`,
	},
	"expectedDirs", "outDir")

func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	if len(a.properties.Aars) != 1 {
		ctx.PropertyErrorf("aars", "exactly one aar is required")
		return
	}

	aar := android.PathForModuleSrc(ctx, a.properties.Aars[0])

	extractedAARDir := android.PathForModuleOut(ctx, "aar")
	extractedResDir := extractedAARDir.Join(ctx, "res")
	a.classpathFile = extractedAARDir.Join(ctx, "classes.jar")
	a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
	manifest := extractedAARDir.Join(ctx, "AndroidManifest.xml")

	ctx.Build(pctx, android.BuildParams{
		Rule:        unzipAAR,
		Input:       aar,
		Outputs:     android.WritablePaths{a.classpathFile, a.proguardFlags, manifest},
		Description: "unzip AAR",
		Args: map[string]string{
			"expectedDirs": extractedResDir.String(),
			"outDir":       extractedAARDir.String(),
		},
	})

	compiledResDir := android.PathForModuleOut(ctx, "flat-res")
	aaptCompileDeps := android.Paths{a.classpathFile}
	aaptCompileDirs := android.Paths{extractedResDir}
	flata := compiledResDir.Join(ctx, "gen_res.flata")
	aapt2CompileDirs(ctx, flata, aaptCompileDirs, aaptCompileDeps)

	a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
	srcJar := android.PathForModuleGen(ctx, "R.jar")
	proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")

	var linkDeps android.Paths

	linkFlags := []string{
		"--static-lib",
		"--no-static-lib-packages",
		"--auto-add-overlay",
	}

	linkFlags = append(linkFlags, "--manifest "+manifest.String())
	linkDeps = append(linkDeps, manifest)

	// Include dirs
	ctx.VisitDirectDeps(func(module android.Module) {
		var depFiles android.Paths
		if javaDep, ok := module.(Dependency); ok {
			// TODO: shared android libraries
			if ctx.OtherModuleName(module) == "framework-res" {
				depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage}
			}
		}

		for _, dep := range depFiles {
			linkFlags = append(linkFlags, "-I "+dep.String())
		}
		linkDeps = append(linkDeps, depFiles...)
	})

	sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version))
	if sdkDep.useFiles {
		linkFlags = append(linkFlags, "-I "+sdkDep.jar.String())
		linkDeps = append(linkDeps, sdkDep.jar)
	}

	aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile,
		linkFlags, linkDeps, nil, android.Paths{flata})
}

var _ Dependency = (*AARImport)(nil)

func (a *AARImport) HeaderJars() android.Paths {
	return android.Paths{a.classpathFile}
}

func (a *AARImport) ImplementationJars() android.Paths {
	return android.Paths{a.classpathFile}
}

func (a *AARImport) AidlIncludeDirs() android.Paths {
	return nil
}

var _ android.PrebuiltInterface = (*Import)(nil)

func AARImportFactory() android.Module {
	module := &AARImport{}

	module.AddProperties(&module.properties)

	android.InitPrebuiltModule(module, &module.properties.Aars)
	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
	return module
}
+18 −0
Original line number Diff line number Diff line
@@ -112,6 +112,24 @@ func (prebuilt *Import) AndroidMk() android.AndroidMkData {
	}
}

func (prebuilt *AARImport) AndroidMk() android.AndroidMkData {
	return android.AndroidMkData{
		Class:      "JAVA_LIBRARIES",
		OutputFile: android.OptionalPathForPath(prebuilt.classpathFile),
		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
		Extra: []android.AndroidMkExtraFunc{
			func(w io.Writer, outputFile android.Path) {
				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
				fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
				fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", prebuilt.classpathFile.String())
				fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", prebuilt.exportPackage.String())
				fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=", prebuilt.proguardFlags.String())
				fmt.Fprintln(w, "LOCAL_SDK_VERSION :=", String(prebuilt.properties.Sdk_version))
			},
		},
	}
}

func (binary *Binary) AndroidMk() android.AndroidMkData {

	if !binary.isWrapperVariant {
+2 −2
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ func init() {
// AndroidManifest.xml merging
// package splits

type androidAppProperties struct {
type appProperties struct {
	// path to a certificate, or the name of a certificate in the default
	// certificate directory, or blank to use the default product certificate
	Certificate *string
@@ -71,7 +71,7 @@ type androidAppProperties struct {
type AndroidApp struct {
	Module

	appProperties androidAppProperties
	appProperties appProperties

	aaptSrcJar    android.Path
	exportPackage android.Path