Merge "bp2build: refactor BazelTargetModule naming boilerplate."
diff --git a/android/api_levels.go b/android/api_levels.go
index 1b53f3f..2f6a9d2 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -24,6 +24,8 @@
RegisterSingletonType("api_levels", ApiLevelsSingleton)
}
+const previewAPILevelBase = 9000
+
// An API level, which may be a finalized (numbered) API, a preview (codenamed)
// API, or the future API level (10000). Can be parsed from a string with
// ApiLevelFromUser or ApiLevelOrPanic.
@@ -57,6 +59,21 @@
}
}
+// FinalOrPreviewInt distinguishes preview versions from "current" (future).
+// This is for "native" stubs and should be in sync with ndkstubgen/getApiLevelsMap().
+// - "current" -> future (10000)
+// - preview codenames -> preview base (9000) + index
+// - otherwise -> cast to int
+func (this ApiLevel) FinalOrPreviewInt() int {
+ if this.IsCurrent() {
+ return this.number
+ }
+ if this.IsPreview() {
+ return previewAPILevelBase + this.number
+ }
+ return this.number
+}
+
// Returns the canonical name for this API level. For a finalized API level
// this will be the API number as a string. For a preview API level this
// will be the codename, or "current".
@@ -282,7 +299,6 @@
func getApiLevelsMap(config Config) map[string]int {
return config.Once(apiLevelsMapKey, func() interface{} {
- baseApiLevel := 9000
apiLevelsMap := map[string]int{
"G": 9,
"I": 14,
@@ -302,7 +318,7 @@
"R": 30,
}
for i, codename := range config.PlatformVersionActiveCodenames() {
- apiLevelsMap[codename] = baseApiLevel + i
+ apiLevelsMap[codename] = previewAPILevelBase + i
}
return apiLevelsMap
diff --git a/android/sdk.go b/android/sdk.go
index bab0ed8..f2cdc88 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -177,12 +177,6 @@
// to the zip
CopyToSnapshot(src Path, dest string)
- // Return the path to an empty file.
- //
- // This can be used by sdk member types that need to create an empty file in the snapshot, simply
- // pass the value returned from this to the CopyToSnapshot() method.
- EmptyFile() Path
-
// Unzip the supplied zip into the snapshot relative directory destDir.
UnzipToSnapshot(zipPath Path, destDir string)
diff --git a/android/variable.go b/android/variable.go
index 9b3ed17..799369d 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -121,10 +121,6 @@
Cppflags []string
}
- Use_lmkd_stats_log struct {
- Cflags []string
- }
-
Arc struct {
Cflags []string `android:"arch_variant"`
Exclude_srcs []string `android:"arch_variant"`
@@ -240,7 +236,6 @@
Treble_linker_namespaces *bool `json:",omitempty"`
Enforce_vintf_manifest *bool `json:",omitempty"`
Uml *bool `json:",omitempty"`
- Use_lmkd_stats_log *bool `json:",omitempty"`
Arc *bool `json:",omitempty"`
MinimizeJavaDebugInfo *bool `json:",omitempty"`
diff --git a/apex/apex.go b/apex/apex.go
index 724a50b..cfeac72 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2348,7 +2348,6 @@
"libFraunhoferAAC",
"libaudio-a2dp-hw-utils",
"libaudio-hearing-aid-hw-utils",
- "libbinder_headers",
"libbluetooth",
"libbluetooth-types",
"libbluetooth-types-header",
@@ -2479,7 +2478,6 @@
"libaudiopolicy",
"libaudioutils",
"libaudioutils_fixedfft",
- "libbinder_headers",
"libbluetooth-types-header",
"libbufferhub",
"libbufferhub_headers",
@@ -2595,7 +2593,6 @@
"libavcenc",
"libavservices_minijail",
"libavservices_minijail",
- "libbinder_headers",
"libbinderthreadstateutils",
"libbluetooth-types-header",
"libbufferhub_headers",
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 7f5be7e..05ad79b 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -994,6 +994,80 @@
})
}
+func TestApex_PlatformUsesLatestStubFromApex(t *testing.T) {
+ t.Parallel()
+ // myapex (Z)
+ // mylib -----------------.
+ // |
+ // otherapex (29) |
+ // libstub's versions: 29 Z current
+ // |
+ // <platform> |
+ // libplatform ----------------'
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ min_sdk_version: "Z", // non-final
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libstub"],
+ apex_available: ["myapex"],
+ min_sdk_version: "Z",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "otherapex",
+ key: "myapex.key",
+ native_shared_libs: ["libstub"],
+ min_sdk_version: "29",
+ }
+
+ cc_library {
+ name: "libstub",
+ srcs: ["mylib.cpp"],
+ stubs: {
+ versions: ["29", "Z", "current"],
+ },
+ apex_available: ["otherapex"],
+ min_sdk_version: "29",
+ }
+
+ // platform module depending on libstub from otherapex should use the latest stub("current")
+ cc_library {
+ name: "libplatform",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libstub"],
+ }
+ `, func(fs map[string][]byte, config android.Config) {
+ config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Z")
+ config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
+ config.TestProductVariables.Platform_version_active_codenames = []string{"Z"}
+ })
+
+ // Ensure that mylib from myapex is built against "min_sdk_version" stub ("Z"), which is non-final
+ mylibCflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
+ ensureContains(t, mylibCflags, "-D__LIBSTUB_API__=9000 ")
+ mylibLdflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+ ensureContains(t, mylibLdflags, "libstub/android_arm64_armv8-a_shared_Z/libstub.so ")
+
+ // Ensure that libplatform is built against latest stub ("current") of mylib3 from the apex
+ libplatformCflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ ensureContains(t, libplatformCflags, "-D__LIBSTUB_API__=10000 ") // "current" maps to 10000
+ libplatformLdflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
+ ensureContains(t, libplatformLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ")
+}
+
func TestApexWithExplicitStubsDependency(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -4288,7 +4362,7 @@
// Empty transformation.
}
- checkDexJarBuildPath := func(ctx *android.TestContext, name string) {
+ checkDexJarBuildPath := func(t *testing.T, ctx *android.TestContext, name string) {
// Make sure the import has been given the correct path to the dex jar.
p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.Dependency)
dexJarBuildPath := p.DexJarBuildPath()
@@ -4297,7 +4371,7 @@
}
}
- ensureNoSourceVariant := func(ctx *android.TestContext) {
+ ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext) {
// Make sure that an apex variant is not created for the source module.
if expected, actual := []string{"android_common"}, ctx.ModuleVariantsForTests("libfoo"); !reflect.DeepEqual(expected, actual) {
t.Errorf("invalid set of variants for %q: expected %q, found %q", "libfoo", expected, actual)
@@ -4328,7 +4402,7 @@
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkDexJarBuildPath(ctx, "libfoo")
+ checkDexJarBuildPath(t, ctx, "libfoo")
})
t.Run("prebuilt with source preferred", func(t *testing.T) {
@@ -4360,8 +4434,8 @@
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkDexJarBuildPath(ctx, "prebuilt_libfoo")
- ensureNoSourceVariant(ctx)
+ checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
+ ensureNoSourceVariant(t, ctx)
})
t.Run("prebuilt preferred with source", func(t *testing.T) {
@@ -4393,8 +4467,8 @@
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkDexJarBuildPath(ctx, "prebuilt_libfoo")
- ensureNoSourceVariant(ctx)
+ checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
+ ensureNoSourceVariant(t, ctx)
})
}
@@ -4403,7 +4477,7 @@
config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo"})
}
- checkBootDexJarPath := func(ctx *android.TestContext, bootDexJarPath string) {
+ checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, bootDexJarPath string) {
s := ctx.SingletonForTests("dex_bootjars")
foundLibfooJar := false
for _, output := range s.AllOutputs() {
@@ -4444,7 +4518,7 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
})
t.Run("prebuilt with source library preferred", func(t *testing.T) {
@@ -4513,7 +4587,7 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
})
t.Run("prebuilt with source apex preferred", func(t *testing.T) {
@@ -4557,7 +4631,7 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(ctx, ".intermediates/libfoo/android_common_apex10000/aligned/libfoo.jar")
+ checkBootDexJarPath(t, ctx, ".intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
})
t.Run("prebuilt preferred with source apex disabled", func(t *testing.T) {
@@ -4603,7 +4677,7 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
})
}
@@ -6230,6 +6304,7 @@
android.RegisterPrebuiltMutators(ctx)
cc.RegisterRequiredBuildComponentsForTest(ctx)
java.RegisterRequiredBuildComponentsForTest(ctx)
+ java.RegisterHiddenApiSingletonComponents(ctx)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
@@ -6241,6 +6316,11 @@
transformDexpreoptConfig(dexpreoptConfig)
dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
+ // Make sure that any changes to these dexpreopt properties are mirrored in the corresponding
+ // product variables that are used by hiddenapi.
+ config.TestProductVariables.BootJars = dexpreoptConfig.BootJars
+ config.TestProductVariables.UpdatableBootJars = dexpreoptConfig.UpdatableBootJars
+
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
android.FailIfErrored(t, errs)
diff --git a/apex/builder.go b/apex/builder.go
index 16ca74c..2663a67 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -700,15 +700,20 @@
})
a.apisUsedByModuleFile = apisUsedbyOutputFile
+ var libNames []string
+ for _, f := range a.filesInfo {
+ if f.class == nativeSharedLib {
+ libNames = append(libNames, f.stem())
+ }
+ }
apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt")
ndkLibraryList := android.PathForSource(ctx, "system/core/rootdir/etc/public.libraries.android.txt")
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")).
- Text(imageDir.String()).
- Implicits(implicitInputs).
Output(apisBackedbyOutputFile).
- Input(ndkLibraryList)
+ Input(ndkLibraryList).
+ Flags(libNames)
rule.Build("ndk_backedby_list", "Generate API libraries backed by Apex")
a.apisBackedByModuleFile = apisBackedbyOutputFile
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 3149952..041afb3 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -260,12 +260,36 @@
}
}
+type exportedDependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+// Mark this tag so dependencies that use it are excluded from visibility enforcement.
+//
+// This does allow any prebuilt_apex to reference any module which does open up a small window for
+// restricted visibility modules to be referenced from the wrong prebuilt_apex. However, doing so
+// avoids opening up a much bigger window by widening the visibility of modules that need files
+// provided by the prebuilt_apex to include all the possible locations they may be defined, which
+// could include everything below vendor/.
+//
+// A prebuilt_apex that references a module via this tag will have to contain the appropriate files
+// corresponding to that module, otherwise it will fail when attempting to retrieve the files from
+// the .apex file. It will also have to be included in the module's apex_available property too.
+// That makes it highly unlikely that a prebuilt_apex would reference a restricted module
+// incorrectly.
+func (t exportedDependencyTag) ExcludeFromVisibilityEnforcement() {}
+
+var (
+ exportedJavaLibTag = exportedDependencyTag{name: "exported_java_lib"}
+)
+
func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies onto the java modules that represent the java libraries that are provided by
// and exported from this prebuilt apex.
for _, lib := range p.properties.Exported_java_libs {
dep := prebuiltApexExportedModuleName(ctx, lib)
- ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), javaLibTag, dep)
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedJavaLibTag, dep)
}
}
@@ -305,7 +329,7 @@
var dependencies []android.ApexModule
mctx.VisitDirectDeps(func(m android.Module) {
tag := mctx.OtherModuleDependencyTag(m)
- if tag == javaLibTag {
+ if tag == exportedJavaLibTag {
depName := mctx.OtherModuleName(m)
// It is an error if the other module is not a prebuilt.
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 8d173b9..7ffcfa4 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -173,6 +173,12 @@
}
t = generateBazelTarget(ctx, m)
case QueryView:
+ // Blocklist certain module types from being generated.
+ if canonicalizeModuleType(ctx.ModuleType(m)) == "package" {
+ // package module name contain slashes, and thus cannot
+ // be mapped cleanly to a bazel label.
+ return
+ }
t = generateSoongModuleTarget(ctx, m)
default:
panic(fmt.Errorf("Unknown code-generation mode: %s", codegenMode))
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 6403547..b1c1b2e 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -266,7 +266,7 @@
}
}
-func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool) {
+func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) {
t.Helper()
mod, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
if !ok {
@@ -282,8 +282,14 @@
if include {
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])
+ if fake {
+ if out.Rule == nil {
+ t.Errorf("Missing rule for module %q output file %q", moduleName, outputFiles[0])
+ }
+ } else {
+ 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])
+ }
}
} else {
out := singleton.MaybeOutput(snapshotPath)
@@ -294,11 +300,15 @@
}
func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
- checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true)
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false)
}
func checkSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
- checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false)
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false)
+}
+
+func checkSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
}
func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) {
diff --git a/cc/library.go b/cc/library.go
index 29a3c69..f185cb7 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -19,6 +19,7 @@
"io"
"path/filepath"
"regexp"
+ "strconv"
"strings"
"sync"
@@ -1362,8 +1363,11 @@
func (library *libraryDecorator) exportVersioningMacroIfNeeded(ctx android.BaseModuleContext) {
if library.buildStubs() && library.stubsVersion() != "" && !library.skipAPIDefine {
name := versioningMacroName(ctx.Module().(*Module).ImplementationModuleName(ctx))
- ver := library.stubsVersion()
- library.reexportFlags("-D" + name + "=" + ver)
+ apiLevel, err := android.ApiLevelFromUser(ctx, library.stubsVersion())
+ if err != nil {
+ ctx.ModuleErrorf("Can't export version macro: %s", err.Error())
+ }
+ library.reexportFlags("-D" + name + "=" + strconv.Itoa(apiLevel.FinalOrPreviewInt()))
}
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 35fc1c1..7077b71 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -239,10 +239,6 @@
if _, ok := m.linker.(*llndkHeadersDecorator); ok {
return false
}
- // If we are using directed snapshot AND we have to exclude this module, skip this
- if image.excludeFromDirectedSnapshot(cfg, m.BaseModuleName()) {
- return false
- }
// Libraries
if l, ok := m.linker.(snapshotLibraryInterface); ok {
@@ -371,18 +367,19 @@
var headers android.Paths
- copyFile := copyFileRule
- if c.fake {
- // All prebuilt binaries and headers are installed by copyFile function. This makes a fake
- // snapshot just touch prebuilts and headers, rather than installing real files.
- copyFile = func(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
+ copyFile := func(ctx android.SingletonContext, path android.Path, out string, fake bool) android.OutputPath {
+ if fake {
+ // All prebuilt binaries and headers are installed by copyFile function. This makes a fake
+ // snapshot just touch prebuilts and headers, rather than installing real files.
return writeStringToFileRule(ctx, "", out)
+ } else {
+ return copyFileRule(ctx, path, out)
}
}
// installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file.
// For executables, init_rc and vintf_fragments files are also copied.
- installSnapshot := func(m *Module) android.Paths {
+ installSnapshot := func(m *Module, fake bool) android.Paths {
targetArch := "arch-" + m.Target().Arch.ArchType.String()
if m.Target().Arch.ArchVariant != "" {
targetArch += "-" + m.Target().Arch.ArchVariant
@@ -419,7 +416,7 @@
out := filepath.Join(configsDir, path.Base())
if !installedConfigs[out] {
installedConfigs[out] = true
- ret = append(ret, copyFile(ctx, path, out))
+ ret = append(ret, copyFile(ctx, path, out, fake))
}
}
@@ -470,7 +467,7 @@
prop.ModuleName += ".cfi"
}
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
- ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
+ ret = append(ret, copyFile(ctx, libPath, snapshotLibOut, fake))
} else {
stem = ctx.ModuleName(m)
}
@@ -484,7 +481,7 @@
// install bin
binPath := m.outputFile.Path()
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
- ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
+ ret = append(ret, copyFile(ctx, binPath, snapshotBinOut, fake))
propOut = snapshotBinOut + ".json"
} else if m.object() {
// object files aren't installed to the device, so their names can conflict.
@@ -492,7 +489,7 @@
objPath := m.outputFile.Path()
snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
- ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
+ ret = append(ret, copyFile(ctx, objPath, snapshotObjOut, fake))
propOut = snapshotObjOut + ".json"
} else {
ctx.Errorf("unknown module %q in vendor snapshot", m.String())
@@ -532,9 +529,17 @@
return
}
- // installSnapshot installs prebuilts and json flag files
- snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...)
+ // If we are using directed snapshot and a module is not included in the
+ // list, we will still include the module as if it was a fake module.
+ // The reason is that soong needs all the dependencies to be present, even
+ // if they are not using during the build.
+ installAsFake := c.fake
+ if c.image.excludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) {
+ installAsFake = true
+ }
+ // installSnapshot installs prebuilts and json flag files
+ snapshotOutputs = append(snapshotOutputs, installSnapshot(m, installAsFake)...)
// just gather headers and notice files here, because they are to be deduplicated
if l, ok := m.linker.(snapshotLibraryInterface); ok {
headers = append(headers, l.snapshotHeaders()...)
@@ -553,7 +558,7 @@
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
- snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String())))
+ snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String()), c.fake))
}
// All artifacts are ready. Sort them to normalize ninja and then zip.
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index 499d7ae..659b693 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -228,7 +228,6 @@
snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
var includeJsonFiles []string
- var excludeJsonFiles []string
for _, arch := range [][]string{
[]string{"arm64", "armv8-a"},
@@ -248,9 +247,10 @@
checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
- // Excluded modules
- checkSnapshotExclude(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json"))
+ // Excluded modules. Modules not included in the directed vendor snapshot
+ // are still include as fake modules.
+ checkSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json"))
}
// Verify that each json file for an included module has a rule.
@@ -259,13 +259,6 @@
t.Errorf("include json file %q not found", jsonFile)
}
}
-
- // Verify that each json file for an excluded module has no rule.
- for _, jsonFile := range excludeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
- t.Errorf("exclude json file %q found", jsonFile)
- }
- }
}
func TestVendorSnapshotUse(t *testing.T) {
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index c06fd4f..7658154 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -48,8 +48,8 @@
// Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
Avb_algorithm *string
- // Type of the filesystem. Currently, ext4 and compressed_cpio are supported. Default is
- // ext4.
+ // Type of the filesystem. Currently, ext4, cpio, and compressed_cpio are supported. Default
+ // is ext4.
Type *string
// file_contexts file to make image. Currently, only ext4 is supported.
@@ -83,6 +83,7 @@
const (
ext4Type fsType = iota
compressedCpioType
+ cpioType // uncompressed
unknown
)
@@ -93,6 +94,8 @@
return ext4Type
case "compressed_cpio":
return compressedCpioType
+ case "cpio":
+ return cpioType
default:
ctx.PropertyErrorf("type", "%q not supported", typeStr)
return unknown
@@ -110,7 +113,9 @@
case ext4Type:
f.output = f.buildImageUsingBuildImage(ctx)
case compressedCpioType:
- f.output = f.buildCompressedCpioImage(ctx)
+ f.output = f.buildCpioImage(ctx, true)
+ case cpioType:
+ f.output = f.buildCpioImage(ctx, false)
default:
return
}
@@ -218,7 +223,7 @@
return propFile, deps
}
-func (f *filesystem) buildCompressedCpioImage(ctx android.ModuleContext) android.OutputPath {
+func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) android.OutputPath {
if proptools.Bool(f.properties.Use_avb) {
ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+
"Consider adding this to bootimg module and signing the entire boot image.")
@@ -239,18 +244,22 @@
Input(zipFile)
output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath
- builder.Command().
+ cmd := builder.Command().
BuiltTool("mkbootfs").
- Text(rootDir.String()). // input directory
- Text("|").
- BuiltTool("lz4").
- Flag("--favor-decSpeed"). // for faster boot
- Flag("-12"). // maximum compression level
- Flag("-l"). // legacy format for kernel
- Text(">").Output(output)
+ Text(rootDir.String()) // input directory
+ if compressed {
+ cmd.Text("|").
+ BuiltTool("lz4").
+ Flag("--favor-decSpeed"). // for faster boot
+ Flag("-12"). // maximum compression level
+ Flag("-l"). // legacy format for kernel
+ Text(">").Output(output)
+ } else {
+ cmd.Text(">").Output(output)
+ }
// rootDir is not deleted. Might be useful for quick inspection.
- builder.Build("build_compressed_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
+ builder.Build("build_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
return output
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 21f3012..6e7c437 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -646,6 +646,9 @@
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", a.dexpreopter.builtInstalled)
}
entries.AddStrings("LOCAL_INSTALLED_MODULE_STEM", a.installPath.Rel())
+ if Bool(a.properties.Export_package_resources) {
+ entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.outputFile)
+ }
},
},
}}
diff --git a/java/app_import.go b/java/app_import.go
index 6f21bfb..59eb10a 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -92,6 +92,10 @@
// Optional name for the installed app. If unspecified, it is derived from the module name.
Filename *string
+
+ // If set, create package-export.apk, which other packages can
+ // use to get PRODUCT-agnostic resource data like IDs and type definitions.
+ Export_package_resources *bool
}
func (a *AndroidAppImport) IsInstallable() bool {
@@ -142,13 +146,17 @@
}
}
+func (a *AndroidAppImport) isPrebuiltFrameworkRes() bool {
+ return a.Name() == "prebuilt_framework-res"
+}
+
func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
cert := android.SrcIsModule(String(a.properties.Certificate))
if cert != "" {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
- a.usesLibrary.deps(ctx, true)
+ a.usesLibrary.deps(ctx, !a.isPrebuiltFrameworkRes())
}
func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
@@ -247,7 +255,12 @@
a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
var installDir android.InstallPath
- if Bool(a.properties.Privileged) {
+
+ if a.isPrebuiltFrameworkRes() {
+ // framework-res.apk is installed as system/framework/framework-res.apk
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ a.preprocessed = true
+ } else if Bool(a.properties.Privileged) {
installDir = android.PathForModuleInstall(ctx, "priv-app", a.BaseModuleName())
} else if ctx.InstallInTestcases() {
installDir = android.PathForModuleInstall(ctx, a.BaseModuleName(), ctx.DeviceConfig().DeviceArch())
@@ -275,7 +288,15 @@
// TODO: Handle EXTERNAL
// Sign or align the package if package has not been preprocessed
- if a.preprocessed {
+
+ if a.isPrebuiltFrameworkRes() {
+ a.outputFile = srcApk
+ certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
+ if len(certificates) != 1 {
+ ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
+ }
+ a.certificate = certificates[0]
+ } else if a.preprocessed {
a.outputFile = srcApk
a.certificate = PresignedCertificate
} else if !Bool(a.properties.Presigned) {
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 344d23b..d7f69eb 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -393,6 +393,69 @@
}
}
+func TestAndroidAppImport_frameworkRes(t *testing.T) {
+ ctx, config := testJava(t, `
+ android_app_import {
+ name: "framework-res",
+ certificate: "platform",
+ apk: "package-res.apk",
+ prefer: true,
+ export_package_resources: true,
+ // Disable dexpreopt and verify_uses_libraries check as the app
+ // contains no Java code to be dexpreopted.
+ enforce_uses_libs: false,
+ dex_preopt: {
+ enabled: false,
+ },
+ }
+ `)
+
+ mod := ctx.ModuleForTests("prebuilt_framework-res", "android_common").Module()
+ a := mod.(*AndroidAppImport)
+
+ if !a.preprocessed {
+ t.Errorf("prebuilt framework-res is not preprocessed")
+ }
+
+ expectedInstallPath := buildDir + "/target/product/test_device/system/framework/framework-res.apk"
+
+ if a.dexpreopter.installPath.String() != expectedInstallPath {
+ t.Errorf("prebuilt framework-res installed to incorrect location, actual: %s, expected: %s", a.dexpreopter.installPath, expectedInstallPath)
+
+ }
+
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+
+ expectedPath := "."
+ // From apk property above, in the root of the source tree.
+ expectedPrebuiltModuleFile := "package-res.apk"
+ // Verify that the apk is preprocessed: The export package is the same
+ // as the prebuilt.
+ expectedSoongResourceExportPackage := expectedPrebuiltModuleFile
+
+ actualPath := entries.EntryMap["LOCAL_PATH"]
+ actualPrebuiltModuleFile := entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"]
+ actualSoongResourceExportPackage := entries.EntryMap["LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE"]
+
+ if len(actualPath) != 1 {
+ t.Errorf("LOCAL_PATH incorrect len %d", len(actualPath))
+ } else if actualPath[0] != expectedPath {
+ t.Errorf("LOCAL_PATH mismatch, actual: %s, expected: %s", actualPath[0], expectedPath)
+ }
+
+ if len(actualPrebuiltModuleFile) != 1 {
+ t.Errorf("LOCAL_PREBUILT_MODULE_FILE incorrect len %d", len(actualPrebuiltModuleFile))
+ } else if actualPrebuiltModuleFile[0] != expectedPrebuiltModuleFile {
+ t.Errorf("LOCAL_PREBUILT_MODULE_FILE mismatch, actual: %s, expected: %s", actualPrebuiltModuleFile[0], expectedPrebuiltModuleFile)
+ }
+
+ if len(actualSoongResourceExportPackage) != 1 {
+ t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE incorrect len %d", len(actualSoongResourceExportPackage))
+ } else if actualSoongResourceExportPackage[0] != expectedSoongResourceExportPackage {
+ t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE mismatch, actual: %s, expected: %s", actualSoongResourceExportPackage[0], expectedSoongResourceExportPackage)
+ }
+}
+
func TestAndroidTestImport(t *testing.T) {
ctx, config := testJava(t, `
android_test_import {
diff --git a/java/builder.go b/java/builder.go
index 995160d..22a891a 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -193,12 +193,19 @@
jarjar = pctx.AndroidStaticRule("jarjar",
blueprint.RuleParams{
- Command: "${config.JavaCmd} ${config.JavaVmFlags}" +
+ Command: "" +
+ // Jarjar doesn't exit with an error when the rules file contains a syntax error,
+ // leading to stale or missing files later in the build. Remove the output file
+ // before running jarjar.
+ "rm -f ${out} && " +
+ "${config.JavaCmd} ${config.JavaVmFlags}" +
// b/146418363 Enable Android specific jarjar transformer to drop compat annotations
// for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes
// avoids adding new hiddenapis after jarjar'ing.
" -DremoveAndroidCompatAnnotations=true" +
- " -jar ${config.JarjarCmd} process $rulesFile $in $out",
+ " -jar ${config.JarjarCmd} process $rulesFile $in $out && " +
+ // Turn a missing output file into a ninja error
+ `[ -e ${out} ] || (echo "Missing output file"; exit 1)`,
CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
},
"rulesFile")
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 2a7eb42..86b1895 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -435,6 +435,11 @@
// Inspect this module to see if it contains a bootclasspath dex jar.
// Note that the same jar may occur in multiple modules.
// This logic is tested in the apex package to avoid import cycle apex <-> java.
+//
+// This is similar to logic in isModuleInConfiguredList() so any changes needed here are likely to
+// be needed there too.
+//
+// TODO(b/177892522): Avoid having to perform this type of check or if necessary dedup it.
func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) {
name := ctx.ModuleName(module)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index eafbf5d..ada11c3 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -108,9 +108,18 @@
// not on the list then that will cause failures in the CtsHiddenApiBlacklist...
// tests.
if inList(bootJarName, ctx.Config().BootJars()) {
- // Create ninja rules to generate various CSV files needed by hiddenapi and store the paths
- // in the hiddenAPI structure.
- h.hiddenAPIGenerateCSV(ctx, implementationJar)
+ // More than one library with the same classes may need to be encoded but only one should be
+ // used as a source of information for hidden API processing otherwise it will result in
+ // duplicate entries in the files.
+ if primary {
+ // Create ninja rules to generate various CSV files needed by hiddenapi and store the paths
+ // in the hiddenAPI structure.
+ h.hiddenAPIGenerateCSV(ctx, implementationJar)
+
+ // Save the unencoded dex jar so it can be used when generating the
+ // hiddenAPISingletonPathsStruct.stubFlags file.
+ h.bootDexJarPath = dexJar
+ }
// If this module is actually on the boot jars list and not providing
// hiddenapi information for a module on the boot jars list then encode
@@ -118,13 +127,6 @@
if name == bootJarName {
hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", name+".jar").OutputPath
- // More than one library with the same classes can be encoded but only one can
- // be added to the global set of flags, otherwise it will result in duplicate
- // classes which is an error. Therefore, only add the dex jar of one of them
- // to the global set of flags.
- if primary {
- h.bootDexJarPath = dexJar
- }
hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
dexJar = hiddenAPIJar
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index ccb8745..46994c3 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -22,9 +22,13 @@
)
func init() {
- android.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
- android.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory)
- android.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory)
+ RegisterHiddenApiSingletonComponents(android.InitRegistrationContext)
+}
+
+func RegisterHiddenApiSingletonComponents(ctx android.RegistrationContext) {
+ ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
+ ctx.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory)
+ ctx.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory)
}
type hiddenAPISingletonPathsStruct struct {
@@ -213,6 +217,10 @@
var bootDexJars android.Paths
+ // Get the configured non-updatable and updatable boot jars.
+ nonUpdatableBootJars := ctx.Config().NonUpdatableBootJars()
+ updatableBootJars := ctx.Config().UpdatableBootJars()
+
ctx.VisitAllModules(func(module android.Module) {
// Collect dex jar paths for the modules listed above.
if j, ok := module.(Dependency); ok {
@@ -227,11 +235,8 @@
// Collect dex jar paths for modules that had hiddenapi encode called on them.
if h, ok := module.(hiddenAPIIntf); ok {
if jar := h.bootDexJar(); jar != nil {
- // For a java lib included in an APEX, only take the one built for
- // the platform variant, and skip the variants for APEXes.
- // Otherwise, the hiddenapi tool will complain about duplicated classes
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
- if !apexInfo.IsForPlatform() {
+ if !isModuleInConfiguredList(ctx, module, nonUpdatableBootJars) &&
+ !isModuleInConfiguredList(ctx, module, updatableBootJars) {
return
}
@@ -280,6 +285,47 @@
rule.Build("hiddenAPIStubFlagsFile", "hiddenapi stub flags")
}
+// Checks to see whether the supplied module variant is in the list of boot jars.
+//
+// This is similar to logic in getBootImageJar() so any changes needed here are likely to be needed
+// there too.
+//
+// TODO(b/179354495): Avoid having to perform this type of check or if necessary dedup it.
+func isModuleInConfiguredList(ctx android.SingletonContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool {
+ name := ctx.ModuleName(module)
+
+ // Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed.
+ name = android.RemoveOptionalPrebuiltPrefix(name)
+
+ // Ignore any module that is not listed in the boot image configuration.
+ index := configuredBootJars.IndexOfJar(name)
+ if index == -1 {
+ return false
+ }
+
+ // It is an error if the module is not an ApexModule.
+ if _, ok := module.(android.ApexModule); !ok {
+ ctx.Errorf("module %q configured in boot jars does not support being added to an apex", module)
+ return false
+ }
+
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+
+ // Now match the apex part of the boot image configuration.
+ requiredApex := configuredBootJars.Apex(index)
+ if requiredApex == "platform" {
+ if len(apexInfo.InApexes) != 0 {
+ // A platform variant is required but this is for an apex so ignore it.
+ return false
+ }
+ } else if !apexInfo.InApexByBaseName(requiredApex) {
+ // An apex variant for a specific apex is required but this is the wrong apex.
+ return false
+ }
+
+ return true
+}
+
func prebuiltFlagsRule(ctx android.SingletonContext) android.Path {
outputPath := hiddenAPISingletonPaths(ctx).flags
inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-flags.csv")
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 27f363e..fcaa94a 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -15,11 +15,12 @@
package java
import (
- "android/soong/android"
"fmt"
"strings"
"testing"
+ "android/soong/android"
+
"github.com/google/blueprint/proptools"
)
@@ -32,7 +33,7 @@
func testContextWithHiddenAPI(config android.Config) *android.TestContext {
ctx := testContext(config)
- ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
+ RegisterHiddenApiSingletonComponents(ctx)
return ctx
}
@@ -64,7 +65,7 @@
name: "foo",
srcs: ["a.java"],
compile_dex: true,
- }
+ }
`, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
@@ -75,6 +76,45 @@
}
}
+func checkRuleInputs(t *testing.T, expected string, hiddenAPIRule android.TestingBuildParams) {
+ actual := strings.TrimSpace(strings.Join(android.NormalizePathsForTesting(hiddenAPIRule.Implicits), "\n"))
+ expected = strings.TrimSpace(expected)
+ if actual != expected {
+ t.Errorf("Expected hiddenapi rule inputs:\n%s\nactual inputs:\n%s", expected, actual)
+ }
+}
+
+func TestHiddenAPIIndexSingleton(t *testing.T) {
+ ctx, _ := testHiddenAPIBootJars(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+
+ java_import {
+ name: "foo",
+ jars: ["a.jar"],
+ compile_dex: true,
+ prefer: false,
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+ `, []string{"platform:foo", "platform:bar"}, nil)
+
+ hiddenAPIIndex := ctx.SingletonForTests("hiddenapi_index")
+ indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index")
+ checkRuleInputs(t, `
+.intermediates/bar/android_common/hiddenapi/index.csv
+.intermediates/foo/android_common/hiddenapi/index.csv
+`,
+ indexRule)
+}
+
func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
ctx, _ := testHiddenAPIBootJars(t, `
java_import {
@@ -98,14 +138,14 @@
name: "foo",
srcs: ["a.java"],
compile_dex: true,
- }
+ }
java_import {
name: "foo",
jars: ["a.jar"],
compile_dex: true,
prefer: false,
- }
+ }
`, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
@@ -127,14 +167,14 @@
name: "foo",
srcs: ["a.java"],
compile_dex: true,
- }
+ }
java_import {
name: "foo",
jars: ["a.jar"],
compile_dex: true,
prefer: true,
- }
+ }
`, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
diff --git a/java/java.go b/java/java.go
index 91944f6..bed232b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -40,18 +40,21 @@
// Register sdk member types.
android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
+ // Export implementation classes jar as part of the sdk.
+ exportImplementationClassesJar := func(_ android.SdkMemberContext, j *Library) android.Path {
+ implementationJars := j.ImplementationAndResourcesJars()
+ if len(implementationJars) != 1 {
+ panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
+ }
+ return implementationJars[0]
+ }
+
// Register java implementation libraries for use only in module_exports (not sdk).
android.RegisterSdkMemberType(&librarySdkMemberType{
android.SdkMemberTypeBase{
PropertyName: "java_libs",
},
- func(_ android.SdkMemberContext, j *Library) android.Path {
- implementationJars := j.ImplementationAndResourcesJars()
- if len(implementationJars) != 1 {
- panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
- }
- return implementationJars[0]
- },
+ exportImplementationClassesJar,
sdkSnapshotFilePathForJar,
copyEverythingToSnapshot,
})
@@ -72,19 +75,11 @@
PropertyName: "java_boot_libs",
SupportsSdk: true,
},
- func(ctx android.SdkMemberContext, j *Library) android.Path {
- // Java boot libs are only provided in the SDK to provide access to their dex implementation
- // jar for use by dexpreopting and boot jars package check. They do not need to provide an
- // actual implementation jar but the java_import will need a file that exists so just copy an
- // empty file. Any attempt to use that file as a jar will cause a build error.
- return ctx.SnapshotBuilder().EmptyFile()
- },
- func(osPrefix, name string) string {
- // Create a special name for the implementation jar to try and provide some useful information
- // to a developer that attempts to compile against this.
- // TODO(b/175714559): Provide a proper error message in Soong not ninja.
- return filepath.Join(osPrefix, "java_boot_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
- },
+ // Temporarily export implementation classes jar for java_boot_libs as it is required for the
+ // hiddenapi processing.
+ // TODO(b/179354495): Revert once hiddenapi processing has been modularized.
+ exportImplementationClassesJar,
+ sdkSnapshotFilePathForJar,
onlyCopyJarToSnapshot,
})
diff --git a/rust/binary.go b/rust/binary.go
index 0334acc..df48916 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -119,6 +119,7 @@
outputFile := android.PathForModuleOut(ctx, fileName)
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
diff --git a/rust/compiler.go b/rust/compiler.go
index c921824..586063e 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -96,7 +96,11 @@
// list of C shared library dependencies
Shared_libs []string `android:"arch_variant"`
- // list of C static library dependencies
+ // list of C static library dependencies. Note, static libraries prefixed by "lib" will be passed to rustc
+ // along with "-lstatic=<name>". This will bundle the static library into rlib/static libraries so dependents do
+ // not need to also declare the static library as a dependency. Static libraries which are not prefixed by "lib"
+ // cannot be passed to rustc with this flag and will not be bundled into rlib/static libraries, and thus must
+ // be redeclared in dependents.
Static_libs []string `android:"arch_variant"`
// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
diff --git a/rust/library.go b/rust/library.go
index b5749a2..7ff13ec 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -443,6 +443,7 @@
}
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
if library.dylib() {
@@ -482,7 +483,6 @@
if library.rlib() || library.dylib() {
library.flagExporter.exportLinkDirs(deps.linkDirs...)
- library.flagExporter.exportDepFlags(deps.depFlags...)
library.flagExporter.exportLinkObjects(deps.linkObjects...)
}
diff --git a/rust/rust.go b/rust/rust.go
index 504b7a9..0b733cc 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -280,10 +280,15 @@
SharedLibDeps android.Paths
StaticLibs android.Paths
ProcMacros RustLibraries
- linkDirs []string
- depFlags []string
- linkObjects []string
- //ReexportedDeps android.Paths
+
+ // depFlags and depLinkFlags are rustc and linker (clang) flags.
+ depFlags []string
+ depLinkFlags []string
+
+ // linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker.
+ // Both of these are exported and propagate to dependencies.
+ linkDirs []string
+ linkObjects []string
// Used by bindgen modules which call clang
depClangFlags []string
@@ -328,12 +333,10 @@
type exportedFlagsProducer interface {
exportLinkDirs(...string)
- exportDepFlags(...string)
exportLinkObjects(...string)
}
type flagExporter struct {
- depFlags []string
linkDirs []string
linkObjects []string
}
@@ -342,17 +345,12 @@
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
}
-func (flagExporter *flagExporter) exportDepFlags(flags ...string) {
- flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...))
-}
-
func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
}
func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
- Flags: flagExporter.depFlags,
LinkDirs: flagExporter.linkDirs,
LinkObjects: flagExporter.linkObjects,
})
@@ -898,8 +896,24 @@
exportDep := false
switch {
case cc.IsStaticDepTag(depTag):
- depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
+ // Only pass -lstatic for rlibs as it results in dylib bloat.
+ if lib, ok := ctx.Module().(*Module).compiler.(libraryInterface); ok && lib.rlib() {
+ // Link cc static libraries using "-lstatic" so rustc can reason about how to handle these
+ // (for example, bundling them into rlibs).
+ //
+ // rustc does not support linking libraries with the "-l" flag unless they are prefixed by "lib".
+ // If we need to link a library that isn't prefixed by "lib", we'll just link to it directly through
+ // linkObjects; such a library may need to be redeclared by static dependents.
+ if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
+ depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
+ }
+ }
+
+ // Add this to linkObjects to pass the library directly to the linker as well. This propagates
+ // to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant.
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
+ depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
+
exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
@@ -1213,6 +1227,16 @@
return false
}
+// If a library file has a "lib" prefix, extract the library name without the prefix.
+func libNameFromFilePath(filepath android.Path) (string, bool) {
+ libName := strings.TrimSuffix(filepath.Base(), filepath.Ext())
+ if strings.HasPrefix(libName, "lib") {
+ libName = libName[3:]
+ return libName, true
+ }
+ return "", false
+}
+
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
diff --git a/rust/rust_test.go b/rust/rust_test.go
index abc9af9..88d9643 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -213,6 +213,7 @@
name: "librlib",
srcs: ["foo.rs"],
crate_name: "rlib",
+ static_libs: ["libstatic"],
}
rust_proc_macro {
name: "libpm",
@@ -230,6 +231,7 @@
}
`)
module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+ rustc := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
@@ -251,6 +253,11 @@
if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) {
t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
}
+
+ if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=static") {
+ t.Errorf("-lstatic flag not being passed to rustc for static library")
+ }
+
}
func TestSourceProviderDeps(t *testing.T) {
diff --git a/scripts/gen_ndk_backedby_apex.sh b/scripts/gen_ndk_backedby_apex.sh
index e0da602..4abaaba 100755
--- a/scripts/gen_ndk_backedby_apex.sh
+++ b/scripts/gen_ndk_backedby_apex.sh
@@ -23,33 +23,50 @@
echo "**************************** Usage Instructions ****************************"
echo "This script is used to generate the Mainline modules backed-by NDK symbols."
echo ""
- echo "To run this script use: ./ndk_backedby_module.sh \$BINARY_IMAGE_DIRECTORY \$OUTPUT_FILE_PATH \$NDK_LIB_NAME_LIST"
- echo "For example: If all the module image files that you would like to run is under directory '/myModule' and output write to /backedby.txt then the command would be:"
- echo "./ndk_usedby_module.sh /myModule /backedby.txt /ndkLibList.txt"
+ echo "To run this script use: ./gen_ndk_backed_by_apex.sh \$OUTPUT_FILE_PATH \$NDK_LIB_NAME_LIST \$MODULE_LIB1 \$MODULE_LIB2..."
+ echo "For example: If output write to /backedby.txt then the command would be:"
+ echo "./gen_ndk_backed_by_apex.sh /backedby.txt /ndkLibList.txt lib1.so lib2.so"
echo "If the module1 is backing lib1 then the backedby.txt would contains: "
echo "lib1"
}
+contains() {
+ val="$1"
+ shift
+ for x in "$@"; do
+ if [ "$x" = "$val" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+
genBackedByList() {
- dir="$1"
- [[ ! -e "$2" ]] && echo "" >> "$2"
+ out="$1"
+ shift
+ ndk_list="$1"
+ shift
+ rm -f "$out"
+ touch "$out"
while IFS= read -r line
do
soFileName=$(echo "$line" | sed 's/\(.*so\).*/\1/')
if [[ ! -z "$soFileName" && "$soFileName" != *"#"* ]]
then
- find "$dir" -type f -name "$soFileName" -exec echo "$soFileName" >> "$2" \;
+ if contains "$soFileName" "$@"; then
+ echo "$soFileName" >> "$out"
+ fi
fi
- done < "$3"
+ done < "$ndk_list"
}
if [[ "$1" == "help" ]]
then
printHelp
-elif [[ "$#" -ne 3 ]]
+elif [[ "$#" -lt 2 ]]
then
- echo "Wrong argument length. Expecting 3 argument representing image file directory, output path, path to ndk library list."
+ echo "Wrong argument length. Expecting at least 2 argument representing output path, path to ndk library list, followed by a list of libraries in the Mainline module."
else
- [[ -e "$2" ]] && rm "$2"
- genBackedByList "$1" "$2" "$3"
+ genBackedByList "$@"
fi
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 488afd8..17a6ca9 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -503,7 +503,7 @@
sdk_member_name: "myjavalib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- jars: ["java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar"],
+ jars: ["java/myjavalib.jar"],
}
java_import {
@@ -511,7 +511,7 @@
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- jars: ["java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar"],
+ jars: ["java/myjavalib.jar"],
}
module_exports_snapshot {
@@ -519,10 +519,9 @@
visibility: ["//visibility:public"],
java_boot_libs: ["myexports_myjavalib@current"],
}
-
`),
checkAllCopyRules(`
-.intermediates/myexports/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar
+.intermediates/myjavalib/android_common/withres/myjavalib.jar -> java/myjavalib.jar
`),
)
}
diff --git a/sdk/update.go b/sdk/update.go
index b5bc9f4..377aaae 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -653,9 +653,6 @@
filesToZip android.Paths
zipsToMerge android.Paths
- // The path to an empty file.
- emptyFile android.WritablePath
-
prebuiltModules map[string]*bpModule
prebuiltOrder []*bpModule
@@ -706,19 +703,6 @@
s.zipsToMerge = append(s.zipsToMerge, tmpZipPath)
}
-func (s *snapshotBuilder) EmptyFile() android.Path {
- if s.emptyFile == nil {
- ctx := s.ctx
- s.emptyFile = android.PathForModuleOut(ctx, "empty")
- s.ctx.Build(pctx, android.BuildParams{
- Rule: android.Touch,
- Output: s.emptyFile,
- })
- }
-
- return s.emptyFile
-}
-
func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType string) android.BpModule {
name := member.Name()
if s.prebuiltModules[name] != nil {
diff --git a/zip/zip.go b/zip/zip.go
index cb85f5c..f731329 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -172,6 +172,9 @@
arg := b.state
arg.SourceFiles = ReadRespFile(list)
+ for i := range arg.SourceFiles {
+ arg.SourceFiles[i] = pathtools.MatchEscape(arg.SourceFiles[i])
+ }
b.fileArgs = append(b.fileArgs, arg)
return b
}
diff --git a/zip/zip_test.go b/zip/zip_test.go
index a16e092..b456ef8 100644
--- a/zip/zip_test.go
+++ b/zip/zip_test.go
@@ -46,13 +46,14 @@
"dangling -> missing": nil,
"a/a/d -> b": nil,
"c": fileC,
- "l_nl": []byte("a/a/a\na/a/b\nc\n"),
- "l_sp": []byte("a/a/a a/a/b c"),
+ "l_nl": []byte("a/a/a\na/a/b\nc\n\\[\n"),
+ "l_sp": []byte("a/a/a a/a/b c \\["),
"l2": []byte("missing\n"),
- "rsp": []byte("'a/a/a'\na/a/b\n'@'\n'foo'\\''bar'"),
+ "rsp": []byte("'a/a/a'\na/a/b\n'@'\n'foo'\\''bar'\n'['"),
"@ -> c": nil,
"foo'bar -> c": nil,
"manifest.txt": fileCustomManifest,
+ "[": fileEmpty,
})
func fh(name string, contents []byte, method uint16) zip.FileHeader {
@@ -127,13 +128,15 @@
args: fileArgsBuilder().
File("a/a/a").
File("a/a/b").
- File("c"),
+ File("c").
+ File(`\[`),
compressionLevel: 9,
files: []zip.FileHeader{
fh("a/a/a", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
fh("c", fileC, zip.Deflate),
+ fh("[", fileEmpty, zip.Store),
},
},
{
@@ -235,6 +238,7 @@
fh("a/a/a", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
fh("c", fileC, zip.Deflate),
+ fh("[", fileEmpty, zip.Store),
},
},
{
@@ -247,6 +251,7 @@
fh("a/a/a", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
fh("c", fileC, zip.Deflate),
+ fh("[", fileEmpty, zip.Store),
},
},
{
@@ -260,6 +265,7 @@
fh("a/a/b", fileB, zip.Deflate),
fh("@", fileC, zip.Deflate),
fh("foo'bar", fileC, zip.Deflate),
+ fh("[", fileEmpty, zip.Store),
},
},
{