Merge "Implement test config auto-gen for sh_test."
diff --git a/OWNERS b/OWNERS
index e1db459..adf2b4c 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,10 @@
-per-file * = asmundak@google.com,ccross@android.com,dwillemsen@google.com,jungjw@google.com,paulduffin@google.com
+per-file * = asmundak@google.com
+per-file * = ccross@android.com
+per-file * = dwillemsen@google.com
+per-file * = eakammer@google.com
+per-file * = jungjw@google.com
+per-file * = patricearruda@google.com
+per-file * = paulduffin@google.com
per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com
per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
diff --git a/android/neverallow.go b/android/neverallow.go
index 9e075b7..be3f712 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -187,6 +187,10 @@
// derive_sdk_prefer32 suppress the platform installation rules, but fails when
// the APEX modules contain the SDK variant and the platform variant still exists.
"frameworks/base/apex/sdkextensions/derive_sdk",
+ // These are for apps and shouldn't be used by non-SDK variant modules.
+ "prebuilts/ndk",
+ "tools/test/graphicsbenchmark/apps/sample_app",
+ "tools/test/graphicsbenchmark/functional_tests/java",
}
platformVariantPropertiesWhitelist := []string{
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 9321ad2..1b3a4ba 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -81,7 +81,7 @@
seenDataOutPaths := make(map[string]bool)
for _, fi := range a.filesInfo {
- if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
+ if ccMod, ok := fi.module.(*cc.Module); ok && ccMod.Properties.HideFromMake {
continue
}
@@ -178,7 +178,8 @@
if fi.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoReportClassesFile.String())
}
- if fi.class == javaSharedLib {
+ switch fi.class {
+ case javaSharedLib:
javaModule := fi.module.(java.Dependency)
// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore
// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
@@ -189,7 +190,7 @@
fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String())
fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
- } else if fi.class == app {
+ case app:
fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", fi.certificate.AndroidMkString())
// soong_app_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .apk Therefore
// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
@@ -199,19 +200,26 @@
fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", strings.Join(app.JniCoverageOutputs().Strings(), " "))
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk")
- } else if fi.class == nativeSharedLib || fi.class == nativeExecutable || fi.class == nativeTest {
+ case appSet:
+ as, ok := fi.module.(*java.AndroidAppSet)
+ if !ok {
+ panic(fmt.Sprintf("Expected %s to be AndroidAppSet", fi.module))
+ }
+ fmt.Fprintln(w, "LOCAL_APK_SET_MASTER_FILE :=", as.MasterFile())
+ fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
+ case nativeSharedLib, nativeExecutable, nativeTest:
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.Stem())
- if cc, ok := fi.module.(*cc.Module); ok {
- if cc.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String())
+ if ccMod, ok := fi.module.(*cc.Module); ok {
+ if ccMod.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", ccMod.UnstrippedOutputFile().String())
}
- cc.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
- if cc.CoverageOutputFile().Valid() {
- fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", cc.CoverageOutputFile().String())
+ ccMod.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
+ if ccMod.CoverageOutputFile().Valid() {
+ fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
}
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
- } else {
+ default:
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.Stem())
if fi.builtFile == a.manifestPbOut && apexType == flattenedApex {
if a.primaryApexType {
diff --git a/apex/apex.go b/apex/apex.go
index d3c5df0..2f7b2e5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1115,6 +1115,7 @@
javaSharedLib
nativeTest
app
+ appSet
)
func (class apexFileClass) NameInMake() string {
@@ -1129,7 +1130,7 @@
return "JAVA_LIBRARIES"
case nativeTest:
return "NATIVE_TESTS"
- case app:
+ case app, appSet:
// b/142537672 Why isn't this APP? We want to have full control over
// the paths and file names of the apk file under the flattend APEX.
// If this is set to APP, then the paths and file names are modified
@@ -1650,13 +1651,14 @@
}
type javaDependency interface {
- java.Dependency
+ DexJarBuildPath() android.Path
+ JacocoReportClassesFile() android.Path
Stem() string
}
func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, module android.Module) apexFile {
dirInApex := "javalib"
- fileToCopy := lib.DexJar()
+ fileToCopy := lib.DexJarBuildPath()
af := newApexFile(ctx, fileToCopy, module.Name(), dirInApex, javaSharedLib, module)
af.jacocoReportClassesFile = lib.JacocoReportClassesFile()
af.stem = lib.Stem() + ".jar"
@@ -1977,23 +1979,16 @@
ctx.PropertyErrorf("binaries", "%q is neither cc_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName)
}
case javaLibTag:
- if javaLib, ok := child.(*java.Library); ok {
- af := apexFileForJavaLibrary(ctx, javaLib, javaLib)
- if !af.Ok() {
- ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
- } else {
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- }
- } else if sdkLib, ok := child.(*java.SdkLibrary); ok {
- af := apexFileForJavaLibrary(ctx, sdkLib, sdkLib)
+ switch child.(type) {
+ case *java.Library, *java.SdkLibrary, *java.DexImport:
+ af := apexFileForJavaLibrary(ctx, child.(javaDependency), child.(android.Module))
if !af.Ok() {
ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
return false
}
filesInfo = append(filesInfo, af)
return true // track transitive dependencies
- } else {
+ default:
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
case androidAppTag:
@@ -2004,6 +1999,15 @@
filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
} else if ap, ok := child.(*java.AndroidTestHelperApp); ok {
filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
+ } else if ap, ok := child.(*java.AndroidAppSet); ok {
+ appDir := "app"
+ if ap.Privileged() {
+ appDir = "priv-app"
+ }
+ af := newApexFile(ctx, ap.OutputFile(), ap.Name(),
+ filepath.Join(appDir, ap.BaseModuleName()), appSet, ap)
+ af.certificate = java.PresignedCertificate
+ filesInfo = append(filesInfo, af)
} else {
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 779119c..d6a5d09 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -96,7 +96,7 @@
// - X86 (secondary)
// - Arm64 on X86_64 (native bridge)
// - Arm on X86 (native bridge)
-func withNativeBridgeEnabled(fs map[string][]byte, config android.Config) {
+func withNativeBridgeEnabled(_ map[string][]byte, config android.Config) {
config.Targets[android.Android] = []android.Target{
{Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}},
NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
@@ -115,15 +115,15 @@
}
}
-func withBinder32bit(fs map[string][]byte, config android.Config) {
+func withBinder32bit(_ map[string][]byte, config android.Config) {
config.TestProductVariables.Binder32bit = proptools.BoolPtr(true)
}
-func withUnbundledBuild(fs map[string][]byte, config android.Config) {
+func withUnbundledBuild(_ map[string][]byte, config android.Config) {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
}
-func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
+func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
android.ClearApexDependency()
bp = bp + `
@@ -187,6 +187,7 @@
"baz": nil,
"bar/baz": nil,
"testdata/baz": nil,
+ "AppSet.apks": nil,
}
cc.GatherRequiredFilesForTest(fs)
@@ -258,7 +259,7 @@
}
func tearDown() {
- os.RemoveAll(buildDir)
+ _ = os.RemoveAll(buildDir)
}
// ensure that 'result' equals 'expected'
@@ -294,6 +295,17 @@
}
}
+func ensureMatches(t *testing.T, result string, expectedRex string) {
+ ok, err := regexp.MatchString(expectedRex, result)
+ if err != nil {
+ t.Fatalf("regexp failure trying to match %s against `%s` expression: %s", result, expectedRex, err)
+ return
+ }
+ if !ok {
+ t.Errorf("%s does not match regular expession %s", result, expectedRex)
+ }
+}
+
func ensureListContains(t *testing.T, result []string, expected string) {
t.Helper()
if !android.InList(expected, result) {
@@ -329,7 +341,10 @@
binaries: ["foo",],
}
},
- java_libs: ["myjar"],
+ java_libs: [
+ "myjar",
+ "myjar_dex",
+ ],
}
apex {
@@ -438,6 +453,15 @@
],
}
+ dex_import {
+ name: "myjar_dex",
+ jars: ["prebuilt.jar"],
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
+
java_library {
name: "myotherjar",
srcs: ["foo/bar/MyClass.java"],
@@ -473,6 +497,7 @@
// Ensure that apex variant is created for the direct dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_myapex")
// Ensure that apex variant is created for the indirect dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
@@ -482,6 +507,7 @@
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
ensureContains(t, copyCmds, "image.apex/javalib/myjar_stem.jar")
+ ensureContains(t, copyCmds, "image.apex/javalib/myjar_dex.jar")
// .. but not for java libs
ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar")
ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar")
@@ -4758,6 +4784,38 @@
ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo/AppFoo.apk"}]}`)
}
+func TestAppSetBundle(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: ["AppSet"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ android_app_set {
+ name: "AppSet",
+ set: "AppSet.apks",
+ }`)
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ bundleConfigRule := mod.Description("Bundle Config")
+ content := bundleConfigRule.Args["content"]
+ ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
+ s := mod.Rule("apexRule").Args["copy_commands"]
+ copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
+ if len(copyCmds) != 3 {
+ t.Fatalf("Expected 3 commands, got %d in:\n%s", len(copyCmds), s)
+ }
+ ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet$")
+ ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet$")
+ ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet .*/AppSet.zip$")
+}
+
func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) {
t.Helper()
@@ -4917,7 +4975,7 @@
func TestNoUpdatableJarsInBootImage(t *testing.T) {
- var error string
+ var err string
var transform func(*dexpreopt.GlobalConfig)
t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
@@ -4928,35 +4986,35 @@
})
t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
- error = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image"
+ err = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image"
transform = func(config *dexpreopt.GlobalConfig) {
config.BootJars = []string{"com.android.art.something:some-art-lib"}
}
- testNoUpdatableJarsInBootImage(t, error, transform)
+ testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
- error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image"
+ err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image"
transform = func(config *dexpreopt.GlobalConfig) {
config.ArtApexJars = []string{"some-updatable-apex:some-updatable-apex-lib"}
}
- testNoUpdatableJarsInBootImage(t, error, transform)
+ testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
- error = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image"
+ err = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image"
transform = func(config *dexpreopt.GlobalConfig) {
config.ArtApexJars = []string{"some-non-updatable-apex:some-non-updatable-apex-lib"}
}
- testNoUpdatableJarsInBootImage(t, error, transform)
+ testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
- error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
+ err = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
transform = func(config *dexpreopt.GlobalConfig) {
config.BootJars = []string{"some-updatable-apex:some-updatable-apex-lib"}
}
- testNoUpdatableJarsInBootImage(t, error, transform)
+ testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
@@ -4967,27 +5025,27 @@
})
t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
- error = "failed to find a dex jar path for module 'nonexistent'"
+ err = "failed to find a dex jar path for module 'nonexistent'"
transform = func(config *dexpreopt.GlobalConfig) {
config.ArtApexJars = []string{"platform:nonexistent"}
}
- testNoUpdatableJarsInBootImage(t, error, transform)
+ testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) {
- error = "failed to find a dex jar path for module 'nonexistent'"
+ err = "failed to find a dex jar path for module 'nonexistent'"
transform = func(config *dexpreopt.GlobalConfig) {
config.BootJars = []string{"platform:nonexistent"}
}
- testNoUpdatableJarsInBootImage(t, error, transform)
+ testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("platform jar in the ART boot image => error", func(t *testing.T) {
- error = "module 'some-platform-lib' is not allowed in the ART boot image"
+ err = "module 'some-platform-lib' is not allowed in the ART boot image"
transform = func(config *dexpreopt.GlobalConfig) {
config.ArtApexJars = []string{"platform:some-platform-lib"}
}
- testNoUpdatableJarsInBootImage(t, error, transform)
+ testNoUpdatableJarsInBootImage(t, err, transform)
})
t.Run("platform jar in the framework boot image => ok", func(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 0108d06..17eac1a 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -69,11 +69,14 @@
// by default set to (uid/gid/mode) = (1000/1000/0644)
// TODO(b/113082813) make this configurable using config.fs syntax
generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
- Command: `echo '/ 1000 1000 0755' > ${out} && ` +
- `echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
- `echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 0 2000 0755"}' >> ${out}`,
- Description: "fs_config ${out}",
- }, "ro_paths", "exec_paths")
+ Command: `( echo '/ 1000 1000 0755' ` +
+ `&& for i in ${ro_paths}; do echo "/$$i 1000 1000 0644"; done ` +
+ `&& for i in ${exec_paths}; do echo "/$$i 0 2000 0755"; done ` +
+ `&& ( tr ' ' '\n' <${out}.apklist | for i in ${apk_paths}; do read apk; echo "/$$i 0 2000 0755"; zipinfo -1 $$apk | sed "s:\(.*\):/$$i/\1 1000 1000 0644:"; done ) ) > ${out}`,
+ Description: "fs_config ${out}",
+ Rspfile: "$out.apklist",
+ RspfileContent: "$in",
+ }, "ro_paths", "exec_paths", "apk_paths")
apexManifestRule = pctx.StaticRule("apexManifestRule", blueprint.RuleParams{
Command: `rm -f $out && ${jsonmodify} $in ` +
@@ -287,7 +290,7 @@
// collect the manifest names and paths of android apps
// if their manifest names are overridden
for _, fi := range a.filesInfo {
- if fi.class != app {
+ if fi.class != app && fi.class != appSet {
continue
}
packageName := fi.overriddenPackageName
@@ -337,13 +340,22 @@
var copyCommands []string
for _, fi := range a.filesInfo {
destPath := android.PathForModuleOut(ctx, "image"+suffix, fi.Path()).String()
- copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(destPath))
+ destPathDir := filepath.Dir(destPath)
+ if fi.class == appSet {
+ copyCommands = append(copyCommands, "rm -rf "+destPathDir)
+ }
+ copyCommands = append(copyCommands, "mkdir -p "+destPathDir)
if a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() {
// TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here
pathOnDevice := filepath.Join("/system", fi.Path())
copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
} else {
- copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+ if fi.class == appSet {
+ copyCommands = append(copyCommands,
+ fmt.Sprintf("unzip -q -d %s %s", destPathDir, fi.builtFile.String()))
+ } else {
+ copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+ }
implicitInputs = append(implicitInputs, fi.builtFile)
}
// create additional symlinks pointing the file inside the APEX
@@ -416,6 +428,8 @@
// files and dirs that will be created in APEX
var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
var executablePaths []string // this also includes dirs
+ var extractedAppSetPaths android.Paths
+ var extractedAppSetDirs []string
for _, f := range a.filesInfo {
pathInApex := f.Path()
if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
@@ -426,6 +440,9 @@
for _, s := range f.symlinks {
executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
}
+ } else if f.class == appSet {
+ extractedAppSetPaths = append(extractedAppSetPaths, f.builtFile)
+ extractedAppSetDirs = append(extractedAppSetDirs, f.installDir)
} else {
readOnlyPaths = append(readOnlyPaths, pathInApex)
}
@@ -446,9 +463,11 @@
Rule: generateFsConfig,
Output: cannedFsConfig,
Description: "generate fs config",
+ Inputs: extractedAppSetPaths,
Args: map[string]string{
"ro_paths": strings.Join(readOnlyPaths, " "),
"exec_paths": strings.Join(executablePaths, " "),
+ "apk_paths": strings.Join(extractedAppSetDirs, " "),
},
})
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 3ce1a89..52480ea 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -548,6 +548,25 @@
})
}
+func (c *vendorSnapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ entries.Class = "STATIC_LIBRARIES"
+
+ if c.androidMkVendorSuffix {
+ entries.SubName = vendorSuffix
+ } else {
+ entries.SubName = ""
+ }
+
+ entries.ExtraFooters = append(entries.ExtraFooters,
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ out := entries.OutputFile.Path()
+ varname := fmt.Sprintf("SOONG_%sOBJECT_%s%s", prefix, name, entries.SubName)
+
+ fmt.Fprintf(w, "\n%s := %s\n", varname, out.String())
+ fmt.Fprintln(w, ".KATI_READONLY: "+varname)
+ })
+}
+
func (c *ndkPrebuiltStlLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "SHARED_LIBRARIES"
}
diff --git a/cc/binary.go b/cc/binary.go
index 661264e..251b7f0 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -231,6 +231,10 @@
return binary.static()
}
+func (binary *binaryDecorator) binary() bool {
+ return true
+}
+
func (binary *binaryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
flags = binary.baseLinker.linkerFlags(ctx, flags)
diff --git a/cc/cc.go b/cc/cc.go
index 94512d5..8eabff5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -316,6 +316,8 @@
static() bool
staticBinary() bool
header() bool
+ binary() bool
+ object() bool
toolchain() config.Toolchain
canUseSdk() bool
useSdk() bool
@@ -1017,14 +1019,8 @@
}
func (c *Module) isSnapshotPrebuilt() bool {
- if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
- return true
- }
- if _, ok := c.linker.(*vendorSnapshotLibraryDecorator); ok {
- return true
- }
- if _, ok := c.linker.(*vendorSnapshotBinaryDecorator); ok {
- return true
+ if p, ok := c.linker.(interface{ isSnapshotPrebuilt() bool }); ok {
+ return p.isSnapshotPrebuilt()
}
return false
}
@@ -1129,6 +1125,14 @@
return ctx.mod.header()
}
+func (ctx *moduleContextImpl) binary() bool {
+ return ctx.mod.binary()
+}
+
+func (ctx *moduleContextImpl) object() bool {
+ return ctx.mod.object()
+}
+
func (ctx *moduleContextImpl) canUseSdk() bool {
return ctx.mod.canUseSdk()
}
@@ -1925,7 +1929,7 @@
if deps.StaticUnwinderIfLegacy {
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, staticUnwinderDepTag, staticUnwinder(actx))
+ }, staticUnwinderDepTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs))
}
for _, lib := range deps.LateStaticLibs {
@@ -2006,11 +2010,13 @@
actx.AddVariationDependencies(nil, objDepTag, deps.ObjFiles...)
+ vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
+
if deps.CrtBegin != "" {
- actx.AddVariationDependencies(nil, CrtBeginDepTag, deps.CrtBegin)
+ actx.AddVariationDependencies(nil, CrtBeginDepTag, rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
}
if deps.CrtEnd != "" {
- actx.AddVariationDependencies(nil, CrtEndDepTag, deps.CrtEnd)
+ actx.AddVariationDependencies(nil, CrtEndDepTag, rewriteSnapshotLibs(deps.CrtEnd, vendorSnapshotObjects))
}
if deps.LinkerFlagsFile != "" {
actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
@@ -2752,6 +2758,24 @@
return false
}
+func (c *Module) binary() bool {
+ if b, ok := c.linker.(interface {
+ binary() bool
+ }); ok {
+ return b.binary()
+ }
+ return false
+}
+
+func (c *Module) object() bool {
+ if o, ok := c.linker.(interface {
+ object() bool
+ }); ok {
+ return o.object()
+ }
+ return false
+}
+
func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
if c.UseVndk() {
if lib, ok := c.linker.(*llndkStubDecorator); ok {
@@ -3064,20 +3088,32 @@
// This will be available in /system, /vendor and /product
// or a /system directory that is available to vendor and product.
coreVariantNeeded = true
- vendorVariants = append(vendorVariants, platformVndkVersion)
- productVariants = append(productVariants, platformVndkVersion)
- // VNDK modules must not create BOARD_VNDK_VERSION variant because its
- // code is PLATFORM_VNDK_VERSION.
- // On the other hand, vendor_available modules which are not VNDK should
- // also build BOARD_VNDK_VERSION because it's installed in /vendor.
- // vendor_available modules are also available to /product.
- if !m.IsVndk() {
+
+ // We assume that modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
+ // PLATFORM_VNDK_VERSION.
+ if isVendorProprietaryPath(mctx.ModuleDir()) {
vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
+
+ // vendor_available modules are also available to /product.
+ productVariants = append(productVariants, platformVndkVersion)
+ // VNDK is always PLATFORM_VNDK_VERSION
+ if !m.IsVndk() {
productVariants = append(productVariants, productVndkVersion)
}
} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
// This will be available in /vendor (or /odm) only
- vendorVariants = append(vendorVariants, boardVndkVersion)
+ // We assume that modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
+ // PLATFORM_VNDK_VERSION.
+ if isVendorProprietaryPath(mctx.ModuleDir()) {
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
} else {
// This is either in /system (or similar: /data), or is a
// modules built with the NDK. Modules built with the NDK
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 67eb248..76b4e38 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -258,9 +258,7 @@
}
}
-func checkSnapshot(t *testing.T, ctx *android.TestContext, singletonName, moduleName, snapshotFilename, subDir, variant string) {
- snapshotSingleton := ctx.SingletonForTests(singletonName)
-
+func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
mod, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
if !ok {
t.Errorf("%q must have output\n", moduleName)
@@ -273,7 +271,7 @@
}
snapshotPath := filepath.Join(subDir, snapshotFilename)
- out := snapshotSingleton.Output(snapshotPath)
+ out := singleton.Output(snapshotPath)
if out.Input.String() != outputFiles[0].String() {
t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
}
@@ -398,16 +396,18 @@
variant := "android_vendor.VER_arm64_armv8-a_shared"
variant2nd := "android_vendor.VER_arm_armv7-a-neon_shared"
- checkSnapshot(t, ctx, "vndk-snapshot", "libvndk", "libvndk.so", vndkCoreLibPath, variant)
- checkSnapshot(t, ctx, "vndk-snapshot", "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
- checkSnapshot(t, ctx, "vndk-snapshot", "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
- checkSnapshot(t, ctx, "vndk-snapshot", "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
+ snapshotSingleton := ctx.SingletonForTests("vndk-snapshot")
+
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLibPath, variant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
snapshotConfigsPath := filepath.Join(snapshotVariantPath, "configs")
- checkSnapshot(t, ctx, "vndk-snapshot", "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, "vndk-snapshot", "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, "vndk-snapshot", "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, "vndk-snapshot", "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
"LLNDK: libc.so",
@@ -839,6 +839,17 @@
vendor_available: true,
nocrt: true,
}
+
+ toolchain_library {
+ name: "libb",
+ vendor_available: true,
+ src: "libb.a",
+ }
+
+ cc_object {
+ name: "obj",
+ vendor_available: true,
+ }
`
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -849,6 +860,9 @@
snapshotDir := "vendor-snapshot"
snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
+
+ var jsonFiles []string
for _, arch := range [][]string{
[]string{"arm64", "armv8-a"},
@@ -861,22 +875,51 @@
// For shared libraries, only non-VNDK vendor_available modules are captured
sharedVariant := fmt.Sprintf("android_vendor.VER_%s_%s_shared", archType, archVariant)
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- checkSnapshot(t, ctx, "vendor-snapshot", "libvendor", "libvendor.so", sharedDir, sharedVariant)
- checkSnapshot(t, ctx, "vendor-snapshot", "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(sharedDir, "libvendor.so.json"),
+ filepath.Join(sharedDir, "libvendor_available.so.json"))
// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- checkSnapshot(t, ctx, "vendor-snapshot", "libvndk", "libvndk.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, "vendor-snapshot", "libvendor", "libvendor.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, "vendor-snapshot", "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(staticDir, "libb.a.json"),
+ filepath.Join(staticDir, "libvndk.a.json"),
+ filepath.Join(staticDir, "libvendor.a.json"),
+ filepath.Join(staticDir, "libvendor_available.a.json"))
- // For binary libraries, all vendor:true and vendor_available modules are captured.
+ // For binary executables, all vendor:true and vendor_available modules are captured.
if archType == "arm64" {
binaryVariant := fmt.Sprintf("android_vendor.VER_%s_%s", archType, archVariant)
binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- checkSnapshot(t, ctx, "vendor-snapshot", "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
- checkSnapshot(t, ctx, "vendor-snapshot", "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(binaryDir, "vendor_bin.json"),
+ filepath.Join(binaryDir, "vendor_available_bin.json"))
+ }
+
+ // For header libraries, all vendor:true and vendor_available modules are captured.
+ headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
+ jsonFiles = append(jsonFiles, filepath.Join(headerDir, "libvendor_headers.json"))
+
+ // For object modules, all vendor:true and vendor_available modules are captured.
+ objectVariant := fmt.Sprintf("android_vendor.VER_%s_%s", archType, archVariant)
+ objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
+ checkSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
+ jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
+ }
+
+ for _, jsonFile := range jsonFiles {
+ // verify all json files exist
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("%q expected but not found", jsonFile)
}
}
}
diff --git a/cc/genrule.go b/cc/genrule.go
index 9331448..66d1784 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -79,8 +79,14 @@
var variants []string
if Bool(g.Vendor_available) || ctx.SocSpecific() || ctx.DeviceSpecific() {
- variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
- if vndkVersion := ctx.DeviceConfig().VndkVersion(); vndkVersion != "current" {
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ // If vndkVersion is current, we can always use PlatformVndkVersion.
+ // If not, we assume modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
+ // PLATFORM_VNDK_VERSION.
+ if vndkVersion == "current" || !isVendorProprietaryPath(ctx.ModuleDir()) {
+ variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
+ } else {
variants = append(variants, VendorVariationPrefix+vndkVersion)
}
}
diff --git a/cc/object.go b/cc/object.go
index 19decec..15a529e 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -158,3 +158,7 @@
func (object *objectLinker) coverageOutputFilePath() android.OptionalPath {
return android.OptionalPath{}
}
+
+func (object *objectLinker) object() bool {
+ return true
+}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index ac990f3..0751f1c 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -291,6 +291,10 @@
return nil
}
+func (p *prebuiltObjectLinker) object() bool {
+ return true
+}
+
func newPrebuiltObject() *Module {
module := newObject()
prebuilt := &prebuiltObjectLinker{
@@ -349,6 +353,10 @@
return nil
}
+func (p *prebuiltBinaryLinker) binary() bool {
+ return true
+}
+
// cc_prebuilt_binary installs a precompiled executable in srcs property in the
// device's directory.
func prebuiltBinaryFactory() android.Module {
diff --git a/cc/testing.go b/cc/testing.go
index be020c5..edbb24d 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -496,6 +496,7 @@
"my_include": nil,
"foo.map.txt": nil,
"liba.so": nil,
+ "libb.a": nil,
}
GatherRequiredFilesForTest(mockFS)
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 5801fc7..ea94544 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -30,6 +30,7 @@
vendorSnapshotSharedSuffix = ".vendor_shared."
vendorSnapshotStaticSuffix = ".vendor_static."
vendorSnapshotBinarySuffix = ".vendor_binary."
+ vendorSnapshotObjectSuffix = ".vendor_object."
)
var (
@@ -39,6 +40,7 @@
vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs")
vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs")
vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries")
+ vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects")
)
// vendor snapshot maps hold names of vendor snapshot modules per arch
@@ -72,6 +74,12 @@
}).(*snapshotMap)
}
+func vendorSnapshotObjects(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotObjectsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
type vendorSnapshotLibraryProperties struct {
// snapshot version.
Version string
@@ -185,6 +193,10 @@
return false
}
+func (p *vendorSnapshotLibraryDecorator) isSnapshotPrebuilt() bool {
+ return true
+}
+
func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
p.baseInstaller.install(ctx, file)
@@ -337,6 +349,10 @@
return outputFile
}
+func (p *vendorSnapshotBinaryDecorator) isSnapshotPrebuilt() bool {
+ return true
+}
+
func VendorSnapshotBinaryFactory() android.Module {
module, binary := NewBinary(android.DeviceSupported)
binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
@@ -364,12 +380,98 @@
return module.Init()
}
+type vendorSnapshotObjectProperties struct {
+ // snapshot version.
+ Version string
+
+ // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
+ Target_arch string
+
+ // Prebuilt file for each arch.
+ Src *string `android:"arch_variant"`
+}
+
+type vendorSnapshotObjectLinker struct {
+ objectLinker
+ properties vendorSnapshotObjectProperties
+ androidMkVendorSuffix bool
+}
+
+func (p *vendorSnapshotObjectLinker) Name(name string) string {
+ return name + p.NameSuffix()
+}
+
+func (p *vendorSnapshotObjectLinker) NameSuffix() string {
+ versionSuffix := p.version()
+ if p.arch() != "" {
+ versionSuffix += "." + p.arch()
+ }
+ return vendorSnapshotObjectSuffix + versionSuffix
+}
+
+func (p *vendorSnapshotObjectLinker) version() string {
+ return p.properties.Version
+}
+
+func (p *vendorSnapshotObjectLinker) arch() string {
+ return p.properties.Target_arch
+}
+
+func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
+ if config.DeviceArch() != p.arch() {
+ return false
+ }
+ if p.properties.Src == nil {
+ return false
+ }
+ return true
+}
+
+func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext,
+ flags Flags, deps PathDeps, objs Objects) android.Path {
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ return nil
+ }
+
+ m := ctx.Module().(*Module)
+ p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+
+ return android.PathForModuleSrc(ctx, *p.properties.Src)
+}
+
+func (p *vendorSnapshotObjectLinker) nativeCoverage() bool {
+ return false
+}
+
+func (p *vendorSnapshotObjectLinker) isSnapshotPrebuilt() bool {
+ return true
+}
+
+func VendorSnapshotObjectFactory() android.Module {
+ module := newObject()
+
+ prebuilt := &vendorSnapshotObjectLinker{
+ objectLinker: objectLinker{
+ baseLinker: NewBaseLinker(nil),
+ },
+ }
+ module.linker = prebuilt
+
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ vendorSnapshotLoadHook(ctx, prebuilt)
+ })
+
+ module.AddProperties(&prebuilt.properties)
+ return module.Init()
+}
+
func init() {
android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
+ android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
}
func VendorSnapshotSingleton() android.Singleton {
@@ -429,7 +531,7 @@
// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
// image and newer system image altogether.
func isVendorSnapshotModule(m *Module, moduleDir string) bool {
- if !m.Enabled() {
+ if !m.Enabled() || m.Properties.HideFromMake {
return false
}
// skip proprietary modules, but include all VNDK (static)
@@ -443,37 +545,37 @@
return false
}
// the module must be installed in /vendor
- if !m.installable() || m.isSnapshotPrebuilt() || !m.inVendor() {
- return false
- }
- // exclude test modules
- if _, ok := m.linker.(interface{ gtest() bool }); ok {
- return false
- }
- // TODO(b/65377115): add full support for sanitizer
- if m.sanitize != nil && !m.sanitize.isUnsanitizedVariant() {
+ if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
return false
}
// Libraries
if l, ok := m.linker.(snapshotLibraryInterface); ok {
+ // TODO(b/65377115): add full support for sanitizer
+ if m.sanitize != nil {
+ // cfi, scs and hwasan export both sanitized and unsanitized variants for static and header
+ // Always use unsanitized variants of them.
+ for _, t := range []sanitizerType{cfi, scs, hwasan} {
+ if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
+ return false
+ }
+ }
+ }
if l.static() {
- return proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
+ return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
}
if l.shared() {
- return !m.IsVndk()
+ return m.outputFile.Valid() && !m.IsVndk()
}
return true
}
- // Binaries
- _, ok := m.linker.(*binaryDecorator)
- if !ok {
- if _, ok := m.linker.(*prebuiltBinaryLinker); !ok {
- return false
- }
+ // Binaries and Objects
+ if m.binary() || m.object() {
+ return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
}
- return proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
+
+ return false
}
func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
@@ -496,6 +598,8 @@
(header only libraries)
binary/
(executable binaries)
+ object/
+ (.o object files)
arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
shared/
(.so shared libraries)
@@ -505,6 +609,8 @@
(header only libraries)
binary/
(executable binaries)
+ object/
+ (.o object files)
NOTICE_FILES/
(notice files, e.g. libbase.txt)
configs/
@@ -620,7 +726,7 @@
}
propOut = filepath.Join(snapshotArchDir, targetArch, libType, stem+".json")
- } else {
+ } else if m.binary() {
// binary flags
prop.Symlinks = m.Symlinks()
prop.SharedLibs = m.Properties.SnapshotSharedLibs
@@ -630,6 +736,17 @@
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
propOut = snapshotBinOut + ".json"
+ } else if m.object() {
+ // object files aren't installed to the device, so their names can conflict.
+ // Use module name as stem.
+ objPath := m.outputFile.Path()
+ snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
+ ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
+ ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
+ propOut = snapshotObjOut + ".json"
+ } else {
+ ctx.Errorf("unknown module %q in vendor snapshot", m.String())
+ return nil
}
j, err := json.Marshal(prop)
@@ -716,6 +833,7 @@
var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil)
var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil)
+var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil)
// gathers all snapshot modules for vendor, and disable unnecessary snapshots
// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
@@ -731,12 +849,12 @@
return
}
- snapshot, ok := module.linker.(snapshotInterface)
- if !ok {
+ if !module.isSnapshotPrebuilt() {
return
}
- if !snapshot.matchesWithDevice(ctx.DeviceConfig()) {
+ // isSnapshotPrebuilt ensures snapshotInterface
+ if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) {
// Disable unnecessary snapshot module, but do not disable
// vndk_prebuilt_shared because they might be packed into vndk APEX
if !module.IsVndk() {
@@ -758,6 +876,8 @@
}
} else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok {
snapshotMap = vendorSnapshotBinaries(ctx.Config())
+ } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok {
+ snapshotMap = vendorSnapshotObjects(ctx.Config())
} else {
return
}
@@ -804,6 +924,11 @@
return
}
+ // .. and also filter out llndk library
+ if module.isLlndk(ctx.Config()) {
+ return
+ }
+
var snapshotMap *snapshotMap
if lib, ok := module.linker.(libraryInterface); ok {
@@ -815,10 +940,10 @@
// header
snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
}
- } else if _, ok := module.linker.(*binaryDecorator); ok {
+ } else if module.binary() {
snapshotMap = vendorSnapshotBinaries(ctx.Config())
- } else if _, ok := module.linker.(*prebuiltBinaryLinker); ok {
- snapshotMap = vendorSnapshotBinaries(ctx.Config())
+ } else if module.object() {
+ snapshotMap = vendorSnapshotObjects(ctx.Config())
} else {
return
}
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 53b5181..5a44c46 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -186,6 +186,10 @@
return false
}
+func (p *vndkPrebuiltLibraryDecorator) isSnapshotPrebuilt() bool {
+ return true
+}
+
func (p *vndkPrebuiltLibraryDecorator) install(ctx ModuleContext, file android.Path) {
arches := ctx.DeviceConfig().Arches()
if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 98850e5..3440f8e 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -50,6 +50,8 @@
UpdatableSystemServerJars []string // jars within apex that are loaded into system server
SpeedApps []string // apps that should be speed optimized
+ BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error
+
PreoptFlags []string // global dex2oat flags that should be used if no module-specific dex2oat flags are specified
DefaultCompilerFilter string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags
@@ -98,6 +100,15 @@
ConstructContext android.Path
}
+// LibraryPath contains paths to the library DEX jar on host and on device.
+type LibraryPath struct {
+ Host android.Path
+ Device string
+}
+
+// LibraryPaths is a map from library name to on-host and on-device paths to its DEX jar.
+type LibraryPaths map[string]*LibraryPath
+
type ModuleConfig struct {
Name string
DexLocation string // dex location on device
@@ -115,7 +126,7 @@
EnforceUsesLibraries bool
PresentOptionalUsesLibraries []string
UsesLibraries []string
- LibraryPaths map[string]android.Path
+ LibraryPaths LibraryPaths
Archs []android.ArchType
DexPreoptImages []android.Path
@@ -163,14 +174,6 @@
return ret
}
-func constructPathMap(ctx android.PathContext, paths map[string]string) map[string]android.Path {
- ret := map[string]android.Path{}
- for key, path := range paths {
- ret[key] = constructPath(ctx, path)
- }
- return ret
-}
-
func constructWritablePath(ctx android.PathContext, path string) android.WritablePath {
if path == "" {
return nil
@@ -262,6 +265,13 @@
// from Make to read the module dexpreopt.config written in the Make config
// stage.
func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) {
+ type jsonLibraryPath struct {
+ Host string
+ Device string
+ }
+
+ type jsonLibraryPaths map[string]jsonLibraryPath
+
type ModuleJSONConfig struct {
*ModuleConfig
@@ -271,12 +281,24 @@
DexPath string
ManifestPath string
ProfileClassListing string
- LibraryPaths map[string]string
+ LibraryPaths jsonLibraryPaths
DexPreoptImages []string
DexPreoptImageLocations []string
PreoptBootClassPathDexFiles []string
}
+ // convert JSON map of library paths to LibraryPaths
+ constructLibraryPaths := func(ctx android.PathContext, paths jsonLibraryPaths) LibraryPaths {
+ m := LibraryPaths{}
+ for lib, path := range paths {
+ m[lib] = &LibraryPath{
+ constructPath(ctx, path.Host),
+ path.Device,
+ }
+ }
+ return m
+ }
+
config := ModuleJSONConfig{}
err := json.Unmarshal(data, &config)
@@ -289,7 +311,7 @@
config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
config.ModuleConfig.ManifestPath = constructPath(ctx, config.ManifestPath)
config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
- config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths)
+ config.ModuleConfig.LibraryPaths = constructLibraryPaths(ctx, config.LibraryPaths)
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 5275e8f..57a9250 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -229,8 +229,9 @@
func (m classLoaderContextMap) addLibs(sdkVer int, module *ModuleConfig, libs ...string) {
clc := m.getValue(sdkVer)
for _, lib := range libs {
- clc.Host = append(clc.Host, pathForLibrary(module, lib))
- clc.Target = append(clc.Target, filepath.Join("/system/framework", lib+".jar"))
+ p := pathForLibrary(module, lib)
+ clc.Host = append(clc.Host, p.Host)
+ clc.Target = append(clc.Target, p.Device)
}
}
@@ -314,6 +315,8 @@
dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
rule.Command().Text("cp -f").Input(module.DexPath).Output(dexPathHost)
+
+ checkSystemServerOrder(ctx, jarIndex)
} else {
// Pass special class loader context to skip the classpath and collision check.
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
@@ -555,7 +558,7 @@
return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
}
-func pathForLibrary(module *ModuleConfig, lib string) android.Path {
+func pathForLibrary(module *ModuleConfig, lib string) *LibraryPath {
path, ok := module.LibraryPaths[lib]
if !ok {
panic(fmt.Errorf("unknown library path for %q", lib))
@@ -607,6 +610,29 @@
}
}
+// Check the order of jars on the system server classpath and give a warning/error if a jar precedes
+// one of its dependencies. This is not an error, but a missed optimization, as dexpreopt won't
+// have the dependency jar in the class loader context, and it won't be able to resolve any
+// references to its classes and methods.
+func checkSystemServerOrder(ctx android.PathContext, jarIndex int) {
+ mctx, isModule := ctx.(android.ModuleContext)
+ if isModule {
+ config := GetGlobalConfig(ctx)
+ jars := NonUpdatableSystemServerJars(ctx, config)
+ mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+ depIndex := android.IndexList(dep.Name(), jars)
+ if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars {
+ jar := jars[jarIndex]
+ dep := jars[depIndex]
+ mctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+
+ " '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+
+ " references from '%s' to '%s'.\n", jar, dep, jar, dep)
+ }
+ return true
+ })
+ }
+}
+
func contains(l []string, s string) bool {
for _, e := range l {
if e == s {
diff --git a/java/aar.go b/java/aar.go
index c8daf83..7413c80 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -730,7 +730,7 @@
return android.Paths{a.classpathFile}
}
-func (a *AARImport) DexJar() android.Path {
+func (a *AARImport) DexJarBuildPath() android.Path {
return nil
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 6eb22fd..62cf169 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -69,7 +69,26 @@
if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
hideFromMake = true
}
- if !hideFromMake {
+ if hideFromMake {
+ // May still need to add some additional dependencies. This will be called
+ // once for the platform variant (even if it is not being used) and once each
+ // for the APEX specific variants. In order to avoid adding the dependency
+ // multiple times only add it for the platform variant.
+ checkedModulePaths := library.additionalCheckedModules
+ if library.IsForPlatform() && len(checkedModulePaths) != 0 {
+ mainEntries = android.AndroidMkEntries{
+ Class: "FAKE",
+ // Need at least one output file in order for this to take effect.
+ OutputFile: android.OptionalPathForPath(checkedModulePaths[0]),
+ Include: "$(BUILD_PHONY_PACKAGE)",
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", checkedModulePaths.Strings()...)
+ },
+ },
+ }
+ }
+ } else {
mainEntries = android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
DistFile: android.OptionalPathForPath(library.distFile),
@@ -104,6 +123,10 @@
entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs...)
+ if len(library.additionalCheckedModules) != 0 {
+ entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
+ }
+
if library.proguardDictionary != nil {
entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
}
diff --git a/java/app.go b/java/app.go
index a45ab6f..24dde79 100755
--- a/java/app.go
+++ b/java/app.go
@@ -28,6 +28,7 @@
"android/soong/android"
"android/soong/cc"
+ "android/soong/dexpreopt"
"android/soong/tradefed"
)
@@ -96,6 +97,14 @@
return Bool(as.properties.Privileged)
}
+func (as *AndroidAppSet) OutputFile() android.Path {
+ return as.packedOutput
+}
+
+func (as *AndroidAppSet) MasterFile() string {
+ return as.masterFile
+}
+
var TargetCpuAbi = map[string]string{
"arm": "ARMEABI_V7A",
"arm64": "ARM64_V8A",
@@ -120,7 +129,7 @@
}
func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- as.packedOutput = android.PathForModuleOut(ctx, "extracted.zip")
+ as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
// We are assuming here that the master file in the APK
// set has `.apk` suffix. If it doesn't the build will fail.
// APK sets containing APEX files are handled elsewhere.
@@ -145,26 +154,17 @@
"stem": ctx.ModuleName(),
},
})
- // TODO(asmundak): add this (it's wrong now, will cause copying extracted.zip)
- /*
- var installDir android.InstallPath
- if Bool(as.properties.Privileged) {
- installDir = android.PathForModuleInstall(ctx, "priv-app", as.BaseModuleName())
- } else if ctx.InstallInTestcases() {
- installDir = android.PathForModuleInstall(ctx, as.BaseModuleName(), ctx.DeviceConfig().DeviceArch())
- } else {
- installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName())
- }
- ctx.InstallFile(installDir, as.masterFile", as.packedOutput)
- */
}
// android_app_set extracts a set of APKs based on the target device
// configuration and installs this set as "split APKs".
-// The set will always contain `base-master.apk` and every APK built
-// to the target device. All density-specific APK will be included, too,
-// unless PRODUCT_APPT_PREBUILT_DPI is defined (should contain comma-sepearated
-// list of density names (LDPI, MDPI, HDPI, etc.)
+// The extracted set always contains 'master' APK whose name is
+// _module_name_.apk and every split APK matching target device.
+// The extraction of the density-specific splits depends on
+// PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should
+// be a list density names: LDPI, MDPI, HDPI, etc.), only listed
+// splits will be extracted. Otherwise all density-specific splits
+// will be extracted.
func AndroidApkSetFactory() android.Module {
module := &AndroidAppSet{}
module.AddProperties(&module.properties)
@@ -335,7 +335,7 @@
presigned bool
}
-var presignedCertificate = Certificate{presigned: true}
+var PresignedCertificate = Certificate{presigned: true}
func (c Certificate) AndroidMkString() string {
if c.presigned {
@@ -445,8 +445,11 @@
return
}
dep, _ := m.(*cc.Module)
- jniSdkVersion, err := android.ApiStrToNum(ctx, dep.SdkVersion())
- if err != nil || int(minSdkVersion) < jniSdkVersion {
+ // The domain of cc.sdk_version is "current" and <number>
+ // We can rely on sdkSpec to convert it to <number> so that "current" is handled
+ // properly regardless of sdk finalization.
+ jniSdkVersion, err := sdkSpecFrom(dep.SdkVersion()).effectiveVersion(ctx)
+ if err != nil || minSdkVersion < jniSdkVersion {
ctx.OtherModuleErrorf(dep, "sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)",
dep.SdkVersion(), minSdkVersion, ctx.ModuleName())
return
@@ -1186,7 +1189,7 @@
android.OverrideModuleBase
}
-func (i *OverrideAndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (i *OverrideAndroidApp) GenerateAndroidBuildActions(_ android.ModuleContext) {
// All the overrides happen in the base module.
// TODO(jungjw): Check the base module type.
}
@@ -1207,7 +1210,7 @@
android.OverrideModuleBase
}
-func (i *OverrideAndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (i *OverrideAndroidTest) GenerateAndroidBuildActions(_ android.ModuleContext) {
// All the overrides happen in the base module.
// TODO(jungjw): Check the base module type.
}
@@ -1229,7 +1232,7 @@
android.OverrideModuleBase
}
-func (i *OverrideRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (i *OverrideRuntimeResourceOverlay) GenerateAndroidBuildActions(_ android.ModuleContext) {
// All the overrides happen in the base module.
// TODO(jungjw): Check the base module type.
}
@@ -1474,7 +1477,7 @@
// Sign or align the package if package has not been preprocessed
if a.preprocessed {
a.outputFile = srcApk
- a.certificate = presignedCertificate
+ a.certificate = PresignedCertificate
} else if !Bool(a.properties.Presigned) {
// If the certificate property is empty at this point, default_dev_cert must be set to true.
// Which makes processMainCert's behavior for the empty cert string WAI.
@@ -1494,7 +1497,7 @@
alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
TransformZipAlign(ctx, alignedApk, dexOutput)
a.outputFile = alignedApk
- a.certificate = presignedCertificate
+ a.certificate = PresignedCertificate
}
// TODO: Optionally compress the output apk.
@@ -1552,7 +1555,7 @@
return Bool(a.properties.Privileged)
}
-func (a *AndroidAppImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+func (a *AndroidAppImport) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
// android_app_import might have extra dependencies via uses_libs property.
// Don't track the dependency as we don't automatically add those libraries
// to the classpath. It should be explicitly added to java_libs property of APEX
@@ -1875,24 +1878,30 @@
return optionalUsesLibs
}
-// usesLibraryPaths returns a map of module names of shared library dependencies to the paths to their dex jars.
-func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) map[string]android.Path {
- usesLibPaths := make(map[string]android.Path)
+// usesLibraryPaths returns a map of module names of shared library dependencies to the paths
+// to their dex jars on host and on device.
+func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) dexpreopt.LibraryPaths {
+ usesLibPaths := make(dexpreopt.LibraryPaths)
if !ctx.Config().UnbundledBuild() {
ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
+ dep := ctx.OtherModuleName(m)
if lib, ok := m.(Dependency); ok {
- if dexJar := lib.DexJar(); dexJar != nil {
- usesLibPaths[ctx.OtherModuleName(m)] = dexJar
+ if dexJar := lib.DexJarBuildPath(); dexJar != nil {
+ usesLibPaths[dep] = &dexpreopt.LibraryPath{
+ dexJar,
+ // TODO(b/132357300): propagate actual install paths here.
+ filepath.Join("/system/framework", dep+".jar"),
+ }
} else {
- ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must produce a dex jar, does it have installable: true?",
- ctx.OtherModuleName(m))
+ ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must"+
+ " produce a dex jar, does it have installable: true?", dep)
}
} else if ctx.Config().AllowMissingDependencies() {
- ctx.AddMissingDependencies([]string{ctx.OtherModuleName(m)})
+ ctx.AddMissingDependencies([]string{dep})
} else {
- ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library",
- ctx.OtherModuleName(m))
+ ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be "+
+ "a java library", dep)
}
})
}
diff --git a/java/app_test.go b/java/app_test.go
index eb583be..eeba161 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -149,7 +149,7 @@
prerelease: true,
}`)
module := ctx.ModuleForTests("foo", "android_common")
- const packedSplitApks = "extracted.zip"
+ const packedSplitApks = "foo.zip"
params := module.Output(packedSplitApks)
if params.Rule == nil {
t.Errorf("expected output %s is missing", packedSplitApks)
@@ -218,7 +218,7 @@
ctx := testContext()
run(t, ctx, config)
module := ctx.ModuleForTests("foo", "android_common")
- const packedSplitApks = "extracted.zip"
+ const packedSplitApks = "foo.zip"
params := module.Output(packedSplitApks)
for k, v := range test.expected {
if actual := params.Args[k]; actual != v {
diff --git a/java/builder.go b/java/builder.go
index 640dba9..a27e5c3 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -206,7 +206,7 @@
blueprint.RuleParams{
Command: "rm -f $out && " +
"${config.PackageCheckCmd} $in $packages && " +
- "cp $in $out",
+ "touch $out",
CommandDeps: []string{"${config.PackageCheckCmd}"},
},
"packages")
@@ -547,9 +547,8 @@
})
}
-func CheckJarPackages(ctx android.ModuleContext, classesJar android.Path, permittedPackages []string) android.ModuleOutPath {
- outputFile := android.PathForModuleOut(ctx, "package-check", classesJar.Base())
-
+func CheckJarPackages(ctx android.ModuleContext, outputFile android.WritablePath,
+ classesJar android.Path, permittedPackages []string) {
ctx.Build(pctx, android.BuildParams{
Rule: packageCheck,
Description: "packageCheck",
@@ -559,8 +558,6 @@
"packages": strings.Join(permittedPackages, " "),
},
})
-
- return outputFile
}
func TransformJetifier(ctx android.ModuleContext, outputFile android.WritablePath,
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index b40ab93..1ffb13f 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -150,7 +150,7 @@
return d.implementationAndResourceJars
}
-func (d *DeviceHostConverter) DexJar() android.Path {
+func (d *DeviceHostConverter) DexJarBuildPath() android.Path {
return nil
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 4725b07..2911fd9 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -37,7 +37,7 @@
usesLibs []string
optionalUsesLibs []string
enforceUsesLibs bool
- libraryPaths map[string]android.Path
+ libraryPaths dexpreopt.LibraryPaths
builtInstalled string
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index ed61d4b..9d93838 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -255,7 +255,7 @@
return -1, nil
}
- jar, hasJar := module.(interface{ DexJar() android.Path })
+ jar, hasJar := module.(interface{ DexJarBuildPath() android.Path })
if !hasJar {
return -1, nil
}
@@ -296,7 +296,7 @@
panic("unknown boot image: " + image.name)
}
- return index, jar.DexJar()
+ return index, jar.DexJarBuildPath()
}
// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
diff --git a/java/droiddoc.go b/java/droiddoc.go
index b16c9cd..d61c62c 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1334,13 +1334,10 @@
d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
cmd.FlagWithOutput("--extract-annotations ", d.annotationsZip)
- if len(d.properties.Merge_annotations_dirs) == 0 {
- ctx.PropertyErrorf("merge_annotations_dirs",
- "has to be non-empty if annotations was enabled!")
+ if len(d.properties.Merge_annotations_dirs) != 0 {
+ d.mergeAnnoDirFlags(ctx, cmd)
}
- d.mergeAnnoDirFlags(ctx, cmd)
-
// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
FlagWithArg("--hide ", "SuperfluousPrefix").
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index c7f7cbd..2f35798 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -147,7 +147,7 @@
name := ctx.ModuleName(module)
for moduleList, pathList := range moduleListToPathList {
if i := android.IndexList(name, *moduleList); i != -1 {
- pathList[i] = j.DexJar()
+ pathList[i] = j.DexJarBuildPath()
}
}
}
diff --git a/java/java.go b/java/java.go
index 09df2ad..0ba1f5a 100644
--- a/java/java.go
+++ b/java/java.go
@@ -463,6 +463,9 @@
// expanded Jarjar_rules
expandJarjarRules android.Path
+ // list of additional targets for checkbuild
+ additionalCheckedModules android.Paths
+
// Extra files generated by the module type to be added as java resources.
extraResources android.Paths
@@ -498,7 +501,7 @@
ImplementationJars() android.Paths
ResourceJars() android.Paths
ImplementationAndResourcesJars() android.Paths
- DexJar() android.Path
+ DexJarBuildPath() android.Path
AidlIncludeDirs() android.Paths
ExportedSdkLibs() []string
ExportedPlugins() (android.Paths, []string)
@@ -833,41 +836,46 @@
}
func (m *Module) getLinkType(name string) (ret linkType, stubs bool) {
- ver := m.sdkVersion()
- switch {
- case name == "core.current.stubs" || name == "core.platform.api.stubs" ||
- name == "stub-annotations" || name == "private-stub-annotations-jar" ||
- name == "core-lambda-stubs" || name == "core-generated-annotation-stubs":
+ switch name {
+ case "core.current.stubs", "core.platform.api.stubs", "stub-annotations",
+ "private-stub-annotations-jar", "core-lambda-stubs", "core-generated-annotation-stubs":
return javaCore, true
- case ver.kind == sdkCore:
- return javaCore, false
- case name == "android_system_stubs_current":
- return javaSystem, true
- case ver.kind == sdkSystem:
- return javaSystem, false
- case name == "android_test_stubs_current":
- return javaSystem, true
- case ver.kind == sdkTest:
- return javaPlatform, false
- case name == "android_stubs_current":
+ case "android_stubs_current":
return javaSdk, true
- case ver.kind == sdkPublic:
- return javaSdk, false
- case name == "android_module_lib_stubs_current":
+ case "android_system_stubs_current":
+ return javaSystem, true
+ case "android_module_lib_stubs_current":
return javaModule, true
- case ver.kind == sdkModule:
- return javaModule, false
- case name == "android_system_server_stubs_current":
+ case "android_system_server_stubs_current":
return javaSystemServer, true
- case ver.kind == sdkSystemServer:
- return javaSystemServer, false
- case ver.kind == sdkPrivate || ver.kind == sdkNone || ver.kind == sdkCorePlatform:
- return javaPlatform, false
- case !ver.valid():
- panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
- default:
- return javaSdk, false
+ case "android_test_stubs_current":
+ return javaSystem, true
}
+
+ if stub, linkType := moduleStubLinkType(name); stub {
+ return linkType, true
+ }
+
+ ver := m.sdkVersion()
+ switch ver.kind {
+ case sdkCore:
+ return javaCore, false
+ case sdkSystem:
+ return javaSystem, false
+ case sdkPublic:
+ return javaSdk, false
+ case sdkModule:
+ return javaModule, false
+ case sdkSystemServer:
+ return javaSystemServer, false
+ case sdkPrivate, sdkNone, sdkCorePlatform, sdkTest:
+ return javaPlatform, false
+ }
+
+ if !ver.valid() {
+ panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
+ }
+ return javaSdk, false
}
func checkLinkType(ctx android.ModuleContext, from *Module, to linkTypeContext, tag dependencyTag) {
@@ -1518,10 +1526,10 @@
// Check package restrictions if necessary.
if len(j.properties.Permitted_packages) > 0 {
- // Check packages and copy input to package-checked file.
- // Use the file copied after a successful package check as the output file for this
- // module so that any dependencies on this module will trigger the package check.
- outputFile = CheckJarPackages(ctx, outputFile, j.properties.Permitted_packages)
+ // Check packages and copy to package-checked file.
+ pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp")
+ CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages)
+ j.additionalCheckedModules = append(j.additionalCheckedModules, pkgckFile)
if ctx.Failed() {
return
@@ -1736,7 +1744,7 @@
return android.Paths{j.implementationJarFile}
}
-func (j *Module) DexJar() android.Path {
+func (j *Module) DexJarBuildPath() android.Path {
return j.dexJarFile
}
@@ -2562,7 +2570,7 @@
return android.Paths{j.combinedClasspathFile}
}
-func (j *Import) DexJar() android.Path {
+func (j *Import) DexJarBuildPath() android.Path {
return nil
}
@@ -2688,6 +2696,10 @@
return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
}
+func (a *DexImport) JacocoReportClassesFile() android.Path {
+ return nil
+}
+
func (j *DexImport) IsInstallable() bool {
return true
}
@@ -2745,7 +2757,7 @@
j.Stem()+".jar", dexOutputFile)
}
-func (j *DexImport) DexJar() android.Path {
+func (j *DexImport) DexJarBuildPath() android.Path {
return j.dexJarFile
}
diff --git a/java/sdk.go b/java/sdk.go
index 9310f78..2a08f32 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -35,6 +35,7 @@
var sdkVersionsKey = android.NewOnceKey("sdkVersionsKey")
var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey")
+var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey")
var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey")
type sdkContext interface {
@@ -447,7 +448,7 @@
return toModule([]string{"core.current.stubs"}, "", nil)
case sdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
+ return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", nonUpdatableFrameworkAidlPath(ctx))
case sdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
return toModule([]string{"android_system_server_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
@@ -506,6 +507,7 @@
}
createSdkFrameworkAidl(ctx)
+ createNonUpdatableFrameworkAidl(ctx)
createAPIFingerprint(ctx)
}
@@ -517,6 +519,31 @@
"android_system_stubs_current",
}
+ combinedAidl := sdkFrameworkAidlPath(ctx)
+ tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
+
+ rule := createFrameworkAidl(stubsModules, tempPath, ctx)
+
+ commitChangeForRestat(rule, tempPath, combinedAidl)
+
+ rule.Build(pctx, ctx, "framework_aidl", "generate framework.aidl")
+}
+
+// Creates a version of framework.aidl for the non-updatable part of the platform.
+func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) {
+ stubsModules := []string{"android_module_lib_stubs_current"}
+
+ combinedAidl := nonUpdatableFrameworkAidlPath(ctx)
+ tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
+
+ rule := createFrameworkAidl(stubsModules, tempPath, ctx)
+
+ commitChangeForRestat(rule, tempPath, combinedAidl)
+
+ rule.Build(pctx, ctx, "framework_non_updatable_aidl", "generate framework_non_updatable.aidl")
+}
+
+func createFrameworkAidl(stubsModules []string, path android.OutputPath, ctx android.SingletonContext) *android.RuleBuilder {
stubsJars := make([]android.Paths, len(stubsModules))
ctx.VisitAllModules(func(module android.Module) {
@@ -536,8 +563,7 @@
if ctx.Config().AllowMissingDependencies() {
missingDeps = append(missingDeps, stubsModules[i])
} else {
- ctx.Errorf("failed to find dex jar path for module %q",
- stubsModules[i])
+ ctx.Errorf("failed to find dex jar path for module %q", stubsModules[i])
}
}
}
@@ -561,20 +587,15 @@
}
}
- combinedAidl := sdkFrameworkAidlPath(ctx)
- tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
-
rule.Command().
- Text("rm -f").Output(tempPath)
+ Text("rm -f").Output(path)
rule.Command().
Text("cat").
Inputs(aidls).
Text("| sort -u >").
- Output(tempPath)
+ Output(path)
- commitChangeForRestat(rule, tempPath, combinedAidl)
-
- rule.Build(pctx, ctx, "framework_aidl", "generate framework.aidl")
+ return rule
}
func sdkFrameworkAidlPath(ctx android.PathContext) android.OutputPath {
@@ -583,6 +604,12 @@
}).(android.OutputPath)
}
+func nonUpdatableFrameworkAidlPath(ctx android.PathContext) android.OutputPath {
+ return ctx.Config().Once(nonUpdatableFrameworkAidlPathKey, func() interface{} {
+ return android.PathForOutput(ctx, "framework_non_updatable.aidl")
+ }).(android.OutputPath)
+}
+
// Create api_fingerprint.txt
func createAPIFingerprint(ctx android.SingletonContext) {
out := ApiFingerprintPath(ctx)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 67b0bd6..de5ee03 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1113,7 +1113,9 @@
props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
- props.Java_version = module.properties.Java_version
+ // We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
+ // interop with older developer tools that don't support 1.9.
+ props.Java_version = proptools.StringPtr("1.8")
if module.deviceProperties.Compile_dex != nil {
props.Compile_dex = module.deviceProperties.Compile_dex
}
@@ -1575,6 +1577,24 @@
var _ sdkLibraryComponentNamingScheme = (*frameworkModulesNamingScheme)(nil)
+func moduleStubLinkType(name string) (stub bool, ret linkType) {
+ // This suffix-based approach is fragile and could potentially mis-trigger.
+ // TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly.
+ if strings.HasSuffix(name, ".stubs.public") || strings.HasSuffix(name, "-stubs-publicapi") {
+ return true, javaSdk
+ }
+ if strings.HasSuffix(name, ".stubs.system") || strings.HasSuffix(name, "-stubs-systemapi") {
+ return true, javaSystem
+ }
+ if strings.HasSuffix(name, ".stubs.module_lib") || strings.HasSuffix(name, "-stubs-module_libs_api") {
+ return true, javaModule
+ }
+ if strings.HasSuffix(name, ".stubs.test") {
+ return true, javaSystem
+ }
+ return false, javaPlatform
+}
+
// java_sdk_library is a special Java library that provides optional platform APIs to apps.
// In practice, it can be viewed as a combination of several modules: 1) stubs library that clients
// are linked against to, 2) droiddoc module that internally generates API stubs source files,
diff --git a/java/sdk_test.go b/java/sdk_test.go
index fb86463..52d2df5 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -252,7 +252,7 @@
bootclasspath: []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
system: "core-current-stubs-system-modules",
java9classpath: []string{"android_module_lib_stubs_current"},
- aidl: "-p" + buildDir + "/framework.aidl",
+ aidl: "-p" + buildDir + "/framework_non_updatable.aidl",
},
{
name: "system_server_current",
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index a559330..7dc4915 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -54,18 +54,16 @@
var ret map[string]string
if len(makeVars) > 0 {
+ // It's not safe to use the same TMPDIR as the build, as that can be removed.
tmpDir, err := ioutil.TempDir("", "dumpvars")
if err != nil {
return nil, err
}
defer os.RemoveAll(tmpDir)
- // It's not safe to use the same TMPDIR as the build, as that can be removed.
- config.Environment().Set("TMPDIR", tmpDir)
+ SetupLitePath(ctx, config, tmpDir)
- SetupLitePath(ctx, config)
-
- ret, err = dumpMakeVars(ctx, config, goals, makeVars, false)
+ ret, err = dumpMakeVars(ctx, config, goals, makeVars, false, tmpDir)
if err != nil {
return ret, err
}
@@ -82,7 +80,7 @@
return ret, nil
}
-func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool) (map[string]string, error) {
+func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool, tmpDir string) (map[string]string, error) {
ctx.BeginTrace(metrics.RunKati, "dumpvars")
defer ctx.EndTrace()
@@ -98,6 +96,9 @@
cmd.Environment.Set("WRITE_SOONG_VARIABLES", "true")
}
cmd.Environment.Set("DUMP_MANY_VARS", strings.Join(vars, " "))
+ if tmpDir != "" {
+ cmd.Environment.Set("TMPDIR", tmpDir)
+ }
cmd.Sandbox = dumpvarsSandbox
output := bytes.Buffer{}
cmd.Stdout = &output
@@ -253,7 +254,7 @@
"BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
}, exportEnvVars...), BannerVars...)
- make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
+ make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
if err != nil {
ctx.Fatalln("Error dumping make vars:", err)
}
diff --git a/ui/build/path.go b/ui/build/path.go
index 7122927..6f5cf78 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -55,8 +55,9 @@
}
// A "lite" version of SetupPath used for dumpvars, or other places that need
-// minimal overhead (but at the expense of logging).
-func SetupLitePath(ctx Context, config Config) {
+// minimal overhead (but at the expense of logging). If tmpDir is empty, the
+// default TMPDIR is used from config.
+func SetupLitePath(ctx Context, config Config, tmpDir string) {
if config.pathReplaced {
return
}
@@ -65,8 +66,11 @@
defer ctx.EndTrace()
origPath, _ := config.Environment().Get("PATH")
- myPath, _ := config.Environment().Get("TMPDIR")
- myPath = filepath.Join(myPath, "path")
+
+ if tmpDir == "" {
+ tmpDir, _ = config.Environment().Get("TMPDIR")
+ }
+ myPath := filepath.Join(tmpDir, "path")
ensureEmptyDirectoriesExist(ctx, myPath)
os.Setenv("PATH", origPath)