Allow building framework.jar and framework-res.apk

Update app support enough to build framework-res.apk, link
framework.jar against its generated files, and export it to
make.

Bug: 69917341
Test: m checkbuild tests docs
Change-Id: I7db29cd1f5fabb22e844483ecc7c38abfedbbe0a
This commit is contained in:
Colin Cross 2017-11-22 16:20:45 -08:00
parent 46029a4131
commit 5ab4e6d817
8 changed files with 117 additions and 18 deletions

View File

@ -16,6 +16,7 @@ package android
import (
"fmt"
"runtime"
"strings"
"github.com/google/blueprint"
@ -141,7 +142,7 @@ func (p PackageContext) SourcePathVariableWithEnvOverride(name, path, env string
})
}
// HostBinVariable returns a Variable whose value is the path to a host tool
// HostBinToolVariable returns a Variable whose value is the path to a host tool
// in the bin directory for host targets. It may only be called during a Go
// package's initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
@ -164,6 +165,33 @@ func (p PackageContext) HostBinToolPath(config Config, path string) (Path, error
return pa, nil
}
// HostJNIToolVariable returns a Variable whose value is the path to a host tool
// in the lib directory for host targets. It may only be called during a Go
// package's initialization - either from the init() function or as part of a
// package-scoped variable's initialization.
func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(config Config) (string, error) {
po, err := p.HostJNIToolPath(config, path)
if err != nil {
return "", err
}
return po.String(), nil
})
}
func (p PackageContext) HostJNIToolPath(config Config, path string) (Path, error) {
ctx := &configErrorWrapper{p, config, []error{}}
ext := ".so"
if runtime.GOOS == "darwin" {
ext = ".dylib"
}
pa := PathForOutput(ctx, "host", ctx.config.PrebuiltOS(), "lib64", path+ext)
if len(ctx.errors) > 0 {
return nil, ctx.errors[0]
}
return pa, nil
}
// HostJavaToolVariable returns a Variable whose value is the path to a host
// tool in the frameworks directory for host targets. It may only be called
// during a Go package's initialization - either from the init() function or as

View File

@ -93,6 +93,7 @@ func init() {
"LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
"LOCAL_NOTICE_FILE": "notice",
"LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
"LOCAL_INSTRUMENTATION_FOR": "instrumentation_for",
})
addStandardProperties(bpparser.ListType,
map[string]string{
@ -662,6 +663,8 @@ var conditionalTranslations = map[string]map[bool]string{
false: "target.not_linux_glibc"},
"(,$(TARGET_BUILD_APPS))": {
false: "product_variables.unbundled_build"},
"($(TARGET_BUILD_APPS),)": {
false: "product_variables.unbundled_build"},
"($(TARGET_BUILD_PDK),true)": {
true: "product_variables.pdk"},
"($(TARGET_BUILD_PDK), true)": {

View File

@ -46,6 +46,14 @@ func (library *Library) AndroidMk() android.AndroidMkData {
if library.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", library.jacocoReportClassesFile.String())
}
// Temporary hack: export sources used to compile framework.jar to Make
// to be used for droiddoc
// TODO(ccross): remove this once droiddoc is in soong
if library.Name() == "framework" {
fmt.Fprintln(w, "SOONG_FRAMEWORK_SRCS :=", strings.Join(library.compiledJavaSrcs.Strings(), " "))
fmt.Fprintln(w, "SOONG_FRAMEWORK_SRCJARS :=", strings.Join(library.compiledSrcJars.Strings(), " "))
}
},
},
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
@ -111,3 +119,33 @@ func (binary *Binary) AndroidMk() android.AndroidMkData {
},
}
}
func (app *AndroidApp) AndroidMk() android.AndroidMkData {
return android.AndroidMkData{
Class: "APPS",
OutputFile: android.OptionalPathForPath(app.outputFile),
Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
Extra: []android.AndroidMkExtraFunc{
func(w io.Writer, outputFile android.Path) {
if Bool(app.appProperties.Export_package_resources) {
if app.dexJarFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", app.dexJarFile.String())
}
fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", app.exportPackage.String())
if app.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
}
if app.Name() == "framework-res" {
fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
// Make base_rules.mk not put framework-res in a subdirectory called
// framework_res.
fmt.Fprintln(w, "LOCAL_NO_STANDARD_LIBRARIES := true")
}
}
},
},
}
}

View File

@ -27,6 +27,7 @@ import (
func init() {
android.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
android.RegisterModuleType("android_app", AndroidAppFactory)
}
// AAR prebuilts
@ -76,7 +77,7 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
switch String(a.deviceProperties.Sdk_version) { // TODO: Res_sdk_version?
case "current", "system_current", "":
case "current", "system_current", "test_current", "":
ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
default:
// We'll already have a dependency on an sdk prebuilt android.jar
@ -116,7 +117,13 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// a.properties.Proguard.Enabled = true
//}
a.Module.compile(ctx)
if String(a.appProperties.Instrumentation_for) == "" {
a.properties.Instrument = true
}
if ctx.ModuleName() != "framework-res" {
a.Module.compile(ctx, a.aaptSrcJar)
}
certificate := String(a.appProperties.Certificate)
if certificate == "" {
@ -138,7 +145,12 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.outputFile = packageFile
ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
if ctx.ModuleName() == "framework-res" {
// framework-res.apk is installed as system/framework/framework-res.apk
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".apk", a.outputFile)
} else {
ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
}
}
var aaptIgnoreFilenames = []string{

View File

@ -29,8 +29,9 @@ import (
var (
signapk = pctx.AndroidStaticRule("signapk",
blueprint.RuleParams{
Command: `java -jar $signapkCmd $certificates $in $out`,
CommandDeps: []string{"$signapkCmd"},
Command: `${config.JavaCmd} -Djava.library.path=$$(dirname $signapkJniLibrary) ` +
`-jar $signapkCmd $certificates $in $out`,
CommandDeps: []string{"$signapkCmd", "$signapkJniLibrary"},
},
"certificates")
@ -48,6 +49,9 @@ func init() {
pctx.SourcePathVariable("androidManifestMergerCmd", "prebuilts/devtools/tools/lib/manifest-merger.jar")
pctx.HostBinToolVariable("aaptCmd", "aapt")
pctx.HostJavaToolVariable("signapkCmd", "signapk.jar")
// TODO(ccross): this should come from the signapk dependencies, but we don't have any way
// to express host JNI dependencies yet.
pctx.HostJNIToolVariable("signapkJniLibrary", "libconscrypt_openjdk_jni")
}
var combineApk = pctx.AndroidStaticRule("combineApk",
@ -79,6 +83,9 @@ func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath
certificateArgs = append(certificateArgs, c+".x509.pem", c+".pk8")
}
// TODO(ccross): sometimes uncompress dex
// TODO(ccross): sometimes strip dex
ctx.Build(pctx, android.BuildParams{
Rule: signapk,
Description: "signapk",

View File

@ -35,17 +35,7 @@ var (
)
func testApp(t *testing.T, bp string) *android.TestContext {
bp += `
android_app {
name: "framework-res",
no_framework_libs: true,
}
`
appFs := map[string][]byte{
"AndroidManifest.xml": nil,
"build/target/product/security/testkey": nil,
}
appFs := map[string][]byte{}
for _, file := range resourceFiles {
appFs[file] = nil

View File

@ -41,7 +41,6 @@ func init() {
android.RegisterModuleType("java_binary_host", BinaryHostFactory)
android.RegisterModuleType("java_import", ImportFactory)
android.RegisterModuleType("java_import_host", ImportFactoryHost)
android.RegisterModuleType("android_app", AndroidAppFactory)
android.RegisterSingletonType("logtags", LogtagsSingleton)
}
@ -206,6 +205,10 @@ type Module struct {
// installed file for binary dependency
installFile android.Path
// list of .java files and srcjars that was passed to javac
compiledJavaSrcs android.Paths
compiledSrcJars android.Paths
}
type Dependency interface {
@ -349,6 +352,9 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
} else if *j.deviceProperties.System_modules != "none" && ctx.Config().TargetOpenJDK9() {
ctx.AddDependency(ctx.Module(), systemModulesTag, *j.deviceProperties.System_modules)
}
if ctx.ModuleName() == "framework" {
ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
}
}
ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
@ -612,6 +618,10 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
}
}
// Store the list of .java files that was passed to javac
j.compiledJavaSrcs = uniqueSrcFiles
j.compiledSrcJars = srcJars
enable_sharding := false
if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {

View File

@ -97,6 +97,13 @@ func testJavaWithEnvFs(t *testing.T, bp string,
`, extra)
}
bp += `
android_app {
name: "framework-res",
no_framework_libs: true,
}
`
if config.TargetOpenJDK9() {
systemModules := []string{
"core-system-modules",
@ -134,6 +141,10 @@ func testJavaWithEnvFs(t *testing.T, bp string,
"prebuilts/sdk/system_current/framework.aidl": nil,
"prebuilts/sdk/test_current/android.jar": nil,
"prebuilts/sdk/test_current/framework.aidl": nil,
// For framework-res, which is an implicit dependency for framework
"AndroidManifest.xml": nil,
"build/target/product/security/testkey": nil,
}
for k, v := range fs {