Merge "Only propgate strict updatability linting to modules that are in the apex" into main
diff --git a/Android.bp b/Android.bp
index 432c7fc..f2d0d94 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,5 +1,8 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_visibility: [
+ "//build/soong:__subpackages__",
+ ],
}
subdirs = [
@@ -23,6 +26,8 @@
srcs: [
"doc.go",
],
+ // Used by plugins, though probably shouldn't be.
+ visibility: ["//visibility:public"],
}
//
@@ -40,6 +45,7 @@
enabled: true,
},
},
+ defaults_visibility: ["//visibility:public"],
}
//
@@ -51,6 +57,7 @@
vendor: true,
recovery_available: true,
min_sdk_version: "apex_inherit",
+ visibility: ["//visibility:public"],
}
cc_genrule {
@@ -75,6 +82,7 @@
cmd: "$(location) -s $(out) $(in)",
srcs: [":linker"],
out: ["linker.s"],
+ visibility: ["//bionic/libc"],
}
cc_genrule {
@@ -99,11 +107,18 @@
cmd: "$(location) -T $(out) $(in)",
srcs: [":linker"],
out: ["linker.script"],
+ visibility: ["//visibility:public"],
}
// Instantiate the dex_bootjars singleton module.
dex_bootjars {
name: "dex_bootjars",
+ visibility: ["//visibility:public"],
+}
+
+art_boot_images {
+ name: "art_boot_images",
+ visibility: ["//art:__subpackages__"],
}
// Pseudo-test that's run on checkbuilds to ensure that get_clang_version can
@@ -123,6 +138,7 @@
// container for apex_contributions selected using build flags
all_apex_contributions {
name: "all_apex_contributions",
+ visibility: ["//visibility:public"],
}
product_config {
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 250fd56..d9a862c 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -88,6 +88,13 @@
ctx.PropertyErrorf("container", "missing container property")
}
+ // treating system_ext as system partition as we are combining them as one container
+ // TODO remove this logic once we start enforcing that system_ext cannot be specified as
+ // container in the container field.
+ if module.properties.Container == "system_ext" {
+ module.properties.Container = "system"
+ }
+
// Add a dependency on the aconfig_value_sets defined in
// RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that
// match our package.
diff --git a/aconfig/aconfig_value_set.go b/aconfig/aconfig_value_set.go
index 7ba76c0..d72ec48 100644
--- a/aconfig/aconfig_value_set.go
+++ b/aconfig/aconfig_value_set.go
@@ -16,6 +16,9 @@
import (
"android/soong/android"
+ "fmt"
+ "strings"
+
"github.com/google/blueprint"
)
@@ -27,6 +30,9 @@
properties struct {
// aconfig_values modules
Values []string
+
+ // Paths to the Android.bp files where the aconfig_values modules are defined.
+ Srcs []string
}
}
@@ -56,7 +62,35 @@
var valueSetProviderKey = blueprint.NewProvider[valueSetProviderData]()
+func (module *ValueSetModule) FindAconfigValuesFromSrc(ctx android.BottomUpMutatorContext) map[string]android.Path {
+ moduleDir := ctx.ModuleDir()
+ srcs := android.PathsForModuleSrcExcludes(ctx, module.properties.Srcs, []string{ctx.BlueprintsFile()})
+
+ aconfigValuesPrefix := strings.Replace(module.Name(), "aconfig_value_set", "aconfig-values", 1)
+ moduleNamesSrcMap := make(map[string]android.Path)
+ for _, src := range srcs {
+ subDir := strings.TrimPrefix(src.String(), moduleDir+"/")
+ packageName, _, found := strings.Cut(subDir, "/")
+ if found {
+ moduleName := fmt.Sprintf("%s-%s-all", aconfigValuesPrefix, packageName)
+ moduleNamesSrcMap[moduleName] = src
+ }
+ }
+ return moduleNamesSrcMap
+}
+
func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+
+ // TODO: b/366285733 - Replace the file path based solution with more robust solution.
+ aconfigValuesMap := module.FindAconfigValuesFromSrc(ctx)
+ for _, moduleName := range android.SortedKeys(aconfigValuesMap) {
+ if ctx.OtherModuleExists(moduleName) {
+ ctx.AddDependency(ctx.Module(), valueSetTag, moduleName)
+ } else {
+ ctx.ModuleErrorf("module %q not found. Rename the aconfig_values module defined in %q to %q", moduleName, aconfigValuesMap[moduleName], moduleName)
+ }
+ }
+
deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...)
for _, dep := range deps {
_, ok := dep.(*ValuesModule)
diff --git a/aconfig/aconfig_value_set_test.go b/aconfig/aconfig_value_set_test.go
index 32c31cb..3b7281e 100644
--- a/aconfig/aconfig_value_set_test.go
+++ b/aconfig/aconfig_value_set_test.go
@@ -18,6 +18,8 @@
"testing"
"android/soong/android"
+
+ "github.com/google/blueprint"
)
func TestAconfigValueSet(t *testing.T) {
@@ -41,3 +43,112 @@
depData, _ := android.OtherModuleProvider(result, module, valueSetProviderKey)
android.AssertStringEquals(t, "AvailablePackages", "blah.aconfig_values", depData.AvailablePackages["foo.package"][0].String())
}
+
+func TestAconfigValueSetBpGlob(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ // .../some_release/android.foo/
+ "some_release/android.foo/Android.bp": []byte(`
+ aconfig_values {
+ name: "aconfig-values-platform_build_release-some_release-android.foo-all",
+ package: "android.foo",
+ srcs: [
+ "*.textproto",
+ ],
+ }
+ `),
+ "some_release/android.foo/flag.textproto": nil,
+
+ // .../some_release/android.bar/
+ "some_release/android.bar/Android.bp": []byte(`
+ aconfig_values {
+ name: "aconfig-values-platform_build_release-some_release-android.bar-all",
+ package: "android.bar",
+ srcs: [
+ "*.textproto",
+ ],
+ }
+ `),
+ "some_release/android.bar/flag.textproto": nil,
+
+ // .../some_release/
+ "some_release/Android.bp": []byte(`
+ aconfig_value_set {
+ name: "aconfig_value_set-platform_build_release-some_release",
+ srcs: [
+ "*/Android.bp",
+ ],
+ }
+ `),
+ },
+ ),
+ ).RunTest(t)
+
+ checkModuleHasDependency := func(name, variant, dep string) bool {
+ t.Helper()
+ module := result.ModuleForTests(name, variant).Module()
+ depFound := false
+ result.VisitDirectDeps(module, func(m blueprint.Module) {
+ if m.Name() == dep {
+ depFound = true
+ }
+ })
+ return depFound
+ }
+ android.AssertBoolEquals(t,
+ "aconfig_value_set expected to depend on aconfig_value via srcs",
+ true,
+ checkModuleHasDependency(
+ "aconfig_value_set-platform_build_release-some_release",
+ "",
+ "aconfig-values-platform_build_release-some_release-android.foo-all",
+ ),
+ )
+ android.AssertBoolEquals(t,
+ "aconfig_value_set expected to depend on aconfig_value via srcs",
+ true,
+ checkModuleHasDependency(
+ "aconfig_value_set-platform_build_release-some_release",
+ "",
+ "aconfig-values-platform_build_release-some_release-android.bar-all",
+ ),
+ )
+}
+
+func TestAconfigValueSetBpGlobError(t *testing.T) {
+ android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ // .../some_release/android.bar/
+ "some_release/android.bar/Android.bp": []byte(`
+ aconfig_values {
+ name: "aconfig-values-platform_build_release-some_release-android_bar-all",
+ package: "android.bar",
+ srcs: [
+ "*.textproto",
+ ],
+ }
+ `),
+ "some_release/android.bar/flag.textproto": nil,
+
+ // .../some_release/
+ "some_release/Android.bp": []byte(`
+ aconfig_value_set {
+ name: "aconfig_value_set-platform_build_release-some_release",
+ srcs: [
+ "*/Android.bp",
+ ],
+ }
+ `),
+ },
+ ),
+ ).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+ `module "aconfig_value_set-platform_build_release-some_release": module ` +
+ `"aconfig-values-platform_build_release-some_release-android.bar-all" not found. ` +
+ `Rename the aconfig_values module defined in "some_release/android.bar/Android.bp" ` +
+ `to "aconfig-values-platform_build_release-some_release-android.bar-all"`),
+ ).RunTest(t)
+}
diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
index b5cf687..8c4bfe6 100644
--- a/aconfig/codegen/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -63,7 +63,7 @@
callbacks := &CcAconfigLibraryCallbacks{
properties: &CcAconfigLibraryProperties{},
}
- return cc.GeneratedCcLibraryModuleFactory("cc_aconfig_library", callbacks)
+ return cc.GeneratedCcLibraryModuleFactory(callbacks)
}
func (this *CcAconfigLibraryCallbacks) GeneratorInit(ctx cc.BaseModuleContext) {
diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go
index 98d288f..ed0b3ed 100644
--- a/aconfig/codegen/init.go
+++ b/aconfig/codegen/init.go
@@ -32,6 +32,7 @@
` --mode ${mode}` +
` --cache ${in}` +
` --out ${out}.tmp` +
+ ` --allow-instrumentation ${debug}` +
` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
` && rm -rf ${out}.tmp`,
CommandDeps: []string{
@@ -39,7 +40,7 @@
"$soong_zip",
},
Restat: true,
- }, "mode")
+ }, "mode", "debug")
// For cc_aconfig_library: Generate C++ library
cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index 673ac2a..ebca413 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -20,6 +20,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+ "strconv"
)
type declarationsTagType struct {
@@ -71,6 +72,7 @@
module.AddSharedLibrary("aconfig-annotations-lib")
// TODO(b/303773055): Remove the annotation after access issue is resolved.
module.AddSharedLibrary("unsupportedappusage")
+ module.AddSharedLibrary("aconfig_storage_reader_java")
}
}
@@ -102,7 +104,8 @@
Output: srcJarPath,
Description: "aconfig.srcjar",
Args: map[string]string{
- "mode": mode,
+ "mode": mode,
+ "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
},
})
diff --git a/aconfig/codegen/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go
index 87b54a4..d8372f3 100644
--- a/aconfig/codegen/java_aconfig_library_test.go
+++ b/aconfig/codegen/java_aconfig_library_test.go
@@ -260,7 +260,7 @@
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package.bar",
- container: "system_ext",
+ container: "vendor",
srcs: ["bar.aconfig"],
}
diff --git a/aidl_library/Android.bp b/aidl_library/Android.bp
index ec21504..07472a4 100644
--- a/aidl_library/Android.bp
+++ b/aidl_library/Android.bp
@@ -29,4 +29,5 @@
"aidl_library_test.go",
],
pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
}
diff --git a/android/Android.bp b/android/Android.bp
index 16a34b7..2adedfe 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -88,6 +88,7 @@
"prebuilt.go",
"prebuilt_build_tool.go",
"product_config.go",
+ "product_config_to_bp.go",
"proto.go",
"provider.go",
"raw_files.go",
@@ -154,4 +155,6 @@
"vintf_fragment_test.go",
"visibility_test.go",
],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index cb88e01..d2a9622 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -233,7 +233,8 @@
} else if m.ProductSpecific() {
container = "product"
} else if m.SystemExtSpecific() {
- container = "system_ext"
+ // system_ext and system partitions should be treated as one container
+ container = "system"
}
paths = append(paths, aconfigFiles[container]...)
diff --git a/android/arch.go b/android/arch.go
index a7868ba..d9ecb50 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -138,6 +138,13 @@
return a.Name
}
+func (a ArchType) Bitness() string {
+ if a.Multilib == "lib32" {
+ return "32"
+ }
+ return "64"
+}
+
const COMMON_VARIANT = "common"
var (
@@ -396,20 +403,21 @@
// device_supported and host_supported properties to determine which OsTypes are enabled for this
// module, then searches through the Targets to determine which have enabled Targets for this
// module.
-func osMutator(mctx BottomUpMutatorContext) {
- module := mctx.Module()
- base := module.base()
+type osTransitionMutator struct{}
- // Nothing to do for modules that are not architecture specific (e.g. a genrule).
- if !base.ArchSpecific() {
- return
- }
+type allOsInfo struct {
+ Os map[string]OsType
+ Variations []string
+}
- // Collect a list of OSTypes supported by this module based on the HostOrDevice value
- // passed to InitAndroidArchModule and the device_supported and host_supported properties.
+var allOsProvider = blueprint.NewMutatorProvider[*allOsInfo]("os_propagate")
+
+// moduleOSList collects a list of OSTypes supported by this module based on the HostOrDevice
+// value passed to InitAndroidArchModule and the device_supported and host_supported properties.
+func moduleOSList(ctx ConfigContext, base *ModuleBase) []OsType {
var moduleOSList []OsType
for _, os := range osTypeList {
- for _, t := range mctx.Config().Targets[os] {
+ for _, t := range ctx.Config().Targets[os] {
if base.supportsTarget(t) {
moduleOSList = append(moduleOSList, os)
break
@@ -417,53 +425,91 @@
}
}
- createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
+ if base.commonProperties.CreateCommonOSVariant {
+ // A CommonOS variant was requested so add it to the list of OS variants to
+ // create. It needs to be added to the end because it needs to depend on the
+ // the other variants and inter variant dependencies can only be created from a
+ // later variant in that list to an earlier one. That is because variants are
+ // always processed in the order in which they are created.
+ moduleOSList = append(moduleOSList, CommonOS)
+ }
+
+ return moduleOSList
+}
+
+func (o *osTransitionMutator) Split(ctx BaseModuleContext) []string {
+ module := ctx.Module()
+ base := module.base()
+
+ // Nothing to do for modules that are not architecture specific (e.g. a genrule).
+ if !base.ArchSpecific() {
+ return []string{""}
+ }
+
+ moduleOSList := moduleOSList(ctx, base)
// If there are no supported OSes then disable the module.
- if len(moduleOSList) == 0 && !createCommonOSVariant {
+ if len(moduleOSList) == 0 {
base.Disable()
- return
+ return []string{""}
}
// Convert the list of supported OsTypes to the variation names.
osNames := make([]string, len(moduleOSList))
+ osMapping := make(map[string]OsType, len(moduleOSList))
for i, os := range moduleOSList {
osNames[i] = os.String()
+ osMapping[osNames[i]] = os
}
- if createCommonOSVariant {
- // A CommonOS variant was requested so add it to the list of OS variants to
- // create. It needs to be added to the end because it needs to depend on the
- // the other variants in the list returned by CreateVariations(...) and inter
- // variant dependencies can only be created from a later variant in that list to
- // an earlier one. That is because variants are always processed in the order in
- // which they are returned from CreateVariations(...).
- osNames = append(osNames, CommonOS.Name)
- moduleOSList = append(moduleOSList, CommonOS)
+ SetProvider(ctx, allOsProvider, &allOsInfo{
+ Os: osMapping,
+ Variations: osNames,
+ })
+
+ return osNames
+}
+
+func (o *osTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (o *osTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+ module := ctx.Module()
+ base := module.base()
+
+ if !base.ArchSpecific() {
+ return ""
}
- // Create the variations, annotate each one with which OS it was created for, and
+ return incomingVariation
+}
+
+func (o *osTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ module := ctx.Module()
+ base := module.base()
+
+ if variation == "" {
+ return
+ }
+
+ allOsInfo, ok := ModuleProvider(ctx, allOsProvider)
+ if !ok {
+ panic(fmt.Errorf("missing allOsProvider"))
+ }
+
+ // Annotate this variant with which OS it was created for, and
// squash the appropriate OS-specific properties into the top level properties.
- modules := mctx.CreateVariations(osNames...)
- for i, m := range modules {
- m.base().commonProperties.CompileOS = moduleOSList[i]
- m.base().setOSProperties(mctx)
- }
+ base.commonProperties.CompileOS = allOsInfo.Os[variation]
+ base.setOSProperties(ctx)
- if createCommonOSVariant {
+ if variation == CommonOS.String() {
// A CommonOS variant was requested so add dependencies from it (the last one in
// the list) to the OS type specific variants.
- last := len(modules) - 1
- commonOSVariant := modules[last]
- commonOSVariant.base().commonProperties.CommonOSVariant = true
- for _, module := range modules[0:last] {
- // Ignore modules that are enabled. Note, this will only avoid adding
- // dependencies on OsType variants that are explicitly disabled in their
- // properties. The CommonOS variant will still depend on disabled variants
- // if they are disabled afterwards, e.g. in archMutator if
- if module.Enabled(mctx) {
- mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
- }
+ osList := allOsInfo.Variations[:len(allOsInfo.Variations)-1]
+ for _, os := range osList {
+ variation := []blueprint.Variation{{"os", os}}
+ ctx.AddVariationDependencies(variation, commonOsToOsSpecificVariantTag, ctx.ModuleName())
}
}
}
@@ -496,7 +542,7 @@
var DarwinUniversalVariantTag = archDepTag{name: "darwin universal binary"}
-// archMutator splits a module into a variant for each Target requested by the module. Target selection
+// archTransitionMutator splits a module into a variant for each Target requested by the module. Target selection
// for a module is in three levels, OsClass, multilib, and then Target.
// OsClass selection is determined by:
// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
@@ -527,25 +573,32 @@
//
// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass,
// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets().
-func archMutator(mctx BottomUpMutatorContext) {
- module := mctx.Module()
+type archTransitionMutator struct{}
+
+type allArchInfo struct {
+ Targets map[string]Target
+ MultiTargets []Target
+ Primary string
+ Multilib string
+}
+
+var allArchProvider = blueprint.NewMutatorProvider[*allArchInfo]("arch_propagate")
+
+func (a *archTransitionMutator) Split(ctx BaseModuleContext) []string {
+ module := ctx.Module()
base := module.base()
if !base.ArchSpecific() {
- return
+ return []string{""}
}
os := base.commonProperties.CompileOS
if os == CommonOS {
- // Make sure that the target related properties are initialized for the
- // CommonOS variant.
- addTargetProperties(module, commonTargetMap[os.Name], nil, true)
-
// Do not create arch specific variants for the CommonOS variant.
- return
+ return []string{""}
}
- osTargets := mctx.Config().Targets[os]
+ osTargets := ctx.Config().Targets[os]
image := base.commonProperties.ImageVariation
// Filter NativeBridge targets unless they are explicitly supported.
@@ -572,19 +625,18 @@
prefer32 := os == Windows
// Determine the multilib selection for this module.
- ignorePrefer32OnDevice := mctx.Config().IgnorePrefer32OnDevice()
- multilib, extraMultilib := decodeMultilib(base, os, ignorePrefer32OnDevice)
+ multilib, extraMultilib := decodeMultilib(ctx, base)
// Convert the multilib selection into a list of Targets.
targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
if err != nil {
- mctx.ModuleErrorf("%s", err.Error())
+ ctx.ModuleErrorf("%s", err.Error())
}
// If there are no supported targets disable the module.
if len(targets) == 0 {
base.Disable()
- return
+ return []string{""}
}
// If the module is using extraMultilib, decode the extraMultilib selection into
@@ -593,7 +645,7 @@
if extraMultilib != "" {
multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
if err != nil {
- mctx.ModuleErrorf("%s", err.Error())
+ ctx.ModuleErrorf("%s", err.Error())
}
multiTargets = filterHostCross(multiTargets, targets[0].HostCross)
}
@@ -601,7 +653,7 @@
// Recovery is always the primary architecture, filter out any other architectures.
// Common arch is also allowed
if image == RecoveryVariation {
- primaryArch := mctx.Config().DevicePrimaryArchType()
+ primaryArch := ctx.Config().DevicePrimaryArchType()
targets = filterToArch(targets, primaryArch, Common)
multiTargets = filterToArch(multiTargets, primaryArch, Common)
}
@@ -609,37 +661,109 @@
// If there are no supported targets disable the module.
if len(targets) == 0 {
base.Disable()
- return
+ return []string{""}
}
// Convert the targets into a list of arch variation names.
targetNames := make([]string, len(targets))
+ targetMapping := make(map[string]Target, len(targets))
for i, target := range targets {
targetNames[i] = target.ArchVariation()
+ targetMapping[targetNames[i]] = targets[i]
}
- // Create the variations, annotate each one with which Target it was created for, and
- // squash the appropriate arch-specific properties into the top level properties.
- modules := mctx.CreateVariations(targetNames...)
- for i, m := range modules {
- addTargetProperties(m, targets[i], multiTargets, i == 0)
- m.base().setArchProperties(mctx)
+ SetProvider(ctx, allArchProvider, &allArchInfo{
+ Targets: targetMapping,
+ MultiTargets: multiTargets,
+ Primary: targetNames[0],
+ Multilib: multilib,
+ })
+ return targetNames
+}
- // Install support doesn't understand Darwin+Arm64
- if os == Darwin && targets[i].HostCross {
- m.base().commonProperties.SkipInstall = true
+func (a *archTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (a *archTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+ module := ctx.Module()
+ base := module.base()
+
+ if !base.ArchSpecific() {
+ return ""
+ }
+
+ os := base.commonProperties.CompileOS
+ if os == CommonOS {
+ // Do not create arch specific variants for the CommonOS variant.
+ return ""
+ }
+
+ if incomingVariation == "" {
+ multilib, _ := decodeMultilib(ctx, base)
+ if multilib == "common" {
+ return "common"
}
}
+ return incomingVariation
+}
+
+func (a *archTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ module := ctx.Module()
+ base := module.base()
+ os := base.commonProperties.CompileOS
+
+ if os == CommonOS {
+ // Make sure that the target related properties are initialized for the
+ // CommonOS variant.
+ addTargetProperties(module, commonTargetMap[os.Name], nil, true)
+ return
+ }
+
+ if variation == "" {
+ return
+ }
+
+ if !base.ArchSpecific() {
+ panic(fmt.Errorf("found variation %q for non arch specifc module", variation))
+ }
+
+ allArchInfo, ok := ModuleProvider(ctx, allArchProvider)
+ if !ok {
+ return
+ }
+
+ target, ok := allArchInfo.Targets[variation]
+ if !ok {
+ panic(fmt.Errorf("missing Target for %q", variation))
+ }
+ primary := variation == allArchInfo.Primary
+ multiTargets := allArchInfo.MultiTargets
+
+ // Annotate the new variant with which Target it was created for, and
+ // squash the appropriate arch-specific properties into the top level properties.
+ addTargetProperties(ctx.Module(), target, multiTargets, primary)
+ base.setArchProperties(ctx)
+
+ // Install support doesn't understand Darwin+Arm64
+ if os == Darwin && target.HostCross {
+ base.commonProperties.SkipInstall = true
+ }
// Create a dependency for Darwin Universal binaries from the primary to secondary
// architecture. The module itself will be responsible for calling lipo to merge the outputs.
if os == Darwin {
- if multilib == "darwin_universal" && len(modules) == 2 {
- mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[1], modules[0])
- } else if multilib == "darwin_universal_common_first" && len(modules) == 3 {
- mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[2], modules[1])
+ isUniversalBinary := (allArchInfo.Multilib == "darwin_universal" && len(allArchInfo.Targets) == 2) ||
+ allArchInfo.Multilib == "darwin_universal_common_first" && len(allArchInfo.Targets) == 3
+ isPrimary := variation == ctx.Config().BuildArch.String()
+ hasSecondaryConfigured := len(ctx.Config().Targets[Darwin]) > 1
+ if isUniversalBinary && isPrimary && hasSecondaryConfigured {
+ secondaryArch := ctx.Config().Targets[Darwin][1].Arch.String()
+ variation := []blueprint.Variation{{"arch", secondaryArch}}
+ ctx.AddVariationDependencies(variation, DarwinUniversalVariantTag, ctx.ModuleName())
}
}
+
}
// addTargetProperties annotates a variant with the Target is is being compiled for, the list
@@ -656,7 +780,9 @@
// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that
// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
// the actual multilib in extraMultilib.
-func decodeMultilib(base *ModuleBase, os OsType, ignorePrefer32OnDevice bool) (multilib, extraMultilib string) {
+func decodeMultilib(ctx ConfigContext, base *ModuleBase) (multilib, extraMultilib string) {
+ os := base.commonProperties.CompileOS
+ ignorePrefer32OnDevice := ctx.Config().IgnorePrefer32OnDevice()
// First check the "android.compile_multilib" or "host.compile_multilib" properties.
switch os.Class {
case Device:
diff --git a/android/arch_list.go b/android/arch_list.go
index 9501c87..a47d5eb 100644
--- a/android/arch_list.go
+++ b/android/arch_list.go
@@ -29,6 +29,7 @@
"armv9-2a",
},
X86: {
+ "alderlake",
"amberlake",
"atom",
"broadwell",
@@ -53,6 +54,7 @@
"x86_64",
},
X86_64: {
+ "alderlake",
"amberlake",
"broadwell",
"goldmont",
@@ -165,6 +167,16 @@
},
},
X86: {
+ "alderlake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
"amberlake": {
"ssse3",
"sse4",
@@ -341,6 +353,16 @@
"sse4_2",
"popcnt",
},
+ "alderlake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
"amberlake": {
"ssse3",
"sse4",
diff --git a/android/arch_test.go b/android/arch_test.go
index 6134a06..57c9010 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -451,7 +451,7 @@
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
- if tt.goOS != runtime.GOOS {
+ if tt.goOS != "" && tt.goOS != runtime.GOOS {
t.Skipf("requries runtime.GOOS %s", tt.goOS)
}
diff --git a/android/config.go b/android/config.go
index 368e573..ca20012 100644
--- a/android/config.go
+++ b/android/config.go
@@ -238,6 +238,11 @@
return c.config.productVariables.ReleaseAconfigFlagDefaultPermission
}
+// Enable object size sanitizer
+func (c Config) ReleaseBuildObjectSizeSanitizer() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_BUILD_OBJECT_SIZE_SANITIZER")
+}
+
// The flag indicating behavior for the tree wrt building modules or using prebuilts
// derived from RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE
func (c Config) ReleaseDefaultModuleBuildFromSource() bool {
@@ -1247,7 +1252,7 @@
}
func (c *config) LibartImgHostBaseAddress() string {
- return "0x60000000"
+ return "0x70000000"
}
func (c *config) LibartImgDeviceBaseAddress() string {
@@ -1686,14 +1691,6 @@
return Bool(c.productVariables.EnforceProductPartitionInterface)
}
-func (c *config) EnforceInterPartitionJavaSdkLibrary() bool {
- return Bool(c.productVariables.EnforceInterPartitionJavaSdkLibrary)
-}
-
-func (c *config) InterPartitionJavaLibraryAllowList() []string {
- return c.productVariables.InterPartitionJavaLibraryAllowList
-}
-
func (c *config) ProductHiddenAPIStubs() []string {
return c.productVariables.ProductHiddenAPIStubs
}
@@ -1965,6 +1962,10 @@
return val, ok
}
+func (c *config) UseOptimizedResourceShrinkingByDefault() bool {
+ return c.productVariables.GetBuildFlagBool("RELEASE_USE_OPTIMIZED_RESOURCE_SHRINKING_BY_DEFAULT")
+}
+
func (c *config) UseResourceProcessorByDefault() bool {
return c.productVariables.GetBuildFlagBool("RELEASE_USE_RESOURCE_PROCESSOR_BY_DEFAULT")
}
diff --git a/android/deapexer.go b/android/deapexer.go
index dcae3e4..4049d2b 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -15,7 +15,6 @@
package android
import (
- "fmt"
"strings"
"github.com/google/blueprint"
@@ -109,10 +108,6 @@
return i.exportedModuleNames
}
-// Provider that can be used from within the `GenerateAndroidBuildActions` of a module that depends
-// on a `deapexer` module to retrieve its `DeapexerInfo`.
-var DeapexerProvider = blueprint.NewProvider[DeapexerInfo]()
-
// NewDeapexerInfo creates and initializes a DeapexerInfo that is suitable
// for use with a prebuilt_apex module.
//
@@ -169,45 +164,6 @@
RequiresFilesFromPrebuiltApex()
}
-// FindDeapexerProviderForModule searches through the direct dependencies of the current context
-// module for a DeapexerTag dependency and returns its DeapexerInfo. If a single nonambiguous
-// deapexer module isn't found then it returns it an error
-// clients should check the value of error and call ctx.ModuleErrof if a non nil error is received
-func FindDeapexerProviderForModule(ctx ModuleContext) (*DeapexerInfo, error) {
- var di *DeapexerInfo
- var err error
- ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) {
- if err != nil {
- // An err has been found. Do not visit further.
- return
- }
- c, ok := OtherModuleProvider(ctx, m, DeapexerProvider)
- if !ok {
- ctx.ModuleErrorf("Expected all deps with DeapexerTag to have a DeapexerProvider, but module %q did not", m.Name())
- return
- }
- p := &c
- if di != nil {
- // If two DeapexerInfo providers have been found then check if they are
- // equivalent. If they are then use the selected one, otherwise fail.
- if selected := equivalentDeapexerInfoProviders(di, p); selected != nil {
- di = selected
- return
- }
- err = fmt.Errorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s", di.ApexModuleName(), p.ApexModuleName())
- }
- di = p
- })
- if err != nil {
- return nil, err
- }
- if di != nil {
- return di, nil
- }
- ai, _ := ModuleProvider(ctx, ApexInfoProvider)
- return nil, fmt.Errorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName)
-}
-
// removeCompressedApexSuffix removes the _compressed suffix from the name if present.
func removeCompressedApexSuffix(name string) string {
return strings.TrimSuffix(name, "_compressed")
diff --git a/android/defaults.go b/android/defaults.go
index d3dbaed..3d06c69 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -101,6 +101,7 @@
// A restricted subset of context methods, similar to LoadHookContext.
type DefaultableHookContext interface {
EarlyModuleContext
+ OtherModuleProviderContext
CreateModule(ModuleFactory, ...interface{}) Module
AddMissingDependencies(missingDeps []string)
diff --git a/android/init.go b/android/init.go
index d5b486b..b462292 100644
--- a/android/init.go
+++ b/android/init.go
@@ -18,5 +18,6 @@
func init() {
gob.Register(ModuleOutPath{})
+ gob.Register(PhonyPath{})
gob.Register(unstableInfo{})
}
diff --git a/android/module.go b/android/module.go
index 47fdc23..d6c129a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -381,7 +381,7 @@
Native_bridge_supported *bool `android:"arch_variant"`
// init.rc files to be installed if this module is installed
- Init_rc []string `android:"arch_variant,path"`
+ Init_rc proptools.Configurable[[]string] `android:"arch_variant,path"`
// VINTF manifest fragments to be installed if this module is installed
Vintf_fragments proptools.Configurable[[]string] `android:"path"`
@@ -443,12 +443,6 @@
// Set at module initialization time by calling InitCommonOSAndroidMultiTargetsArchModule
CreateCommonOSVariant bool `blueprint:"mutated"`
- // If set to true then this variant is the CommonOS variant that has dependencies on its
- // OsType specific variants.
- //
- // Set by osMutator.
- CommonOSVariant bool `blueprint:"mutated"`
-
// When set to true, this module is not installed to the full install path (ex: under
// out/target/product/<name>/<partition>). It can be installed only to the packaging
// modules like android_filesystem.
@@ -1063,8 +1057,29 @@
}{}
func addVintfFragmentDeps(ctx BottomUpMutatorContext) {
+ // Vintf manifests in the recovery partition will be ignored.
+ if !ctx.Device() || ctx.Module().InstallInRecovery() {
+ return
+ }
+
+ deviceConfig := ctx.DeviceConfig()
+
mod := ctx.Module()
- ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...)
+ vintfModules := ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...)
+
+ modPartition := mod.PartitionTag(deviceConfig)
+ for _, vintf := range vintfModules {
+ if vintfModule, ok := vintf.(*vintfFragmentModule); ok {
+ vintfPartition := vintfModule.PartitionTag(deviceConfig)
+ if modPartition != vintfPartition {
+ ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.",
+ mod.Name(), modPartition,
+ vintfModule.Name(), vintfPartition)
+ }
+ } else {
+ ctx.ModuleErrorf("Only vintf_fragment type module should be listed in vintf_fragment_modules : %q", vintf.Name())
+ }
+ }
}
// AddProperties "registers" the provided props
@@ -1221,7 +1236,7 @@
// True if the current variant is a CommonOS variant, false otherwise.
func (m *ModuleBase) IsCommonOSVariant() bool {
- return m.commonProperties.CommonOSVariant
+ return m.commonProperties.CompileOS == CommonOS
}
// supportsTarget returns true if the given Target is supported by the current module.
@@ -1346,6 +1361,14 @@
return m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled)
}
+// Returns a copy of the enabled property, useful for passing it on to sub-modules
+func (m *ModuleBase) EnabledProperty() proptools.Configurable[bool] {
+ if m.commonProperties.ForcedDisabled {
+ return proptools.NewSimpleConfigurable(false)
+ }
+ return m.commonProperties.Enabled.Clone()
+}
+
func (m *ModuleBase) Disable() {
m.commonProperties.ForcedDisabled = true
}
@@ -1853,7 +1876,7 @@
// so only a single rule is created for each init.rc or vintf fragment file.
if !m.InVendorRamdisk() {
- ctx.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
+ ctx.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc.GetOrDefault(ctx, nil))
rcDir := PathForModuleInstall(ctx, "etc", "init")
for _, src := range ctx.initRcPaths {
installedInitRc := rcDir.Join(ctx, src.Base())
@@ -2204,9 +2227,15 @@
return proptools.Bool(m.commonProperties.Native_bridge_supported)
}
+type ConfigContext interface {
+ Config() Config
+}
+
type ConfigurableEvaluatorContext interface {
+ OtherModuleProviderContext
Config() Config
OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+ HasMutatorFinished(mutatorName string) bool
}
type configurationEvalutor struct {
@@ -2228,6 +2257,12 @@
func (e configurationEvalutor) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
ctx := e.ctx
m := e.m
+
+ if !ctx.HasMutatorFinished("defaults") {
+ ctx.OtherModulePropertyErrorf(m, property, "Cannot evaluate configurable property before the defaults mutator has run")
+ return proptools.ConfigurableValueUndefined()
+ }
+
switch condition.FunctionName() {
case "release_flag":
if condition.NumArgs() != 1 {
diff --git a/android/module_test.go b/android/module_test.go
index d64e3a5..d76d9b3 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -1080,3 +1080,29 @@
})
}
}
+
+func TestVintfFragmentModulesChecksPartition(t *testing.T) {
+ bp := `
+ vintf_fragment {
+ name: "vintfModA",
+ src: "test_vintf_file",
+ vendor: true,
+ }
+ deps {
+ name: "modA",
+ vintf_fragment_modules: [
+ "vintfModA",
+ ]
+ }
+ `
+
+ testPreparer := GroupFixturePreparers(
+ PrepareForTestWithAndroidBuildComponents,
+ prepareForModuleTests,
+ )
+
+ testPreparer.
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(
+ "Module .+ and Vintf_fragment .+ are installed to different partitions.")).
+ RunTestWithBp(t, bp)
+}
diff --git a/android/mutator.go b/android/mutator.go
index 6f8990d..434e3ba 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -26,7 +26,7 @@
// run Pre-deps mutators
// run depsMutator
// run PostDeps mutators
-// run FinalDeps mutators (CreateVariations disallowed in this phase)
+// run FinalDeps mutators (TransitionMutators disallowed in this phase)
// continue on to GenerateAndroidBuildActions
// collateGloballyRegisteredMutators constructs the list of mutators that have been registered
@@ -148,9 +148,9 @@
}
func registerArchMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("os", osMutator).Parallel()
+ ctx.Transition("os", &osTransitionMutator{})
ctx.Transition("image", &imageTransitionMutator{})
- ctx.BottomUp("arch", archMutator).Parallel()
+ ctx.Transition("arch", &archTransitionMutator{})
}
var preDeps = []RegisterMutatorFunc{
@@ -231,36 +231,6 @@
// module's dependency list.
AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string)
- // CreateVariations splits a module into multiple variants, one for each name in the variationNames
- // parameter. It returns a list of new modules in the same order as the variationNames
- // list.
- //
- // If any of the dependencies of the module being operated on were already split
- // by calling CreateVariations with the same name, the dependency will automatically
- // be updated to point the matching variant.
- //
- // If a module is split, and then a module depending on the first module is not split
- // when the Mutator is later called on it, the dependency of the depending module will
- // automatically be updated to point to the first variant.
- CreateVariations(...string) []Module
-
- // CreateLocationVariations splits a module into multiple variants, one for each name in the variantNames
- // parameter. It returns a list of new modules in the same order as the variantNames
- // list.
- //
- // Local variations do not affect automatic dependency resolution - dependencies added
- // to the split module via deps or DynamicDependerModule must exactly match a variant
- // that contains all the non-local variations.
- CreateLocalVariations(...string) []Module
-
- // SetDependencyVariation sets all dangling dependencies on the current module to point to the variation
- // with given name. This function ignores the default variation set by SetDefaultDependencyVariation.
- SetDependencyVariation(string)
-
- // SetDefaultDependencyVariation sets the default variation when a dangling reference is detected
- // during the subsequent calls on Create*Variations* functions. To reset, set it to nil.
- SetDefaultDependencyVariation(*string)
-
// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
// argument to select which variant of the dependency to use. It returns a slice of modules for
// each dependency (some entries may be nil). A variant of the dependency must exist that matches
@@ -287,12 +257,6 @@
// be ordered correctly for all future mutator passes.
AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module
- // AddInterVariantDependency adds a dependency between two variants of the same module. Variants are always
- // ordered in the same orderas they were listed in CreateVariations, and AddInterVariantDependency does not change
- // that ordering, but it associates a DependencyTag with the dependency and makes it visible to VisitDirectDeps,
- // WalkDeps, etc.
- AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module)
-
// ReplaceDependencies finds all the variants of the module with the specified name, then
// replaces all dependencies onto those variants with the current variant of this module.
// Replacements don't take effect until after the mutator pass is finished.
@@ -303,30 +267,6 @@
// as long as the supplied predicate returns true.
// Replacements don't take effect until after the mutator pass is finished.
ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
-
- // AliasVariation takes a variationName that was passed to CreateVariations for this module,
- // and creates an alias from the current variant (before the mutator has run) to the new
- // variant. The alias will be valid until the next time a mutator calls CreateVariations or
- // CreateLocalVariations on this module without also calling AliasVariation. The alias can
- // be used to add dependencies on the newly created variant using the variant map from
- // before CreateVariations was run.
- AliasVariation(variationName string)
-
- // CreateAliasVariation takes a toVariationName that was passed to CreateVariations for this
- // module, and creates an alias from a new fromVariationName variant the toVariationName
- // variant. The alias will be valid until the next time a mutator calls CreateVariations or
- // CreateLocalVariations on this module without also calling AliasVariation. The alias can
- // be used to add dependencies on the toVariationName variant using the fromVariationName
- // variant.
- CreateAliasVariation(fromVariationName, toVariationName string)
-
- // SetVariationProvider sets the value for a provider for the given newly created variant of
- // the current module, i.e. one of the Modules returned by CreateVariations.. It panics if
- // not called during the appropriate mutator or GenerateBuildActions pass for the provider,
- // if the value is not of the appropriate type, or if the module is not a newly created
- // variant of the current module. The value should not be modified after being passed to
- // SetVariationProvider.
- SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{})
}
// An outgoingTransitionContextImpl and incomingTransitionContextImpl is created for every dependency of every module
@@ -516,6 +456,9 @@
}
func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string {
+ if a.finalPhase {
+ panic("TransitionMutator not allowed in FinalDepsMutators")
+ }
if m, ok := ctx.Module().(Module); ok {
moduleContext := m.base().baseModuleContextFactory(ctx)
return a.mutator.Split(&moduleContext)
@@ -760,51 +703,6 @@
}
b.bp.AddReverseDependency(module, tag, name)
}
-
-func (b *bottomUpMutatorContext) CreateVariations(variations ...string) []Module {
- if b.finalPhase {
- panic("CreateVariations not allowed in FinalDepsMutators")
- }
-
- modules := b.bp.CreateVariations(variations...)
-
- aModules := make([]Module, len(modules))
- for i := range variations {
- aModules[i] = modules[i].(Module)
- base := aModules[i].base()
- base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
- base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
- }
-
- return aModules
-}
-
-func (b *bottomUpMutatorContext) CreateLocalVariations(variations ...string) []Module {
- if b.finalPhase {
- panic("CreateLocalVariations not allowed in FinalDepsMutators")
- }
-
- modules := b.bp.CreateLocalVariations(variations...)
-
- aModules := make([]Module, len(modules))
- for i := range variations {
- aModules[i] = modules[i].(Module)
- base := aModules[i].base()
- base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
- base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
- }
-
- return aModules
-}
-
-func (b *bottomUpMutatorContext) SetDependencyVariation(variation string) {
- b.bp.SetDependencyVariation(variation)
-}
-
-func (b *bottomUpMutatorContext) SetDefaultDependencyVariation(variation *string) {
- b.bp.SetDefaultDependencyVariation(variation)
-}
-
func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
names ...string) []blueprint.Module {
if b.baseModuleContext.checkedMissingDeps() {
@@ -822,10 +720,6 @@
return b.bp.AddFarVariationDependencies(variations, tag, names...)
}
-func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) {
- b.bp.AddInterVariantDependency(tag, from, to)
-}
-
func (b *bottomUpMutatorContext) ReplaceDependencies(name string) {
if b.baseModuleContext.checkedMissingDeps() {
panic("Adding deps not allowed after checking for missing deps")
@@ -839,15 +733,3 @@
}
b.bp.ReplaceDependenciesIf(name, predicate)
}
-
-func (b *bottomUpMutatorContext) AliasVariation(variationName string) {
- b.bp.AliasVariation(variationName)
-}
-
-func (b *bottomUpMutatorContext) CreateAliasVariation(fromVariationName, toVariationName string) {
- b.bp.CreateAliasVariation(fromVariationName, toVariationName)
-}
-
-func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{}) {
- b.bp.SetVariationProvider(module, provider, value)
-}
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 21eebd2..5d4074a 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -81,6 +81,40 @@
AssertDeepEquals(t, "foo missing deps", []string{"added_missing_dep", "regular_missing_dep"}, foo.missingDeps)
}
+type testTransitionMutator struct {
+ split func(ctx BaseModuleContext) []string
+ outgoingTransition func(ctx OutgoingTransitionContext, sourceVariation string) string
+ incomingTransition func(ctx IncomingTransitionContext, incomingVariation string) string
+ mutate func(ctx BottomUpMutatorContext, variation string)
+}
+
+func (t *testTransitionMutator) Split(ctx BaseModuleContext) []string {
+ if t.split != nil {
+ return t.split(ctx)
+ }
+ return []string{""}
+}
+
+func (t *testTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
+ if t.outgoingTransition != nil {
+ return t.outgoingTransition(ctx, sourceVariation)
+ }
+ return sourceVariation
+}
+
+func (t *testTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+ if t.incomingTransition != nil {
+ return t.incomingTransition(ctx, incomingVariation)
+ }
+ return incomingVariation
+}
+
+func (t *testTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ if t.mutate != nil {
+ t.mutate(ctx, variation)
+ }
+}
+
func TestModuleString(t *testing.T) {
bp := `
test {
@@ -94,9 +128,11 @@
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("pre_arch", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateVariations("a", "b")
+ ctx.Transition("pre_arch", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"a", "b"}
+ },
})
ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
@@ -105,16 +141,23 @@
})
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("pre_deps", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateVariations("c", "d")
+ ctx.Transition("pre_deps", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"c", "d"}
+ },
})
})
ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("post_deps", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateLocalVariations("e", "f")
+ ctx.Transition("post_deps", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"e", "f"}
+ },
+ outgoingTransition: func(ctx OutgoingTransitionContext, sourceVariation string) string {
+ return ""
+ },
})
ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
@@ -138,15 +181,15 @@
"foo{pre_arch:b}",
"foo{pre_arch:a}",
- // After rename_top_down.
- "foo_renamed1{pre_arch:a}",
+ // After rename_top_down (reversed because pre_deps TransitionMutator.Split is TopDown).
"foo_renamed1{pre_arch:b}",
+ "foo_renamed1{pre_arch:a}",
- // After pre_deps.
- "foo_renamed1{pre_arch:a,pre_deps:c}",
- "foo_renamed1{pre_arch:a,pre_deps:d}",
- "foo_renamed1{pre_arch:b,pre_deps:c}",
+ // After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
"foo_renamed1{pre_arch:b,pre_deps:d}",
+ "foo_renamed1{pre_arch:b,pre_deps:c}",
+ "foo_renamed1{pre_arch:a,pre_deps:d}",
+ "foo_renamed1{pre_arch:a,pre_deps:c}",
// After post_deps.
"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
@@ -202,8 +245,10 @@
ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1")
}
})
- ctx.BottomUp("variant", func(ctx BottomUpMutatorContext) {
- ctx.CreateLocalVariations("a", "b")
+ ctx.Transition("variant", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ return []string{"a", "b"}
+ },
})
})
@@ -242,28 +287,21 @@
AssertDeepEquals(t, "final", finalWant, finalGot)
}
-func TestNoCreateVariationsInFinalDeps(t *testing.T) {
- checkErr := func() {
- if err := recover(); err == nil || !strings.Contains(fmt.Sprintf("%s", err), "not allowed in FinalDepsMutators") {
- panic("Expected FinalDepsMutators consistency check to fail")
- }
- }
-
+func TestTransitionMutatorInFinalDeps(t *testing.T) {
GroupFixturePreparers(
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("vars", func(ctx BottomUpMutatorContext) {
- defer checkErr()
- ctx.CreateVariations("a", "b")
- })
- ctx.BottomUp("local_vars", func(ctx BottomUpMutatorContext) {
- defer checkErr()
- ctx.CreateLocalVariations("a", "b")
+ ctx.Transition("vars", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ return []string{"a", "b"}
+ },
})
})
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
}),
FixtureWithRootAndroidBp(`test {name: "foo"}`),
- ).RunTest(t)
+ ).
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern("not allowed in FinalDepsMutators")).
+ RunTest(t)
}
diff --git a/android/packaging_test.go b/android/packaging_test.go
index 0f7bb39..f5b1020 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -118,6 +118,7 @@
}
result := GroupFixturePreparers(
+ PrepareForTestWithDefaults,
PrepareForTestWithArchMutator,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("component", componentTestModuleFactory)
diff --git a/android/paths.go b/android/paths.go
index 0a4f891..0d94f03 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -91,6 +91,7 @@
// the Path methods that rely on module dependencies having been resolved.
type ModuleWithDepsPathContext interface {
EarlyModulePathContext
+ OtherModuleProviderContext
VisitDirectDepsBlueprint(visit func(blueprint.Module))
OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
HasMutatorFinished(mutatorName string) bool
diff --git a/android/prebuilt.go b/android/prebuilt.go
index fd5a6ea..4f04d05 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -359,8 +359,8 @@
//
// This function is for use on dependencies after PrebuiltPostDepsMutator has
// run - any dependency that is registered before that will already reference
-// the right module. This function is only safe to call after all mutators that
-// may call CreateVariations, e.g. in GenerateAndroidBuildActions.
+// the right module. This function is only safe to call after all TransitionMutators
+// have run, e.g. in GenerateAndroidBuildActions.
func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module {
if !module.IsReplacedByPrebuilt() {
return module
diff --git a/android/product_config.go b/android/product_config.go
index 04180bf..ce3acc9 100644
--- a/android/product_config.go
+++ b/android/product_config.go
@@ -14,7 +14,9 @@
package android
-import "github.com/google/blueprint/proptools"
+import (
+ "github.com/google/blueprint/proptools"
+)
func init() {
ctx := InitRegistrationContext
diff --git a/android/product_config_to_bp.go b/android/product_config_to_bp.go
new file mode 100644
index 0000000..680328f
--- /dev/null
+++ b/android/product_config_to_bp.go
@@ -0,0 +1,35 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+func init() {
+ ctx := InitRegistrationContext
+ ctx.RegisterParallelSingletonType("product_config_to_bp_singleton", productConfigToBpSingletonFactory)
+}
+
+type productConfigToBpSingleton struct{}
+
+func (s *productConfigToBpSingleton) GenerateBuildActions(ctx SingletonContext) {
+ // TODO: update content from make-based product config
+ var content string
+ generatedBp := PathForOutput(ctx, "soong_generated_product_config.bp")
+ WriteFileRule(ctx, generatedBp, content)
+ ctx.Phony("product_config_to_bp", generatedBp)
+}
+
+// productConfigToBpSingleton generates a bp file from make-based product config
+func productConfigToBpSingletonFactory() Singleton {
+ return &productConfigToBpSingleton{}
+}
diff --git a/android/singleton_module_test.go b/android/singleton_module_test.go
index 3b1bf39..3b8c6b2 100644
--- a/android/singleton_module_test.go
+++ b/android/singleton_module_test.go
@@ -96,12 +96,6 @@
}
}
-func testVariantSingletonModuleMutator(ctx BottomUpMutatorContext) {
- if _, ok := ctx.Module().(*testSingletonModule); ok {
- ctx.CreateVariations("a", "b")
- }
-}
-
func TestVariantSingletonModule(t *testing.T) {
if testing.Short() {
t.Skip("test fails with data race enabled")
@@ -116,7 +110,11 @@
prepareForSingletonModuleTest,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("test_singleton_module_mutator", testVariantSingletonModuleMutator)
+ ctx.Transition("test_singleton_module_mutator", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ return []string{"a", "b"}
+ },
+ })
})
}),
).
diff --git a/android/team_proto/Android.bp b/android/team_proto/Android.bp
index 7e2a4c1..5faaaf1 100644
--- a/android/team_proto/Android.bp
+++ b/android/team_proto/Android.bp
@@ -40,4 +40,8 @@
proto: {
canonical_path_from_root: false,
},
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//tools/asuite/team_build_scripts",
+ ],
}
diff --git a/android/testing.go b/android/testing.go
index 1ee6e4c..196b22e 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -1330,6 +1330,10 @@
return ctx.ctx.HasMutatorFinished(mutatorName)
}
+func (ctx *panickingConfigAndErrorContext) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
+ return ctx.ctx.otherModuleProvider(m, p)
+}
+
func PanickingConfigAndErrorContext(ctx *TestContext) ConfigurableEvaluatorContext {
return &panickingConfigAndErrorContext{
ctx: ctx,
diff --git a/android/variable.go b/android/variable.go
index e0d512d..7041f49 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -428,9 +428,6 @@
EnforceProductPartitionInterface *bool `json:",omitempty"`
- EnforceInterPartitionJavaSdkLibrary *bool `json:",omitempty"`
- InterPartitionJavaLibraryAllowList []string `json:",omitempty"`
-
BoardUsesRecoveryAsBoot *bool `json:",omitempty"`
BoardKernelBinaries []string `json:",omitempty"`
diff --git a/apex/Android.bp b/apex/Android.bp
index ef2f755..4848513 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -42,4 +42,6 @@
"systemserver_classpath_fragment_test.go",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/apex/apex.go b/apex/apex.go
index 786f732..aff69c1 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -49,15 +49,10 @@
ctx.RegisterModuleType("override_apex", OverrideApexFactory)
ctx.RegisterModuleType("apex_set", apexSetFactory)
- ctx.PreArchMutators(registerPreArchMutators)
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
}
-func registerPreArchMutators(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("prebuilt_apex_module_creator", prebuiltApexModuleCreatorMutator).Parallel()
-}
-
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
}
@@ -2740,6 +2735,12 @@
return
}
+ // Temporarily bypass /product APEXes with a specific prefix.
+ // TODO: b/352818241 - Remove this after APEX availability is enforced for /product APEXes.
+ if a.ProductSpecific() && strings.HasPrefix(a.ApexVariationName(), "com.sdv.") {
+ return
+ }
+
// Coverage build adds additional dependencies for the coverage-only runtime libraries.
// Requiring them and their transitive depencies with apex_available is not right
// because they just add noise.
diff --git a/apex/apex_test.go b/apex/apex_test.go
index cc46bee..8cb8a91 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3685,7 +3685,7 @@
}
func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleName string, variant string, files []string) {
- deapexer := ctx.ModuleForTests(moduleName+".deapexer", variant).Description("deapex")
+ deapexer := ctx.ModuleForTests(moduleName, variant).Description("deapex")
outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1)
if deapexer.Output != nil {
outputs = append(outputs, deapexer.Output.String())
@@ -4885,236 +4885,6 @@
func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
}
-// These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
-// propagation of paths to dex implementation jars from the former to the latter.
-func TestPrebuiltExportDexImplementationJars(t *testing.T) {
- transform := android.NullFixturePreparer
-
- checkDexJarBuildPath := func(t *testing.T, ctx *android.TestContext, name string) {
- t.Helper()
- // Make sure the import has been given the correct path to the dex jar.
- p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
- dexJarBuildPath := p.DexJarBuildPath(moduleErrorfTestCtx{}).PathOrNil()
- stem := android.RemoveOptionalPrebuiltPrefix(name)
- android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.",
- ".intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
- android.NormalizePathForTesting(dexJarBuildPath))
- }
-
- checkDexJarInstallPath := func(t *testing.T, ctx *android.TestContext, name string) {
- t.Helper()
- // Make sure the import has been given the correct path to the dex jar.
- p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
- dexJarBuildPath := p.DexJarInstallPath()
- stem := android.RemoveOptionalPrebuiltPrefix(name)
- android.AssertStringEquals(t, "DexJarInstallPath should be apex-related path.",
- "target/product/test_device/apex/myapex/javalib/"+stem+".jar",
- android.NormalizePathForTesting(dexJarBuildPath))
- }
-
- ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext, name string) {
- t.Helper()
- // Make sure that an apex variant is not created for the source module.
- android.AssertArrayString(t, "Check if there is no source variant",
- []string{"android_common"},
- ctx.ModuleVariantsForTests(name))
- }
-
- t.Run("prebuilt only", func(t *testing.T) {
- bp := `
- prebuilt_apex {
- name: "myapex",
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["libfoo", "libbar"],
- }
-
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- sdk_version: "core_current",
- }
-
- java_sdk_library_import {
- name: "libbar",
- public: {
- jars: ["libbar.jar"],
- },
- }
- `
-
- // Make sure that dexpreopt can access dex implementation files from the prebuilt.
- ctx := testDexpreoptWithApexes(t, bp, "", transform)
-
- deapexerName := deapexerModuleName("prebuilt_myapex")
- android.AssertStringEquals(t, "APEX module name from deapexer name", "prebuilt_myapex", apexModuleName(deapexerName))
-
- // Make sure that the deapexer has the correct input APEX.
- deapexer := ctx.ModuleForTests(deapexerName, "android_common")
- rule := deapexer.Rule("deapexer")
- if expected, actual := []string{"myapex-arm64.apex"}, android.NormalizePathsForTesting(rule.Implicits); !reflect.DeepEqual(expected, actual) {
- t.Errorf("expected: %q, found: %q", expected, actual)
- }
-
- // Make sure that the prebuilt_apex has the correct input APEX.
- prebuiltApex := ctx.ModuleForTests("myapex", "android_common_myapex")
- rule = prebuiltApex.Rule("android/soong/android.Cp")
- if expected, actual := "myapex-arm64.apex", android.NormalizePathForTesting(rule.Input); !reflect.DeepEqual(expected, actual) {
- t.Errorf("expected: %q, found: %q", expected, actual)
- }
-
- checkDexJarBuildPath(t, ctx, "libfoo")
- checkDexJarInstallPath(t, ctx, "libfoo")
-
- checkDexJarBuildPath(t, ctx, "libbar")
- checkDexJarInstallPath(t, ctx, "libbar")
- })
-
- t.Run("prebuilt with source preferred", func(t *testing.T) {
-
- bp := `
- apex {
- name: "myapex",
- key: "myapex.key",
- updatable: false,
- java_libs: [
- "libfoo",
- "libbar",
- ],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- prebuilt_apex {
- name: "myapex",
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["libfoo", "libbar"],
- }
-
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- apex_available: [
- "myapex",
- ],
- compile_dex: true,
- sdk_version: "core_current",
- }
-
- java_library {
- name: "libfoo",
- srcs: ["foo/bar/MyClass.java"],
- apex_available: [
- "myapex",
- ],
- compile_dex: true,
- sdk_version: "core_current",
- }
-
- java_sdk_library_import {
- name: "libbar",
- public: {
- jars: ["libbar.jar"],
- },
- apex_available: [
- "myapex",
- ],
- compile_dex: true,
- }
-
- java_sdk_library {
- name: "libbar",
- srcs: ["foo/bar/MyClass.java"],
- unsafe_ignore_missing_latest_api: true,
- apex_available: [
- "myapex",
- ],
- compile_dex: true,
- sdk_version: "core_current",
- }
- `
-
- // Make sure that dexpreopt can access dex implementation files from the prebuilt.
- ctx := testDexpreoptWithApexes(t, bp, "", transform)
-
- checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
- checkDexJarInstallPath(t, ctx, "prebuilt_libfoo")
-
- checkDexJarBuildPath(t, ctx, "prebuilt_libbar")
- checkDexJarInstallPath(t, ctx, "prebuilt_libbar")
- })
-
- t.Run("prebuilt preferred with source", func(t *testing.T) {
- bp := `
- prebuilt_apex {
- name: "myapex",
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["libfoo", "libbar"],
- }
-
- java_import {
- name: "libfoo",
- prefer: true,
- jars: ["libfoo.jar"],
- }
-
- java_library {
- name: "libfoo",
- sdk_version: "core_current",
- }
-
- java_sdk_library_import {
- name: "libbar",
- prefer: true,
- public: {
- jars: ["libbar.jar"],
- },
- }
-
- java_sdk_library {
- name: "libbar",
- srcs: ["foo/bar/MyClass.java"],
- unsafe_ignore_missing_latest_api: true,
- }
- `
-
- // Make sure that dexpreopt can access dex implementation files from the prebuilt.
- ctx := testDexpreoptWithApexes(t, bp, "", transform)
-
- checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
- checkDexJarInstallPath(t, ctx, "prebuilt_libfoo")
- ensureNoSourceVariant(t, ctx, "libfoo")
-
- checkDexJarBuildPath(t, ctx, "prebuilt_libbar")
- checkDexJarInstallPath(t, ctx, "prebuilt_libbar")
- ensureNoSourceVariant(t, ctx, "libbar")
- })
-}
-
func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
preparer := android.GroupFixturePreparers(
java.FixtureConfigureApexBootJars("myapex:libfoo", "myapex:libbar"),
@@ -5137,23 +4907,6 @@
}),
)
- checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
- t.Helper()
- s := ctx.ModuleForTests("dex_bootjars", "android_common")
- foundLibfooJar := false
- base := stem + ".jar"
- for _, output := range s.AllOutputs() {
- if filepath.Base(output) == base {
- foundLibfooJar = true
- buildRule := s.Output(output)
- android.AssertStringEquals(t, "boot dex jar path", bootDexJarPath, buildRule.Input.String())
- }
- }
- if !foundLibfooJar {
- t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().SoongOutDir(), s.AllOutputs()))
- }
- }
-
checkHiddenAPIIndexFromClassesInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
t.Helper()
platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
@@ -5206,12 +4959,14 @@
},
}
- java_import {
+ java_sdk_library_import {
name: "libfoo",
- jars: ["libfoo.jar"],
+ public: {
+ jars: ["libfoo.jar"],
+ },
apex_available: ["myapex"],
+ shared_library: false,
permitted_packages: ["foo"],
- sdk_version: "core_current",
}
java_sdk_library_import {
@@ -5226,8 +4981,6 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -5243,18 +4996,10 @@
apex_set {
name: "myapex",
set: "myapex.apks",
- exported_java_libs: ["myjavalib"],
exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
exported_systemserverclasspath_fragments: ["my-systemserverclasspath-fragment"],
}
- java_import {
- name: "myjavalib",
- jars: ["myjavalib.jar"],
- apex_available: ["myapex"],
- permitted_packages: ["javalib"],
- }
-
prebuilt_bootclasspath_fragment {
name: "my-bootclasspath-fragment",
contents: ["libfoo", "libbar"],
@@ -5275,13 +5020,17 @@
apex_available: ["myapex"],
}
- java_import {
+ java_sdk_library_import {
name: "libfoo",
- jars: ["libfoo.jar"],
+ public: {
+ jars: ["libfoo.jar"],
+ },
apex_available: ["myapex"],
- permitted_packages: ["foo"],
+ shared_library: false,
+ permitted_packages: ["libfoo"],
}
+
java_sdk_library_import {
name: "libbar",
public: {
@@ -5304,8 +5053,6 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -5459,13 +5206,15 @@
},
}
- java_import {
+ java_sdk_library_import {
name: "libfoo",
prefer: true,
- jars: ["libfoo.jar"],
+ public: {
+ jars: ["libfoo.jar"],
+ },
apex_available: ["myapex"],
- permitted_packages: ["foo"],
- sdk_version: "core_current",
+ shared_library: false,
+ permitted_packages: ["libfoo"],
}
java_library {
@@ -5497,8 +5246,6 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -5597,8 +5344,6 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -5710,8 +5455,6 @@
)
ctx := testDexpreoptWithApexes(t, bp, "", preparer2, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -6270,6 +6013,87 @@
system_shared_libs: [],
apex_available: ["otherapex"],
}`)
+
+ // 'apex_available' check is bypassed for /product apex with a specific prefix.
+ // TODO: b/352818241 - Remove below two cases after APEX availability is enforced for /product APEXes.
+ testApex(t, `
+ apex {
+ name: "com.sdv.myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ product_specific: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "com.any.otherapex",
+ key: "otherapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "otherapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["com.any.otherapex"],
+ product_specific: true,
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
+ "system/sepolicy/apex/com.any.otherapex-file_contexts": nil,
+ }))
+
+ // 'apex_available' check is not bypassed for non-product apex with a specific prefix.
+ testApexError(t, "requires \"libfoo\" that doesn't list the APEX under 'apex_available'.", `
+ apex {
+ name: "com.sdv.myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "com.any.otherapex",
+ key: "otherapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "otherapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["com.any.otherapex"],
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
+ "system/sepolicy/apex/com.any.otherapex-file_contexts": nil,
+ }))
}
func TestApexAvailable_IndirectDep(t *testing.T) {
@@ -6315,6 +6139,91 @@
stl: "none",
system_shared_libs: [],
}`)
+
+ // 'apex_available' check is bypassed for /product apex with a specific prefix.
+ // TODO: b/352818241 - Remove below two cases after APEX availability is enforced for /product APEXes.
+ testApex(t, `
+ apex {
+ name: "com.sdv.myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ product_specific: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ shared_libs: ["libbar"],
+ system_shared_libs: [],
+ apex_available: ["com.sdv.myapex"],
+ product_specific: true,
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ shared_libs: ["libbaz"],
+ system_shared_libs: [],
+ apex_available: ["com.sdv.myapex"],
+ product_specific: true,
+ }
+
+ cc_library {
+ name: "libbaz",
+ stl: "none",
+ system_shared_libs: [],
+ product_specific: true,
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
+ }))
+
+ // 'apex_available' check is not bypassed for non-product apex with a specific prefix.
+ testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.`, `
+ apex {
+ name: "com.sdv.myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ shared_libs: ["libbar"],
+ system_shared_libs: [],
+ apex_available: ["com.sdv.myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ shared_libs: ["libbaz"],
+ system_shared_libs: [],
+ apex_available: ["com.sdv.myapex"],
+ }
+
+ cc_library {
+ name: "libbaz",
+ stl: "none",
+ system_shared_libs: [],
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
+ }))
}
func TestApexAvailable_IndirectStaticDep(t *testing.T) {
@@ -7339,7 +7248,7 @@
java_library {
name: "bar",
srcs: ["a.java"],
- libs: ["foo"],
+ libs: ["foo.impl"],
apex_available: ["myapex"],
sdk_version: "none",
system_modules: "none",
@@ -7392,7 +7301,7 @@
java_library {
name: "bar",
srcs: ["a.java"],
- libs: ["foo"],
+ libs: ["foo.stubs"],
sdk_version: "none",
system_modules: "none",
}
@@ -7446,7 +7355,7 @@
java_library {
name: "bar",
srcs: ["a.java"],
- libs: ["foo"],
+ libs: ["foo.impl"],
apex_available: ["myapex"],
sdk_version: "none",
system_modules: "none",
@@ -8119,9 +8028,9 @@
ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
// Check that the extractor produces the correct output file from the correct input file.
- extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.hwasan.apks"
- m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("myapex", "android_common_myapex")
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
@@ -8146,10 +8055,10 @@
}
`)
- m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("myapex", "android_common_myapex")
// Check that the extractor produces the correct apks file from the input module
- extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.apks"
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
@@ -8211,189 +8120,6 @@
return result.TestContext
}
-func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
- preparers := android.GroupFixturePreparers(
- java.PrepareForTestWithJavaDefaultModules,
- prepareForTestWithBootclasspathFragment,
- dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:libfoo"),
- PrepareForTestWithApexBuildComponents,
- ).
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art"))
-
- bpBase := `
- apex_set {
- name: "com.android.art",
- installable: true,
- exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
- set: "myapex.apks",
- }
-
- apex_set {
- name: "com.mycompany.android.art",
- apex_name: "com.android.art",
- installable: true,
- exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
- set: "company-myapex.apks",
- }
-
- prebuilt_bootclasspath_fragment {
- name: "art-bootclasspath-fragment",
- apex_available: ["com.android.art"],
- hidden_api: {
- annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
- metadata: "my-bootclasspath-fragment/metadata.csv",
- index: "my-bootclasspath-fragment/index.csv",
- stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
- all_flags: "my-bootclasspath-fragment/all-flags.csv",
- },
- %s
- }
- `
-
- t.Run("java_import", func(t *testing.T) {
- _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- apex_available: ["com.android.art"],
- }
- `)
- })
-
- t.Run("java_sdk_library_import", func(t *testing.T) {
- _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
- java_sdk_library_import {
- name: "libfoo",
- public: {
- jars: ["libbar.jar"],
- },
- shared_library: false,
- apex_available: ["com.android.art"],
- }
- `)
- })
-
- t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {
- _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `
- image_name: "art",
- contents: ["libfoo"],
- `)+`
- java_sdk_library_import {
- name: "libfoo",
- public: {
- jars: ["libbar.jar"],
- },
- shared_library: false,
- apex_available: ["com.android.art"],
- }
- `)
- })
-}
-
-func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
- preparers := android.GroupFixturePreparers(
- java.PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithApexBuildComponents,
- )
-
- errCtx := moduleErrorfTestCtx{}
-
- bpBase := `
- apex_set {
- name: "com.android.myapex",
- installable: true,
- exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
- set: "myapex.apks",
- }
-
- apex_set {
- name: "com.android.myapex_compressed",
- apex_name: "com.android.myapex",
- installable: true,
- exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
- set: "myapex_compressed.apks",
- }
-
- prebuilt_bootclasspath_fragment {
- name: "my-bootclasspath-fragment",
- apex_available: [
- "com.android.myapex",
- "com.android.myapex_compressed",
- ],
- hidden_api: {
- annotation_flags: "annotation-flags.csv",
- metadata: "metadata.csv",
- index: "index.csv",
- signature_patterns: "signature_patterns.csv",
- },
- %s
- }
- `
-
- t.Run("java_import", func(t *testing.T) {
- result := preparers.RunTestWithBp(t,
- fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- apex_available: [
- "com.android.myapex",
- "com.android.myapex_compressed",
- ],
- }
- `)
-
- module := result.Module("libfoo", "android_common_com.android.myapex")
- usesLibraryDep := module.(java.UsesLibraryDependency)
- android.AssertPathRelativeToTopEquals(t, "dex jar path",
- "out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
- usesLibraryDep.DexJarBuildPath(errCtx).Path())
- })
-
- t.Run("java_sdk_library_import", func(t *testing.T) {
- result := preparers.RunTestWithBp(t,
- fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
- java_sdk_library_import {
- name: "libfoo",
- public: {
- jars: ["libbar.jar"],
- },
- apex_available: [
- "com.android.myapex",
- "com.android.myapex_compressed",
- ],
- compile_dex: true,
- }
- `)
-
- module := result.Module("libfoo", "android_common_com.android.myapex")
- usesLibraryDep := module.(java.UsesLibraryDependency)
- android.AssertPathRelativeToTopEquals(t, "dex jar path",
- "out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
- usesLibraryDep.DexJarBuildPath(errCtx).Path())
- })
-
- t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {
- _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `
- image_name: "art",
- contents: ["libfoo"],
- `)+`
- java_sdk_library_import {
- name: "libfoo",
- public: {
- jars: ["libbar.jar"],
- },
- apex_available: [
- "com.android.myapex",
- "com.android.myapex_compressed",
- ],
- compile_dex: true,
- }
- `)
- })
-}
-
func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
apex {
@@ -8505,12 +8231,16 @@
},
}
- java_import {
- name: "libfoo",
+ java_sdk_library_import {
+ name: "libfoo",
+ prefer: true,
+ public: {
jars: ["libfoo.jar"],
- apex_available: ["myapex"],
- permitted_packages: ["libfoo"],
- }
+ },
+ apex_available: ["myapex"],
+ shared_library: false,
+ permitted_packages: ["libfoo"],
+ }
`, "", preparer, fragment)
})
}
@@ -8890,7 +8620,7 @@
}),
)
- m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("myapex", "android_common_myapex")
// Check extract_apks tool parameters.
extractedApex := m.Output("extracted/myapex.apks")
@@ -8931,7 +8661,7 @@
}),
)
- m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("myapex", "android_common_myapex")
// Check extract_apks tool parameters. No native bridge arch expected
extractedApex := m.Output("extracted/myapex.apks")
@@ -9618,42 +9348,6 @@
ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES := foo.myapex foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex\n")
}
-func TestAndroidMk_DexpreoptBuiltInstalledForApex_Prebuilt(t *testing.T) {
- ctx := testApex(t, `
- prebuilt_apex {
- name: "myapex",
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["foo"],
- }
-
- java_import {
- name: "foo",
- jars: ["foo.jar"],
- apex_available: ["myapex"],
- }
- `,
- dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
- )
-
- prebuilt := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
- entriesList := android.AndroidMkEntriesForTest(t, ctx, prebuilt)
- mainModuleEntries := entriesList[0]
- android.AssertArrayString(t,
- "LOCAL_REQUIRED_MODULES",
- mainModuleEntries.EntryMap["LOCAL_REQUIRED_MODULES"],
- []string{
- "foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex",
- "foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex",
- })
-}
-
func TestAndroidMk_RequiredModules(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -10522,14 +10216,15 @@
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 12 {
- t.Fatalf("Expected 12 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 14 {
+ t.Fatalf("Expected 14 commands, got %d in:\n%s", len(copyCmds), s)
}
ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info.*/image.apex/etc/flag.info")
inputs := []string{
"my_aconfig_declarations_foo/intermediate.pb",
@@ -10539,6 +10234,7 @@
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
+ VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
}
func TestAconfigFilesJavaAndCcDeps(t *testing.T) {
@@ -10657,14 +10353,15 @@
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 16 {
- t.Fatalf("Expected 16 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 18 {
+ t.Fatalf("Expected 18 commands, got %d in:\n%s", len(copyCmds), s)
}
ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info")
inputs := []string{
"my_aconfig_declarations_foo/intermediate.pb",
@@ -10675,6 +10372,7 @@
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
+ VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
}
func TestAconfigFilesRustDeps(t *testing.T) {
@@ -10825,14 +10523,15 @@
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 36 {
- t.Fatalf("Expected 36 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 38 {
+ t.Fatalf("Expected 38 commands, got %d in:\n%s", len(copyCmds), s)
}
ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info")
inputs := []string{
"my_aconfig_declarations_foo/intermediate.pb",
@@ -10844,6 +10543,7 @@
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
+ VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
}
func VerifyAconfigRule(t *testing.T, mod *android.TestingModule, desc string, inputs []string, output string, container string, file_type string) {
@@ -11172,12 +10872,12 @@
{
desc: "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.contributions",
- expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.deapexer/android_common/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
},
{
desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.v2.contributions",
- expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.v2.deapexer/android_common/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
},
}
@@ -11869,3 +11569,110 @@
)
})
}
+
+func TestSdkLibraryTransitiveClassLoaderContext(t *testing.T) {
+ // This test case tests that listing the impl lib instead of the top level java_sdk_library
+ // in libs of android_app and java_library does not lead to class loader context device/host
+ // path mismatch errors.
+ android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.PrepareForIntegrationTestWithAndroid,
+ PrepareForTestWithApexBuildComponents,
+ android.FixtureModifyEnv(func(env map[string]string) {
+ env["DISABLE_CONTAINER_CHECK"] = "true"
+ }),
+ withFiles(filesForSdkLibrary),
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.android.foo30-file_contexts": nil,
+ }),
+ ).RunTestWithBp(t, `
+ apex {
+ name: "com.android.foo30",
+ key: "myapex.key",
+ updatable: true,
+ bootclasspath_fragments: [
+ "foo-bootclasspath-fragment",
+ ],
+ java_libs: [
+ "bar",
+ ],
+ apps: [
+ "bar-app",
+ ],
+ min_sdk_version: "30",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ bootclasspath_fragment {
+ name: "foo-bootclasspath-fragment",
+ contents: [
+ "framework-foo",
+ ],
+ apex_available: [
+ "com.android.foo30",
+ ],
+ hidden_api: {
+ split_packages: ["*"]
+ },
+ }
+
+ java_sdk_library {
+ name: "framework-foo",
+ srcs: [
+ "A.java"
+ ],
+ unsafe_ignore_missing_latest_api: true,
+ apex_available: [
+ "com.android.foo30",
+ ],
+ compile_dex: true,
+ sdk_version: "core_current",
+ shared_library: false,
+ }
+
+ java_library {
+ name: "bar",
+ srcs: [
+ "A.java"
+ ],
+ libs: [
+ "framework-foo.impl",
+ ],
+ apex_available: [
+ "com.android.foo30",
+ ],
+ sdk_version: "core_current",
+ }
+
+ java_library {
+ name: "baz",
+ srcs: [
+ "A.java"
+ ],
+ libs: [
+ "bar",
+ ],
+ sdk_version: "core_current",
+ }
+
+ android_app {
+ name: "bar-app",
+ srcs: [
+ "A.java"
+ ],
+ libs: [
+ "baz",
+ "framework-foo.impl",
+ ],
+ apex_available: [
+ "com.android.foo30",
+ ],
+ sdk_version: "core_current",
+ min_sdk_version: "30",
+ manifest: "AndroidManifest.xml",
+ }
+ `)
+}
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index df7857f..e44d3f5 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -398,11 +398,20 @@
// Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
addPrebuilt(true, "foo", "bar"),
+ android.FixtureMergeMockFs(android.MockFS{
+ "apex_contributions/Android.bp": []byte(`
+ apex_contributions {
+ name: "prebuilt_art_contributions",
+ contents: ["prebuilt_com.android.art"],
+ api_domain: "com.android.art",
+ }
+ `)}),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"),
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
- ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common", []string{
+ ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_com.android.art", []string{
"etc/boot-image.prof",
"javalib/bar.jar",
"javalib/foo.jar",
@@ -495,6 +504,7 @@
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"),
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"),
)
bp := `
@@ -552,6 +562,12 @@
src: "com.mycompany.android.art.apex",
exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
+
+ apex_contributions {
+ name: "prebuilt_art_contributions",
+ contents: ["prebuilt_com.android.art"],
+ api_domain: "com.android.art",
+ }
`
t.Run("disabled alternative APEX", func(t *testing.T) {
@@ -561,27 +577,18 @@
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_art-bootclasspath-fragment`,
- `prebuilt_com.android.art.apex.selector`,
- `prebuilt_com.android.art.deapexer`,
})
java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_bar`,
- `prebuilt_com.android.art.deapexer`,
`prebuilt_foo`,
})
module := result.ModuleForTests("dex_bootjars", "android_common")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
-
- t.Run("enabled alternative APEX", func(t *testing.T) {
- preparers.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art")).
- RunTestWithBp(t, fmt.Sprintf(bp, ""))
- })
}
// checkCopiesToPredefinedLocationForArt checks that the supplied modules are copied to the
diff --git a/apex/builder.go b/apex/builder.go
index da9e47e..244119b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -96,6 +96,7 @@
{"package.map", "create_aconfig_package_map_file", "package_map"},
{"flag.map", "create_aconfig_flag_map_file", "flag_map"},
{"flag.val", "create_aconfig_flag_val_file", "flag_val"},
+ {"flag.info", "create_aconfig_flag_info_file", "flag_info"},
}
var (
diff --git a/apex/deapexer.go b/apex/deapexer.go
index a673108..3b8233d 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -15,37 +15,9 @@
package apex
import (
- "strings"
-
"android/soong/android"
)
-// Contains 'deapexer' a private module type used by 'prebuilt_apex' to make dex files contained
-// within a .apex file referenced by `prebuilt_apex` available for use by their associated
-// `java_import` modules.
-//
-// An 'apex' module references `java_library` modules from which .dex files are obtained that are
-// stored in the resulting `.apex` file. The resulting `.apex` file is then made available as a
-// prebuilt by referencing it from a `prebuilt_apex`. For each such `java_library` that is used by
-// modules outside the `.apex` file a `java_import` prebuilt is made available referencing a jar
-// that contains the Java classes.
-//
-// When building a Java module type, e.g. `java_module` or `android_app` against such prebuilts the
-// `java_import` provides the classes jar (jar containing `.class` files) against which the
-// module's `.java` files are compiled. That classes jar usually contains only stub classes. The
-// resulting classes jar is converted into a dex jar (jar containing `.dex` files). Then if
-// necessary the dex jar is further processed by `dexpreopt` to produce an optimized form of the
-// library specific to the current Android version. This process requires access to implementation
-// dex jars for each `java_import`. The `java_import` will obtain the implementation dex jar from
-// the `.apex` file in the associated `prebuilt_apex`.
-//
-// This is intentionally not registered by name as it is not intended to be used from within an
-// `Android.bp` file.
-
-// DeapexerProperties specifies the properties supported by the deapexer module.
-//
-// As these are never intended to be supplied in a .bp file they use a different naming convention
-// to make it clear that they are different.
type DeapexerProperties struct {
// List of common modules that may need access to files exported by this module.
//
@@ -72,46 +44,9 @@
Selected_apex *string `android:"path" blueprint:"mutated"`
}
-type Deapexer struct {
- android.ModuleBase
-
- properties DeapexerProperties
- selectedApexProperties SelectedApexProperties
-
- inputApex android.Path
-}
-
-// Returns the name of the deapexer module corresponding to an APEX module with the given name.
-func deapexerModuleName(apexModuleName string) string {
- return apexModuleName + ".deapexer"
-}
-
-// Returns the name of the APEX module corresponding to an deapexer module with
-// the given name. This reverses deapexerModuleName.
-func apexModuleName(deapexerModuleName string) string {
- return strings.TrimSuffix(deapexerModuleName, ".deapexer")
-}
-
-func privateDeapexerFactory() android.Module {
- module := &Deapexer{}
- module.AddProperties(&module.properties, &module.selectedApexProperties)
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- return module
-}
-
-func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
- // Add dependencies from the java modules to which this exports files from the `.apex` file onto
- // this module so that they can access the `DeapexerInfo` object that this provides.
- // TODO: b/308174306 - Once all the mainline modules have been flagged, drop this dependency edge
- for _, lib := range p.properties.CommonModules {
- dep := prebuiltApexExportedModuleName(ctx, lib)
- ctx.AddReverseDependency(ctx.Module(), android.DeapexerTag, dep)
- }
-}
-
-func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.inputApex = android.OptionalPathForModuleSrc(ctx, p.selectedApexProperties.Selected_apex).Path()
-
+// deapex creates the build rules to deapex a prebuilt .apex file
+// it returns a pointer to a DeapexerInfo object
+func deapex(ctx android.ModuleContext, apexFile android.Path, deapexerProps DeapexerProperties) *android.DeapexerInfo {
// Create and remember the directory into which the .apex file's contents will be unpacked.
deapexerOutput := android.PathForModuleOut(ctx, "deapexer")
@@ -119,7 +54,7 @@
// Create mappings from apex relative path to the extracted file's path.
exportedPaths := make(android.Paths, 0, len(exports))
- for _, path := range p.properties.ExportedFiles {
+ for _, path := range deapexerProps.ExportedFiles {
// Populate the exports that this makes available.
extractedPath := deapexerOutput.Join(ctx, path)
exports[path] = extractedPath
@@ -131,9 +66,8 @@
// apex relative path to extracted file path available for other modules.
if len(exports) > 0 {
// Make the information available for other modules.
- di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports, p.properties.CommonModules)
- di.AddDexpreoptProfileGuidedExportedModuleNames(p.properties.DexpreoptProfileGuidedModules...)
- android.SetProvider(ctx, android.DeapexerProvider, di)
+ di := android.NewDeapexerInfo(ctx.ModuleName(), exports, deapexerProps.CommonModules)
+ di.AddDexpreoptProfileGuidedExportedModuleNames(deapexerProps.DexpreoptProfileGuidedModules...)
// Create a sorted list of the files that this exports.
exportedPaths = android.SortedUniquePaths(exportedPaths)
@@ -147,11 +81,13 @@
BuiltTool("deapexer").
BuiltTool("debugfs").
BuiltTool("fsck.erofs").
- Input(p.inputApex).
+ Input(apexFile).
Text(deapexerOutput.String())
for _, p := range exportedPaths {
command.Output(p.(android.WritablePath))
}
- builder.Build("deapexer", "deapex "+apexModuleName(ctx.ModuleName()))
+ builder.Build("deapexer", "deapex "+ctx.ModuleName())
+ return &di
}
+ return nil
}
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index d8ee4ba..4feade8 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -127,16 +127,29 @@
src: "com.android.art-arm.apex",
exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
+
+ apex_contributions {
+ name: "prebuilt_art_contributions",
+ contents: ["prebuilt_com.android.art"],
+ api_domain: "com.android.art",
+ }
`
- result := android.GroupFixturePreparers(
+ fixture := android.GroupFixturePreparers(
java.PrepareForTestWithDexpreopt,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo"),
java.FixtureConfigureBootJars("com.android.art:core-oj", "platform:foo", "system_ext:bar", "platform:baz"),
PrepareForTestWithApexBuildComponents,
prepareForTestWithArtApex,
- ).RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt))
+ )
+ if preferPrebuilt {
+ fixture = android.GroupFixturePreparers(
+ fixture,
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"),
+ )
+ }
+ result := fixture.RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt))
dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
rule := dexBootJars.Output(ruleFile)
@@ -200,7 +213,7 @@
"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
- "out/soong/.intermediates/prebuilt_com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
+ "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
"out/soong/dexpreopt/uffd_gc_flag.txt",
}
@@ -384,12 +397,12 @@
{
desc: "Prebuilt apex prebuilt_com.android.art is selected, profile should come from .prof deapexed from the prebuilt",
selectedArtApexContributions: "art.prebuilt.contributions",
- expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof",
},
{
desc: "Prebuilt apex prebuilt_com.android.art.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedArtApexContributions: "art.prebuilt.v2.contributions",
- expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art.v2.deapexer/android_common/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_com.android.art/deapexer/etc/boot-image.prof",
},
}
for _, tc := range testCases {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 792b571..9cd5688 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -107,11 +107,6 @@
// from PRODUCT_PACKAGES.
Overrides []string
- // List of java libraries that are embedded inside this prebuilt APEX bundle and for which this
- // APEX bundle will create an APEX variant and provide dex implementation jars for use by
- // dexpreopt and boot jars package check.
- Exported_java_libs []string
-
// List of bootclasspath fragments inside this prebuilt APEX bundle and for which this APEX
// bundle will create an APEX variant.
Exported_bootclasspath_fragments []string
@@ -199,9 +194,8 @@
}
// If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex
-func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) {
- // If this apex does not export anything, return
- if !p.hasExportedDeps() {
+func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext, di *android.DeapexerInfo) {
+ if di == nil {
return
}
// If this prebuilt apex has not been selected, return
@@ -210,10 +204,7 @@
}
// Use apex_name to determine the api domain of this prebuilt apex
apexName := p.ApexVariationName()
- di, err := android.FindDeapexerProviderForModule(ctx)
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- }
+ // TODO: do not compute twice
dc := dexpreopt.GetGlobalConfig(ctx)
systemServerJarList := dc.AllApexSystemServerJars(ctx)
@@ -262,29 +253,8 @@
return entriesList
}
-// prebuiltApexModuleCreator defines the methods that need to be implemented by prebuilt_apex and
-// apex_set in order to create the modules needed to provide access to the prebuilt .apex file.
-type prebuiltApexModuleCreator interface {
- createPrebuiltApexModules(ctx android.BottomUpMutatorContext)
-}
-
-// prebuiltApexModuleCreatorMutator is the mutator responsible for invoking the
-// prebuiltApexModuleCreator's createPrebuiltApexModules method.
-//
-// It is registered as a pre-arch mutator as it must run after the ComponentDepsMutator because it
-// will need to access dependencies added by that (exported modules) but must run before the
-// DepsMutator so that the deapexer module it creates can add dependencies onto itself from the
-// exported modules.
-func prebuiltApexModuleCreatorMutator(ctx android.BottomUpMutatorContext) {
- module := ctx.Module()
- if creator, ok := module.(prebuiltApexModuleCreator); ok {
- creator.createPrebuiltApexModules(ctx)
- }
-}
-
func (p *prebuiltCommon) hasExportedDeps() bool {
- return len(p.prebuiltCommonProperties.Exported_java_libs) > 0 ||
- len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 ||
+ return len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 ||
len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0
}
@@ -292,11 +262,6 @@
func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) {
module := ctx.Module()
- for _, dep := range p.prebuiltCommonProperties.Exported_java_libs {
- prebuiltDep := android.PrebuiltNameFromSource(dep)
- ctx.AddDependency(module, exportedJavaLibTag, prebuiltDep)
- }
-
for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments {
prebuiltDep := android.PrebuiltNameFromSource(dep)
ctx.AddDependency(module, exportedBootclasspathFragmentTag, prebuiltDep)
@@ -414,34 +379,6 @@
}
}
-// prebuiltApexSelectorModule is a private module type that is only created by the prebuilt_apex
-// module. It selects the apex to use and makes it available for use by prebuilt_apex and the
-// deapexer.
-type prebuiltApexSelectorModule struct {
- android.ModuleBase
-
- apexFileProperties ApexFileProperties
-
- inputApex android.Path
-}
-
-func privateApexSelectorModuleFactory() android.Module {
- module := &prebuiltApexSelectorModule{}
- module.AddProperties(
- &module.apexFileProperties,
- )
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- return module
-}
-
-func (p *prebuiltApexSelectorModule) Srcs() android.Paths {
- return android.Paths{p.inputApex}
-}
-
-func (p *prebuiltApexSelectorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.inputApex = android.SingleSourcePathFromSupplier(ctx, p.apexFileProperties.prebuiltApexSelector, "src")
-}
-
type Prebuilt struct {
prebuiltCommon
@@ -484,11 +421,11 @@
// to use methods on it that are specific to the current module.
//
// See the ApexFileProperties.Src property.
-func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) []string {
+func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) string {
multiTargets := prebuilt.MultiTargets()
if len(multiTargets) != 1 {
ctx.OtherModuleErrorf(prebuilt, "compile_multilib shouldn't be \"both\" for prebuilt_apex")
- return nil
+ return ""
}
var src string
switch multiTargets[0].Arch.ArchType {
@@ -521,7 +458,7 @@
// logic from reporting a more general, less useful message.
}
- return []string{src}
+ return src
}
type PrebuiltProperties struct {
@@ -538,35 +475,19 @@
func PrebuiltFactory() android.Module {
module := &Prebuilt{}
module.AddProperties(&module.properties)
- module.initPrebuiltCommon(module, &module.properties.PrebuiltCommonProperties)
+ module.prebuiltCommon.prebuiltCommonProperties = &module.properties.PrebuiltCommonProperties
+
+ // init the module as a prebuilt
+ // even though this module type has srcs, use `InitPrebuiltModuleWithoutSrcs`, since the existing
+ // InitPrebuiltModule* are not friendly with Sources of Configurable type.
+ // The actual src will be evaluated in GenerateAndroidBuildActions.
+ android.InitPrebuiltModuleWithoutSrcs(module)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
-func createApexSelectorModule(ctx android.BottomUpMutatorContext, name string, apexFileProperties *ApexFileProperties) {
- props := struct {
- Name *string
- }{
- Name: proptools.StringPtr(name),
- }
-
- ctx.CreateModule(privateApexSelectorModuleFactory,
- &props,
- apexFileProperties,
- )
-}
-
-// createDeapexerModuleIfNeeded will create a deapexer module if it is needed.
-//
-// A deapexer module is only needed when the prebuilt apex specifies one or more modules in either
-// the `exported_java_libs` or `exported_bootclasspath_fragments` properties as that indicates that
-// the listed modules need access to files from within the prebuilt .apex file.
-func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.BottomUpMutatorContext, deapexerName string, apexFileSource string) {
- // Only create the deapexer module if it is needed.
- if !p.hasExportedDeps() {
- return
- }
-
+func (p *prebuiltCommon) getDeapexerPropertiesIfNeeded(ctx android.ModuleContext) DeapexerProperties {
// Compute the deapexer properties from the transitive dependencies of this module.
commonModules := []string{}
dexpreoptProfileGuidedModules := []string{}
@@ -600,7 +521,7 @@
})
// Create properties for deapexer module.
- deapexerProperties := &DeapexerProperties{
+ deapexerProperties := DeapexerProperties{
// Remove any duplicates from the common modules lists as a module may be included via a direct
// dependency as well as transitive ones.
CommonModules: android.SortedUniqueStrings(commonModules),
@@ -609,22 +530,7 @@
// Populate the exported files property in a fixed order.
deapexerProperties.ExportedFiles = android.SortedUniqueStrings(exportedFiles)
-
- props := struct {
- Name *string
- Selected_apex *string
- }{
- Name: proptools.StringPtr(deapexerName),
- Selected_apex: proptools.StringPtr(apexFileSource),
- }
- ctx.CreateModule(privateDeapexerFactory,
- &props,
- deapexerProperties,
- )
-}
-
-func apexSelectorModuleName(baseModuleName string) string {
- return baseModuleName + ".apex.selector"
+ return deapexerProperties
}
func prebuiltApexExportedModuleName(ctx android.BottomUpMutatorContext, name string) string {
@@ -666,97 +572,50 @@
var _ android.RequiresFilesFromPrebuiltApexTag = exportedDependencyTag{}
var (
- exportedJavaLibTag = exportedDependencyTag{name: "exported_java_libs"}
exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"}
exportedSystemserverclasspathFragmentTag = exportedDependencyTag{name: "exported_systemserverclasspath_fragments"}
)
-var _ prebuiltApexModuleCreator = (*Prebuilt)(nil)
-
-// createPrebuiltApexModules creates modules necessary to export files from the prebuilt apex to the
-// build.
-//
-// If this needs to make files from within a `.apex` file available for use by other Soong modules,
-// e.g. make dex implementation jars available for java_import modules listed in exported_java_libs,
-// it does so as follows:
-//
-// 1. It creates a `deapexer` module that actually extracts the files from the `.apex` file and
-// makes them available for use by other modules, at both Soong and ninja levels.
-//
-// 2. It adds a dependency onto those modules and creates an apex specific variant similar to what
-// an `apex` module does. That ensures that code which looks for specific apex variant, e.g.
-// dexpreopt, will work the same way from source and prebuilt.
-//
-// 3. The `deapexer` module adds a dependency from the modules that require the exported files onto
-// itself so that they can retrieve the file paths to those files.
-//
-// It also creates a child module `selector` that is responsible for selecting the appropriate
-// input apex for both the prebuilt_apex and the deapexer. That is needed for a couple of reasons:
-//
-// 1. To dedup the selection logic so it only runs in one module.
-//
-// 2. To allow the deapexer to be wired up to a different source for the input apex, e.g. an
-// `apex_set`.
-//
-// prebuilt_apex
-// / | \
-// / | \
-// V V V
-// selector <--- deapexer <--- exported java lib
-func (p *Prebuilt) createPrebuiltApexModules(ctx android.BottomUpMutatorContext) {
- apexSelectorModuleName := apexSelectorModuleName(p.Name())
- createApexSelectorModule(ctx, apexSelectorModuleName, &p.properties.ApexFileProperties)
-
- apexFileSource := ":" + apexSelectorModuleName
- p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(p.Name()), apexFileSource)
-
- // Add a source reference to retrieve the selected apex from the selector module.
- p.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
-}
-
func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
p.prebuiltApexContentsDeps(ctx)
}
-func (p *prebuiltCommon) DepsMutator(ctx android.BottomUpMutatorContext) {
- if p.hasExportedDeps() {
- // Create a dependency from the prebuilt apex (prebuilt_apex/apex_set) to the internal deapexer module
- // The deapexer will return a provider which will be used to determine the exported artfifacts from this prebuilt.
- ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.Name()))
- }
-}
-
var _ ApexInfoMutator = (*Prebuilt)(nil)
func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
p.apexInfoMutator(mctx)
}
+// creates the build rules to deapex the prebuilt, and returns a deapexerInfo
+func (p *prebuiltCommon) getDeapexerInfo(ctx android.ModuleContext, apexFile android.Path) *android.DeapexerInfo {
+ if !p.hasExportedDeps() {
+ // nothing to do
+ return nil
+ }
+ deapexerProps := p.getDeapexerPropertiesIfNeeded(ctx)
+ return deapex(ctx, apexFile, deapexerProps)
+}
+
// Set a provider containing information about the jars and .prof provided by the apex
// Apexes built from prebuilts retrieve this information by visiting its internal deapexer module
// Used by dex_bootjars to generate the boot image
-func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext) {
- if !p.hasExportedDeps() {
- // nothing to do
+func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext, di *android.DeapexerInfo) {
+ if di == nil {
return
}
- if di, err := android.FindDeapexerProviderForModule(ctx); err == nil {
- javaModuleToDexPath := map[string]android.Path{}
- for _, commonModule := range di.GetExportedModuleNames() {
- if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil {
- javaModuleToDexPath[commonModule] = dex
- }
+ javaModuleToDexPath := map[string]android.Path{}
+ for _, commonModule := range di.GetExportedModuleNames() {
+ if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil {
+ javaModuleToDexPath[commonModule] = dex
}
-
- exports := android.ApexExportsInfo{
- ApexName: p.ApexVariationName(),
- ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex),
- LibraryNameToDexJarPathOnHost: javaModuleToDexPath,
- }
- android.SetProvider(ctx, android.ApexExportsInfoProvider, exports)
- } else {
- ctx.ModuleErrorf(err.Error())
}
+
+ exports := android.ApexExportsInfo{
+ ApexName: p.ApexVariationName(),
+ ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex),
+ LibraryNameToDexJarPathOnHost: javaModuleToDexPath,
+ }
+ android.SetProvider(ctx, android.ApexExportsInfoProvider, exports)
}
// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
@@ -792,7 +651,7 @@
p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
- p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
+ p.inputApex = android.PathForModuleSrc(ctx, p.properties.prebuiltApexSelector(ctx, ctx.Module()))
p.installDir = android.PathForModuleInstall(ctx, "apex")
p.installFilename = p.InstallFilename()
if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
@@ -810,11 +669,13 @@
return
}
+ deapexerInfo := p.getDeapexerInfo(ctx, p.inputApex)
+
// dexpreopt any system server jars if present
- p.dexpreoptSystemServerJars(ctx)
+ p.dexpreoptSystemServerJars(ctx, deapexerInfo)
// provide info used for generating the boot image
- p.provideApexExportsInfo(ctx)
+ p.provideApexExportsInfo(ctx, deapexerInfo)
p.providePrebuiltInfo(ctx)
@@ -850,26 +711,11 @@
extractedApex android.WritablePath
}
-func privateApexExtractorModuleFactory() android.Module {
- module := &prebuiltApexExtractorModule{}
- module.AddProperties(
- &module.properties,
- )
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- return module
-}
-
-func (p *prebuiltApexExtractorModule) Srcs() android.Paths {
- return android.Paths{p.extractedApex}
-}
-
-func (p *prebuiltApexExtractorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- srcsSupplier := func(ctx android.BaseModuleContext, prebuilt android.Module) []string {
- return p.properties.prebuiltSrcs(ctx)
- }
+// extract registers the build actions to extract an apex from .apks file
+// returns the path of the extracted apex
+func extract(ctx android.ModuleContext, apexSet android.Path, prerelease *bool) android.Path {
defaultAllowPrerelease := ctx.Config().IsEnvTrue("SOONG_ALLOW_PRERELEASE_APEXES")
- apexSet := android.SingleSourcePathFromSupplier(ctx, srcsSupplier, "set")
- p.extractedApex = android.PathForModuleOut(ctx, "extracted", apexSet.Base())
+ extractedApex := android.PathForModuleOut(ctx, "extracted", apexSet.Base())
// Filter out NativeBridge archs (b/260115309)
abis := java.SupportedAbis(ctx, true)
ctx.Build(pctx,
@@ -877,14 +723,16 @@
Rule: extractMatchingApex,
Description: "Extract an apex from an apex set",
Inputs: android.Paths{apexSet},
- Output: p.extractedApex,
+ Output: extractedApex,
Args: map[string]string{
"abis": strings.Join(abis, ","),
- "allow-prereleased": strconv.FormatBool(proptools.BoolDefault(p.properties.Prerelease, defaultAllowPrerelease)),
+ "allow-prereleased": strconv.FormatBool(proptools.BoolDefault(prerelease, defaultAllowPrerelease)),
"sdk-version": ctx.Config().PlatformSdkVersion().String(),
"skip-sdk-check": strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")),
},
- })
+ },
+ )
+ return extractedApex
}
type ApexSet struct {
@@ -953,48 +801,18 @@
func apexSetFactory() android.Module {
module := &ApexSet{}
module.AddProperties(&module.properties)
- module.initPrebuiltCommon(module, &module.properties.PrebuiltCommonProperties)
+ module.prebuiltCommon.prebuiltCommonProperties = &module.properties.PrebuiltCommonProperties
+
+ // init the module as a prebuilt
+ // even though this module type has srcs, use `InitPrebuiltModuleWithoutSrcs`, since the existing
+ // InitPrebuiltModule* are not friendly with Sources of Configurable type.
+ // The actual src will be evaluated in GenerateAndroidBuildActions.
+ android.InitPrebuiltModuleWithoutSrcs(module)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
-func createApexExtractorModule(ctx android.BottomUpMutatorContext, name string, apexExtractorProperties *ApexExtractorProperties) {
- props := struct {
- Name *string
- }{
- Name: proptools.StringPtr(name),
- }
-
- ctx.CreateModule(privateApexExtractorModuleFactory,
- &props,
- apexExtractorProperties,
- )
-}
-
-func apexExtractorModuleName(baseModuleName string) string {
- return baseModuleName + ".apex.extractor"
-}
-
-var _ prebuiltApexModuleCreator = (*ApexSet)(nil)
-
-// createPrebuiltApexModules creates modules necessary to export files from the apex set to other
-// modules.
-//
-// This effectively does for apex_set what Prebuilt.createPrebuiltApexModules does for a
-// prebuilt_apex except that instead of creating a selector module which selects one .apex file
-// from those provided this creates an extractor module which extracts the appropriate .apex file
-// from the zip file containing them.
-func (a *ApexSet) createPrebuiltApexModules(ctx android.BottomUpMutatorContext) {
- apexExtractorModuleName := apexExtractorModuleName(a.Name())
- createApexExtractorModule(ctx, apexExtractorModuleName, &a.properties.ApexExtractorProperties)
-
- apexFileSource := ":" + apexExtractorModuleName
- a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(a.Name()), apexFileSource)
-
- // After passing the arch specific src properties to the creating the apex selector module
- a.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
-}
-
func (a *ApexSet) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
a.prebuiltApexContentsDeps(ctx)
}
@@ -1017,7 +835,15 @@
ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix)
}
- inputApex := android.OptionalPathForModuleSrc(ctx, a.prebuiltCommonProperties.Selected_apex).Path()
+ var apexSet android.Path
+ if srcs := a.properties.prebuiltSrcs(ctx); len(srcs) == 1 {
+ apexSet = android.PathForModuleSrc(ctx, srcs[0])
+ } else {
+ ctx.ModuleErrorf("Expected exactly one source apex_set file, found %v\n", srcs)
+ }
+
+ extractedApex := extract(ctx, apexSet, a.properties.Prerelease)
+
a.outputApex = android.PathForModuleOut(ctx, a.installFilename)
// Build the output APEX. If compression is not enabled, make sure the output is not compressed even if the input is compressed
@@ -1027,7 +853,7 @@
}
ctx.Build(pctx, android.BuildParams{
Rule: buildRule,
- Input: inputApex,
+ Input: extractedApex,
Output: a.outputApex,
})
@@ -1036,11 +862,13 @@
return
}
+ deapexerInfo := a.getDeapexerInfo(ctx, extractedApex)
+
// dexpreopt any system server jars if present
- a.dexpreoptSystemServerJars(ctx)
+ a.dexpreoptSystemServerJars(ctx, deapexerInfo)
// provide info used for generating the boot image
- a.provideApexExportsInfo(ctx)
+ a.provideApexExportsInfo(ctx, deapexerInfo)
a.providePrebuiltInfo(ctx)
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index fd9020b..acb3649 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -277,8 +277,6 @@
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
`all_apex_contributions`,
`dex2oatd`,
- `prebuilt_myapex.apex.selector`,
- `prebuilt_myapex.deapexer`,
`prebuilt_mysystemserverclasspathfragment`,
})
@@ -286,10 +284,9 @@
`all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
- `prebuilt_myapex.deapexer`,
})
- ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -439,10 +436,9 @@
`all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
- `prebuilt_myapex.deapexer`,
})
- ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 73c8800..8679821 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -56,6 +56,7 @@
)
func registerBpfBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("bpf_defaults", defaultsFactory)
ctx.RegisterModuleType("bpf", BpfFactory)
}
@@ -77,10 +78,16 @@
// the C/C++ module.
Cflags []string
- // directories (relative to the root of the source tree) that will
- // be added to the include paths using -I.
+ // list of directories relative to the root of the source tree that
+ // will be added to the include paths using -I.
+ // If possible, don't use this. If adding paths from the current
+ // directory, use local_include_dirs. If adding paths from other
+ // modules, use export_include_dirs in that module.
Include_dirs []string
+ // list of directories relative to the Blueprint file that will be
+ // added to the include path using -I.
+ Local_include_dirs []string
// optional subdirectory under which this module is installed into.
Sub_dir string
@@ -94,7 +101,7 @@
type bpf struct {
android.ModuleBase
-
+ android.DefaultableModuleBase
properties BpfProperties
objs android.Paths
@@ -163,6 +170,10 @@
"-I " + ctx.ModuleDir(),
}
+ for _, dir := range android.PathsForModuleSrc(ctx, bpf.properties.Local_include_dirs) {
+ cflags = append(cflags, "-I "+dir.String())
+ }
+
for _, dir := range android.PathsForSource(ctx, bpf.properties.Include_dirs) {
cflags = append(cflags, "-I "+dir.String())
}
@@ -264,6 +275,26 @@
}
}
+type Defaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+func defaultsFactory() android.Module {
+ return DefaultsFactory()
+}
+
+func DefaultsFactory(props ...interface{}) android.Module {
+ module := &Defaults{}
+
+ module.AddProperties(props...)
+ module.AddProperties(&BpfProperties{})
+
+ android.InitDefaultsModule(module)
+
+ return module
+}
+
func (bpf *bpf) SubDir() string {
return bpf.properties.Sub_dir
}
@@ -274,5 +305,7 @@
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+
return module
}
diff --git a/bpf/libbpf/libbpf_prog.go b/bpf/libbpf/libbpf_prog.go
index 1fdb3d6..ac61510 100644
--- a/bpf/libbpf/libbpf_prog.go
+++ b/bpf/libbpf/libbpf_prog.go
@@ -61,6 +61,7 @@
)
func registerLibbpfProgBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("libbpf_defaults", defaultsFactory)
ctx.RegisterModuleType("libbpf_prog", LibbpfProgFactory)
}
@@ -88,14 +89,17 @@
// be added to the include path using -I
Local_include_dirs []string `android:"arch_variant"`
+ Header_libs []string `android:"arch_variant"`
+
// optional subdirectory under which this module is installed into.
Relative_install_path string
}
type libbpfProg struct {
android.ModuleBase
+ android.DefaultableModuleBase
properties LibbpfProgProperties
- objs android.Paths
+ objs android.Paths
}
var _ android.ImageInterface = (*libbpfProg)(nil)
@@ -139,6 +143,7 @@
func (libbpf *libbpfProg) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddDependency(ctx.Module(), libbpfProgDepTag, "libbpf_headers")
+ ctx.AddVariationDependencies(nil, cc.HeaderDepTag(), libbpf.properties.Header_libs...)
}
func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -180,6 +185,11 @@
depName := ctx.OtherModuleName(dep)
ctx.ModuleErrorf("module %q is not a genrule", depName)
}
+ } else if depTag == cc.HeaderDepTag() {
+ depExporterInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
+ for _, dir := range depExporterInfo.IncludeDirs {
+ cflags = append(cflags, "-I "+dir.String())
+ }
}
})
@@ -269,10 +279,32 @@
}
}
+type Defaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+func defaultsFactory() android.Module {
+ return DefaultsFactory()
+}
+
+func DefaultsFactory(props ...interface{}) android.Module {
+ module := &Defaults{}
+
+ module.AddProperties(props...)
+ module.AddProperties(&LibbpfProgProperties{})
+
+ android.InitDefaultsModule(module)
+
+ return module
+}
+
func LibbpfProgFactory() android.Module {
module := &libbpfProg{}
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
+
return module
}
diff --git a/build_kzip.bash b/build_kzip.bash
index 4c42048..850aeda 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -40,6 +40,7 @@
merge_zips
xref_cxx
xref_java
+ xref_kotlin
# TODO: b/286390153 - reenable rust
# xref_rust
)
diff --git a/cc/Android.bp b/cc/Android.bp
index 2952614..3688c8a 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -116,4 +116,6 @@
"cmake_module_cc.txt",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/cc/TEST_MAPPING b/cc/TEST_MAPPING
new file mode 100644
index 0000000..be2809d
--- /dev/null
+++ b/cc/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "bionic"
+ }
+ ]
+}
diff --git a/cc/cc.go b/cc/cc.go
index 96795d3..a8ff474 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -137,7 +137,7 @@
// LLNDK headers for the ABI checker to check LLNDK implementation library.
// An LLNDK implementation is the core variant. LLNDK header libs are reexported by the vendor variant.
- // The core variant cannot depend on the vendor variant because of the order of CreateVariations.
+ // The core variant cannot depend on the vendor variant because of the order of imageTransitionMutator.Split().
// Instead, the LLNDK implementation depends on the LLNDK header libs.
LlndkHeaderLibs []string
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 93630db..3f3347b 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -49,17 +49,30 @@
func registerTestMutators(ctx android.RegistrationContext) {
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("apex", testApexMutator).Parallel()
+ ctx.Transition("apex", &testApexTransitionMutator{})
})
}
-func testApexMutator(mctx android.BottomUpMutatorContext) {
- modules := mctx.CreateVariations(apexVariationName)
+type testApexTransitionMutator struct{}
+
+func (t *testApexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ return []string{apexVariationName}
+}
+
+func (t *testApexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (t *testApexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ return incomingVariation
+}
+
+func (t *testApexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
MinSdkVersion: android.ApiLevelForTest(apexVersion),
}
- mctx.SetVariationProvider(modules[0], android.ApexInfoProvider, apexInfo)
+ android.SetProvider(ctx, android.ApexInfoProvider, apexInfo)
}
// testCcWithConfig runs tests using the prepareForCcTest
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index 289409f..f514db6 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -35,4 +35,8 @@
testSrcs: [
"tidy_test.go",
],
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//prebuilts/clang/host/linux-x86/soong",
+ ],
}
diff --git a/cc/config/global.go b/cc/config/global.go
index c838357..9d3de6d 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -286,6 +286,8 @@
// New warnings to be fixed after clang-r468909
"-Wno-error=deprecated-builtins", // http://b/241601211
"-Wno-error=deprecated", // in external/googletest/googletest
+ // Disabling until the warning is fixed in libc++abi header files b/366180429
+ "-Wno-deprecated-dynamic-exception-spec",
// New warnings to be fixed after clang-r475365
"-Wno-error=enum-constexpr-conversion", // http://b/243964282
// New warnings to be fixed after clang-r522817
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 5aa2a7e..e7ac038 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -40,6 +40,9 @@
"-march=x86-64",
},
+ "alderlake": []string{
+ "-march=alderlake",
+ },
"broadwell": []string{
"-march=broadwell",
},
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 4b0041c..a92881d 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -42,6 +42,9 @@
"x86_64": []string{
"-march=prescott",
},
+ "alderlake": []string{
+ "-march=alderlake",
+ },
"atom": []string{
"-march=atom",
},
diff --git a/cc/generated_cc_library.go b/cc/generated_cc_library.go
index b1084e4..709586b 100644
--- a/cc/generated_cc_library.go
+++ b/cc/generated_cc_library.go
@@ -18,7 +18,7 @@
"android/soong/android"
)
-func GeneratedCcLibraryModuleFactory(moduleName string, callbacks Generator) android.Module {
+func GeneratedCcLibraryModuleFactory(callbacks Generator) android.Module {
module, _ := NewLibrary(android.HostAndDeviceSupported)
// Can be used as both a static and a shared library.
diff --git a/cc/libbuildversion/Android.bp b/cc/libbuildversion/Android.bp
index b105a30..c1f2c10 100644
--- a/cc/libbuildversion/Android.bp
+++ b/cc/libbuildversion/Android.bp
@@ -20,4 +20,5 @@
"//apex_available:anyapex",
],
vendor_available: true,
+ visibility: ["//visibility:public"],
}
diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go
index 8202cc0..2706261 100644
--- a/cc/ndk_abi.go
+++ b/cc/ndk_abi.go
@@ -46,7 +46,7 @@
if m, ok := module.(*Module); ok {
if installer, ok := m.installer.(*stubDecorator); ok {
- if canDumpAbi(ctx.Config(), ctx.ModuleDir(module)) {
+ if installer.hasAbiDump {
depPaths = append(depPaths, installer.abiDumpPath)
}
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index bd6dfa3..01551ab 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -125,6 +125,7 @@
parsedCoverageXmlPath android.ModuleOutPath
installPath android.Path
abiDumpPath android.OutputPath
+ hasAbiDump bool
abiDiffPaths android.Paths
apiLevel android.ApiLevel
@@ -330,11 +331,11 @@
}
// Feature flag.
-func canDumpAbi(config android.Config, moduleDir string) bool {
+func (this *stubDecorator) canDumpAbi(ctx ModuleContext) bool {
if runtime.GOOS == "darwin" {
return false
}
- if strings.HasPrefix(moduleDir, "bionic/") {
+ if strings.HasPrefix(ctx.ModuleDir(), "bionic/") {
// Bionic has enough uncommon implementation details like ifuncs and asm
// code that the ABI tracking here has a ton of false positives. That's
// causing pretty extreme friction for development there, so disabling
@@ -343,8 +344,14 @@
// http://b/358653811
return false
}
+
+ if this.apiLevel.IsCurrent() {
+ // "current" (AKA 10000) is not tracked.
+ return false
+ }
+
// http://b/156513478
- return config.ReleaseNdkAbiMonitored()
+ return ctx.Config().ReleaseNdkAbiMonitored()
}
// Feature flag to disable diffing against prebuilts.
@@ -357,6 +364,7 @@
this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
this.apiLevel.String(), ctx.Arch().ArchType.String(),
this.libraryName(ctx), "abi.stg")
+ this.hasAbiDump = true
headersList := getNdkABIHeadersFile(ctx)
ctx.Build(pctx, android.BuildParams{
Rule: stg,
@@ -421,41 +429,45 @@
// Also ensure that the ABI of the next API level (if there is one) matches
// this API level. *New* ABI is allowed, but any changes to APIs that exist
// in this API level are disallowed.
- if !this.apiLevel.IsCurrent() && prebuiltAbiDump.Valid() {
+ if prebuiltAbiDump.Valid() {
nextApiLevel := findNextApiLevel(ctx, this.apiLevel)
if nextApiLevel == nil {
panic(fmt.Errorf("could not determine which API level follows "+
"non-current API level %s", this.apiLevel))
}
- nextAbiDiffPath := android.PathForModuleOut(ctx,
- "abidiff_next.timestamp")
- nextAbiDump := this.findPrebuiltAbiDump(ctx, *nextApiLevel)
- missingNextPrebuiltError := fmt.Sprintf(
- missingPrebuiltErrorTemplate, this.libraryName(ctx),
- nextAbiDump.InvalidReason())
- if !nextAbiDump.Valid() {
- ctx.Build(pctx, android.BuildParams{
- Rule: android.ErrorRule,
- Output: nextAbiDiffPath,
- Args: map[string]string{
- "error": missingNextPrebuiltError,
- },
- })
- } else {
- ctx.Build(pctx, android.BuildParams{
- Rule: stgdiff,
- Description: fmt.Sprintf(
- "Comparing ABI to the next API level %s %s",
- prebuiltAbiDump, nextAbiDump),
- Output: nextAbiDiffPath,
- Inputs: android.Paths{
- prebuiltAbiDump.Path(), nextAbiDump.Path()},
- Args: map[string]string{
- "args": "--format=small --ignore=interface_addition",
- },
- })
+
+ // "current" ABI is not tracked.
+ if !nextApiLevel.IsCurrent() {
+ nextAbiDiffPath := android.PathForModuleOut(ctx,
+ "abidiff_next.timestamp")
+ nextAbiDump := this.findPrebuiltAbiDump(ctx, *nextApiLevel)
+ missingNextPrebuiltError := fmt.Sprintf(
+ missingPrebuiltErrorTemplate, this.libraryName(ctx),
+ nextAbiDump.InvalidReason())
+ if !nextAbiDump.Valid() {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: nextAbiDiffPath,
+ Args: map[string]string{
+ "error": missingNextPrebuiltError,
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: stgdiff,
+ Description: fmt.Sprintf(
+ "Comparing ABI to the next API level %s %s",
+ prebuiltAbiDump, nextAbiDump),
+ Output: nextAbiDiffPath,
+ Inputs: android.Paths{
+ prebuiltAbiDump.Path(), nextAbiDump.Path()},
+ Args: map[string]string{
+ "args": "--format=small --ignore=interface_addition",
+ },
+ })
+ }
+ this.abiDiffPaths = append(this.abiDiffPaths, nextAbiDiffPath)
}
- this.abiDiffPaths = append(this.abiDiffPaths, nextAbiDiffPath)
}
}
@@ -478,7 +490,7 @@
nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile, c.apiLevel, "")
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
c.versionScriptPath = nativeAbiResult.versionScript
- if canDumpAbi(ctx.Config(), ctx.ModuleDir()) {
+ if c.canDumpAbi(ctx) {
c.dumpAbi(ctx, nativeAbiResult.symbolList)
if canDiffAbi(ctx.Config()) {
c.diffAbi(ctx)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index b10a3dd..a8722a0 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -79,7 +79,7 @@
minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
"-fno-sanitize-recover=integer,undefined"}
- memtagStackCommonFlags = []string{"-march=armv8-a+memtag"}
+ memtagStackCommonFlags = []string{"-Xclang -target-feature -Xclang +mte"}
memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"}
hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"}
@@ -1437,11 +1437,11 @@
//"null",
//"shift-base",
//"signed-integer-overflow",
- // TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
- // https://llvm.org/PR19302
- // http://reviews.llvm.org/D6974
- // "object-size",
)
+
+ if mctx.Config().ReleaseBuildObjectSizeSanitizer() {
+ sanitizers = append(sanitizers, "object-size")
+ }
}
sanitizers = append(sanitizers, sanProps.Misc_undefined...)
}
diff --git a/cmd/extract_apks/bundle_proto/Android.bp b/cmd/extract_apks/bundle_proto/Android.bp
index e56c0fb..0abf1e2 100644
--- a/cmd/extract_apks/bundle_proto/Android.bp
+++ b/cmd/extract_apks/bundle_proto/Android.bp
@@ -10,4 +10,8 @@
proto: {
canonical_path_from_root: false,
},
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//tools/mainline:__subpackages__",
+ ],
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 24a44b4..577c6cc 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -212,7 +212,14 @@
}
// Check if there are changes to the environment file, product variable file and
-// soong_build binary, in which case no incremental will be performed.
+// soong_build binary, in which case no incremental will be performed. For env
+// variables we check the used env file, which will be removed in soong ui if
+// there is any changes to the env variables used last time, in which case the
+// check below will fail and a full build will be attempted. If any new env
+// variables are added in the new run, soong ui won't be able to detect it, the
+// used env file check below will pass. But unless there is a soong build code
+// change, in which case the soong build binary check will fail, otherwise the
+// new env variables shouldn't have any affect.
func incrementalValid(config android.Config, configCacheFile string) (*ConfigCache, bool) {
var newConfigCache ConfigCache
data, err := os.ReadFile(shared.JoinPath(topDir, usedEnvFile))
diff --git a/cmd/symbols_map/Android.bp b/cmd/symbols_map/Android.bp
index e3ae6ed..272e806 100644
--- a/cmd/symbols_map/Android.bp
+++ b/cmd/symbols_map/Android.bp
@@ -30,4 +30,5 @@
srcs: [
"symbols_map_proto/symbols_map.pb.go",
],
+ visibility: ["//visibility:public"],
}
diff --git a/cmd/zip2zip/Android.bp b/cmd/zip2zip/Android.bp
index 3ef7668..7f9b165 100644
--- a/cmd/zip2zip/Android.bp
+++ b/cmd/zip2zip/Android.bp
@@ -27,4 +27,6 @@
"zip2zip.go",
],
testSrcs: ["zip2zip_test.go"],
+ // Used by genrules
+ visibility: ["//visibility:public"],
}
diff --git a/compliance/Android.bp b/compliance/Android.bp
new file mode 100644
index 0000000..08736b4
--- /dev/null
+++ b/compliance/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-compliance",
+ pkgPath: "android/soong/compliance",
+ deps: [
+ "soong-android",
+ ],
+ srcs: [
+ "notice.go",
+ ],
+ testSrcs: [
+ ],
+ pluginFor: ["soong_build"],
+}
+
+notice_xml {
+ name: "notice_xml_system",
+ partition_name: "system",
+ visibility: [
+ "//device/google/cuttlefish/system_image",
+ ],
+}
diff --git a/compliance/license_metadata_proto/Android.bp b/compliance/license_metadata_proto/Android.bp
index 3c041e4..4761285 100644
--- a/compliance/license_metadata_proto/Android.bp
+++ b/compliance/license_metadata_proto/Android.bp
@@ -24,4 +24,8 @@
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
],
+ visibility: [
+ "//build/make/tools/compliance:__subpackages__",
+ "//build/soong:__subpackages__",
+ ],
}
diff --git a/compliance/notice.go b/compliance/notice.go
new file mode 100644
index 0000000..4fc83ab
--- /dev/null
+++ b/compliance/notice.go
@@ -0,0 +1,100 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compliance
+
+import (
+ "path/filepath"
+
+ "android/soong/android"
+ "github.com/google/blueprint"
+)
+
+func init() {
+ RegisterNoticeXmlBuildComponents(android.InitRegistrationContext)
+}
+
+var PrepareForTestWithNoticeXmlBuildComponents = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(RegisterNoticeXmlBuildComponents),
+)
+
+var PrepareForTestWithNoticeXml = android.GroupFixturePreparers(
+ PrepareForTestWithNoticeXmlBuildComponents,
+)
+
+func RegisterNoticeXmlBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("notice_xml", NoticeXmlFactory)
+}
+
+var (
+ pctx = android.NewPackageContext("android/soong/compliance")
+
+ genNoticeXml = pctx.HostBinToolVariable("genNoticeXml", "gen_notice_xml")
+
+ // Command to generate NOTICE.xml.gz for a partition
+ genNoticeXmlRule = pctx.AndroidStaticRule("genNoticeXmlRule", blueprint.RuleParams{
+ Command: "rm -rf $out && " +
+ "${genNoticeXml} --output_file ${out} --metadata ${in} --partition ${partition} --product_out ${productOut} --soong_out ${soongOut}",
+ CommandDeps: []string{"${genNoticeXml}"},
+ }, "partition", "productOut", "soongOut")
+)
+
+func NoticeXmlFactory() android.Module {
+ m := &NoticeXmlModule{}
+ m.AddProperties(&m.props)
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibFirst)
+ return m
+}
+
+type NoticeXmlModule struct {
+ android.ModuleBase
+
+ props noticeXmlProperties
+
+ outputFile android.OutputPath
+ installPath android.InstallPath
+}
+
+type noticeXmlProperties struct {
+ Partition_name string
+}
+
+func (nx *NoticeXmlModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ output := android.PathForModuleOut(ctx, "NOTICE.xml.gz")
+ metadataDb := android.PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "compliance-metadata.db")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: genNoticeXmlRule,
+ Input: metadataDb,
+ Output: output,
+ Args: map[string]string{
+ "productOut": filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()),
+ "soongOut": ctx.Config().SoongOutDir(),
+ "partition": nx.props.Partition_name,
+ },
+ })
+
+ nx.outputFile = output.OutputPath
+
+ if android.Bool(ctx.Config().ProductVariables().UseSoongSystemImage) {
+ nx.installPath = android.PathForModuleInPartitionInstall(ctx, nx.props.Partition_name, "etc")
+ ctx.InstallFile(nx.installPath, "NOTICE.xml.gz", nx.outputFile)
+ }
+}
+
+func (nx *NoticeXmlModule) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(nx.outputFile),
+ }}
+}
diff --git a/compliance/notice_test.go b/compliance/notice_test.go
new file mode 100644
index 0000000..6187e53
--- /dev/null
+++ b/compliance/notice_test.go
@@ -0,0 +1,38 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compliance
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+var prepareForNoticeXmlTest = android.GroupFixturePreparers(
+ android.PrepareForTestWithArchMutator,
+ PrepareForTestWithNoticeXml,
+)
+
+func TestPrebuiltEtcOutputFile(t *testing.T) {
+ result := prepareForNoticeXmlTest.RunTestWithBp(t, `
+ notice_xml {
+ name: "notice_xml_system",
+ partition_name: "system",
+ }
+ `)
+
+ m := result.Module("notice_xml_system", "android_arm64_armv8-a").(*NoticeXmlModule)
+ android.AssertStringEquals(t, "output file", "NOTICE.xml.gz", m.outputFile.Base())
+}
\ No newline at end of file
diff --git a/compliance/project_metadata_proto/Android.bp b/compliance/project_metadata_proto/Android.bp
index 56e76e7..0c807b2 100644
--- a/compliance/project_metadata_proto/Android.bp
+++ b/compliance/project_metadata_proto/Android.bp
@@ -24,4 +24,5 @@
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
],
+ visibility: ["//build/make/tools/compliance:__subpackages__"],
}
diff --git a/docs/tidy.md b/docs/tidy.md
index ae0ca93..2e4c957 100644
--- a/docs/tidy.md
+++ b/docs/tidy.md
@@ -38,7 +38,7 @@
clang-tidy is enabled explicitly and with a different check list:
```
cc_defaults {
- name: "bpf_defaults",
+ name: "bpf_cc_defaults",
// snipped
tidy: true,
tidy_checks: [
@@ -52,7 +52,7 @@
}
```
That means in normal builds, even without `WITH_TIDY=1`,
-the modules that use `bpf_defaults` _should_ run clang-tidy
+the modules that use `bpf_cc_defaults` _should_ run clang-tidy
over C/C++ source files with the given `tidy_checks`.
However since clang-tidy warnings and its runtime cost might
diff --git a/etc/Android.bp b/etc/Android.bp
index f02c12a..580c54f 100644
--- a/etc/Android.bp
+++ b/etc/Android.bp
@@ -20,4 +20,6 @@
"install_symlink_test.go",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 0b39062..0353992 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -147,14 +147,14 @@
func filesystemFactory() android.Module {
module := &filesystem{}
module.filterPackagingSpec = module.filterInstallablePackagingSpec
- initFilesystemModule(module)
+ initFilesystemModule(module, module)
return module
}
-func initFilesystemModule(module *filesystem) {
- module.AddProperties(&module.properties)
- android.InitPackageModule(module)
- module.PackagingBase.DepsCollectFirstTargetOnly = true
+func initFilesystemModule(module android.DefaultableModule, filesystemModule *filesystem) {
+ module.AddProperties(&filesystemModule.properties)
+ android.InitPackageModule(filesystemModule)
+ filesystemModule.PackagingBase.DepsCollectFirstTargetOnly = true
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
}
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index a8fd368..63cb627 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -27,7 +27,7 @@
type systemImageProperties struct {
// Path to the input linker config json file.
- Linker_config_src *string
+ Linker_config_src *string `android:"path"`
}
// android_system_image is a specialization of android_filesystem for the 'system' partition.
@@ -38,7 +38,7 @@
module.AddProperties(&module.properties)
module.filesystem.buildExtraFiles = module.buildExtraFiles
module.filesystem.filterPackagingSpec = module.filterPackagingSpec
- initFilesystemModule(&module.filesystem)
+ initFilesystemModule(module, &module.filesystem)
return module
}
diff --git a/genrule/Android.bp b/genrule/Android.bp
index 7331741..f4197e6 100644
--- a/genrule/Android.bp
+++ b/genrule/Android.bp
@@ -22,4 +22,6 @@
"genrule_test.go",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/golang/golang.go b/golang/golang.go
index ede2150..618a085 100644
--- a/golang/golang.go
+++ b/golang/golang.go
@@ -96,17 +96,31 @@
outputFile := android.PathForArbitraryOutput(ctx, android.Rel(ctx, ctx.Config().OutDir(), g.IntermediateFile())).WithoutRel()
g.outputFile = outputFile
- installPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), outputFile)
+ // Don't create install rules for modules used by bootstrap, the install command line will differ from
+ // what was used during bootstrap, which will cause ninja to rebuild the module on the next run,
+ // triggering reanalysis.
+ if !usedByBootstrap(ctx.ModuleName()) {
+ installPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), outputFile)
- if !ctx.Config().KatiEnabled() || g.ExportedToMake() {
// Modules in an unexported namespace have no install rule, only add modules in the exported namespaces
// to the blueprint_tools phony rules.
- ctx.Phony("blueprint_tools", installPath)
+ if !ctx.Config().KatiEnabled() || g.ExportedToMake() {
+ ctx.Phony("blueprint_tools", installPath)
+ }
}
ctx.SetOutputFiles(android.Paths{outputFile}, "")
}
+func usedByBootstrap(name string) bool {
+ switch name {
+ case "loadplugins", "soong_build":
+ return true
+ default:
+ return false
+ }
+}
+
func (g *GoBinary) HostToolPath() android.OptionalPath {
return android.OptionalPathForPath(g.outputFile)
}
diff --git a/java/Android.bp b/java/Android.bp
index 9603815..1101d7a 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -72,7 +72,7 @@
"rro.go",
"sdk.go",
"sdk_library.go",
- "sdk_library_external.go",
+ "sdk_library_internal.go",
"support_libraries.go",
"system_modules.go",
"systemserver_classpath_fragment.go",
@@ -120,4 +120,5 @@
"test_spec_test.go",
],
pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
}
diff --git a/java/androidmk.go b/java/androidmk.go
index a1bc904..0539d25 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -415,7 +415,7 @@
} else {
var names []string
for _, jniLib := range app.jniLibs {
- names = append(names, jniLib.name)
+ names = append(names, jniLib.name+":"+jniLib.target.Arch.ArchType.Bitness())
}
entries.AddStrings("LOCAL_REQUIRED_MODULES", names...)
}
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 243a279..1d98b18 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -286,7 +286,7 @@
}{
{
name: "app",
- expected: []string{"libjni"},
+ expected: []string{"libjni:64"},
},
{
name: "app_embedded",
diff --git a/java/app_test.go b/java/app_test.go
index ec97a55..d7f5f0c 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -3241,7 +3241,7 @@
java_library {
name: "static-runtime-helper",
srcs: ["a.java"],
- libs: ["runtime-library"],
+ libs: ["runtime-library.impl"],
sdk_version: "current",
}
@@ -3305,7 +3305,7 @@
name: "app",
srcs: ["a.java"],
libs: [
- "qux",
+ "qux.impl",
"quuz.stubs"
],
static_libs: [
diff --git a/java/base.go b/java/base.go
index fc8cf95..129d722 100644
--- a/java/base.go
+++ b/java/base.go
@@ -535,7 +535,8 @@
linter
// list of the xref extraction files
- kytheFiles android.Paths
+ kytheFiles android.Paths
+ kytheKotlinFiles android.Paths
hideApexVariantFromMake bool
@@ -850,33 +851,6 @@
// Add dependency on libraries that provide additional hidden api annotations.
ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
- if ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
- // Require java_sdk_library at inter-partition java dependency to ensure stable
- // interface between partitions. If inter-partition java_library dependency is detected,
- // raise build error because java_library doesn't have a stable interface.
- //
- // Inputs:
- // PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY
- // if true, enable enforcement
- // PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST
- // exception list of java_library names to allow inter-partition dependency
- for idx := range j.properties.Libs {
- if libDeps[idx] == nil {
- continue
- }
-
- if javaDep, ok := libDeps[idx].(javaSdkLibraryEnforceContext); ok {
- // java_sdk_library is always allowed at inter-partition dependency.
- // So, skip check.
- if _, ok := javaDep.(*SdkLibrary); ok {
- continue
- }
-
- j.checkPartitionsForJavaDependency(ctx, "libs", javaDep)
- }
- }
- }
-
// For library dependencies that are component libraries (like stubs), add the implementation
// as a dependency (dexpreopt needs to be against the implementation library, not stubs).
for _, dep := range libDeps {
@@ -1367,7 +1341,7 @@
kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)
- kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
if ctx.Failed() {
return
}
@@ -1790,14 +1764,14 @@
classesJar: outputFile,
jarName: jarName,
}
- if j.GetProfileGuided() && j.optimizeOrObfuscateEnabled() && !j.EnableProfileRewriting() {
+ if j.GetProfileGuided(ctx) && j.optimizeOrObfuscateEnabled() && !j.EnableProfileRewriting(ctx) {
ctx.PropertyErrorf("enable_profile_rewriting",
"Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on. The attached profile should be sourced from an unoptimized/unobfuscated APK.",
)
}
- if j.EnableProfileRewriting() {
- profile := j.GetProfile()
- if profile == "" || !j.GetProfileGuided() {
+ if j.EnableProfileRewriting(ctx) {
+ profile := j.GetProfile(ctx)
+ if profile == "" || !j.GetProfileGuided(ctx) {
ctx.PropertyErrorf("enable_profile_rewriting", "Profile and Profile_guided must be set when enable_profile_rewriting is true")
}
params.artProfileInput = &profile
@@ -2414,18 +2388,13 @@
return
}
- if dep, ok := module.(SdkLibraryDependency); ok {
+ if _, ok := module.(SdkLibraryDependency); ok {
switch tag {
- case sdkLibTag, libTag:
- depHeaderJars := dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))
- deps.classpath = append(deps.classpath, depHeaderJars...)
- deps.dexClasspath = append(deps.dexClasspath, depHeaderJars...)
-
- // TODO: SDK libraries should export a provider with TransitiveClasspathHeaderJars
- depHeaderJarsSet := android.NewDepSet(android.PREORDER, depHeaderJars, nil)
- transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, depHeaderJarsSet)
- case staticLibTag:
- ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
+ case sdkLibTag, libTag, staticLibTag:
+ sdkInfo, _ := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider)
+ generatingLibsString := android.PrettyConcat(
+ getGeneratingLibs(ctx, j.SdkVersion(ctx), module.Name(), sdkInfo), true, "or")
+ ctx.ModuleErrorf("cannot depend directly on java_sdk_library %q; try depending on %s instead", module.Name(), generatingLibsString)
}
} else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
if sdkLinkType != javaPlatform {
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index fe4cc76..4fcd40b 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -414,6 +414,12 @@
// Cross-cutting metadata dependencies are metadata.
return false
}
+ // Dependency to the bootclasspath fragment of another apex
+ // e.g. concsrypt-bootclasspath-fragment --> art-bootclasspath-fragment
+ if tag == bootclasspathFragmentDepTag {
+ return false
+
+ }
panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
}
@@ -1099,22 +1105,10 @@
return &output
}
+// DEPRECATED: this information is now generated in the context of the top level prebuilt apex.
// produceBootImageProfile extracts the boot image profile from the APEX if available.
func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx android.ModuleContext) android.WritablePath {
- // This module does not provide a boot image profile.
- if module.getProfileProviderApex(ctx) == "" {
- return nil
- }
-
- di, err := android.FindDeapexerProviderForModule(ctx)
- if err != nil {
- // An error was found, possibly due to multiple apexes in the tree that export this library
- // Defer the error till a client tries to call getProfilePath
- module.profilePathErr = err
- return nil // An error has been reported by FindDeapexerProviderForModule.
- }
-
- return di.PrebuiltExportPath(ProfileInstallPathInApex)
+ return android.PathForModuleInstall(ctx, "intentionally_no_longer_supported")
}
func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
diff --git a/java/config/Android.bp b/java/config/Android.bp
index bfe83ab..6217390 100644
--- a/java/config/Android.bp
+++ b/java/config/Android.bp
@@ -17,4 +17,8 @@
"kotlin.go",
"makevars.go",
],
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//external/error_prone/soong",
+ ],
}
diff --git a/java/config/config.go b/java/config/config.go
index c28e070..4c1c723 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -145,6 +145,7 @@
pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod")
pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar")
pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar")
+ pctx.SourcePathVariable("KotlinKytheExtractor", "prebuilts/build-tools/${hostPrebuiltTag}/bin/kotlinc_extractor")
pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime")
pctx.SourcePathVariable("ResourceProcessorBusyBox", "prebuilts/bazel/common/android_tools/android_tools/all_android_tools_deploy.jar")
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index e5e187c..302d021 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -50,4 +50,11 @@
}, " "))
pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{}, " "))
+ // Use KotlincKytheGlobalFlags to prevent kotlinc version skew issues between android and
+ // g3 kythe indexers.
+ // This is necessary because there might be instances of kotlin code in android
+ // platform that are not fully compatible with the kotlinc used in g3 kythe indexers.
+ // e.g. uninitialized variables are a warning in 1.*, but an error in 2.*
+ // https://github.com/JetBrains/kotlin/blob/master/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt#L748
+ pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " "))
}
diff --git a/java/dex.go b/java/dex.go
index 7d42efc..faf51a3 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -120,7 +120,7 @@
}
func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleContext) bool {
- return d.resourceShrinkingEnabled(ctx) && Bool(d.Optimize.Optimized_shrink_resources)
+ return d.resourceShrinkingEnabled(ctx) && BoolDefault(d.Optimize.Optimized_shrink_resources, ctx.Config().UseOptimizedResourceShrinkingByDefault())
}
func (d *dexer) optimizeOrObfuscateEnabled() bool {
@@ -220,14 +220,28 @@
deps = append(deps, f)
}
+ var requestReleaseMode bool
+ requestReleaseMode, flags = android.RemoveFromList("--release", flags)
+
if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" {
flags = append(flags, "--debug")
+ requestReleaseMode = false
}
if ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" {
flags = append(flags,
"--debug",
"--verbose")
+ requestReleaseMode = false
+ }
+
+ // Don't strip out debug information for eng builds, unless the target
+ // explicitly provided the `--release` build flag. This allows certain
+ // test targets to remain optimized as part of eng test_suites builds.
+ if requestReleaseMode {
+ flags = append(flags, "--release")
+ } else if ctx.Config().Eng() {
+ flags = append(flags, "--debug")
}
// Supplying the platform build flag disables various features like API modeling and desugaring.
@@ -245,6 +259,16 @@
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err)
}
+ if !Bool(d.dexProperties.No_dex_container) && effectiveVersion.FinalOrFutureInt() >= 36 {
+ // W is 36, but we have not bumped the SDK version yet, so check for both.
+ if ctx.Config().PlatformSdkVersion().FinalInt() >= 36 ||
+ ctx.Config().PlatformSdkCodename() == "Wear" {
+ // TODO(b/329465418): Skip this module since it causes issue with app DRM
+ if ctx.ModuleName() != "framework-minus-apex" {
+ flags = append([]string{"-JDcom.android.tools.r8.dexContainerExperiment"}, flags...)
+ }
+ }
+ }
// If the specified SDK level is 10000, then configure the compiler to use the
// current platform SDK level and to compile the build as a platform build.
@@ -374,11 +398,6 @@
// TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
// dictionary of the app and move the app from libraryjars to injars.
- // Don't strip out debug information for eng builds.
- if ctx.Config().Eng() {
- r8Flags = append(r8Flags, "--debug")
- }
-
// TODO(b/180878971): missing classes should be added to the relevant builds.
// TODO(b/229727645): do not use true as default for Android platform builds.
if proptools.BoolDefault(opt.Ignore_warnings, true) {
@@ -390,7 +409,7 @@
r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String())
r8Deps = append(r8Deps, d.resourcesInput.Path())
r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String())
- if Bool(opt.Optimized_shrink_resources) {
+ if d.dexProperties.optimizedResourceShrinkingEnabled(ctx) {
r8Flags = append(r8Flags, "--optimized-resource-shrinking")
}
}
diff --git a/java/dex_test.go b/java/dex_test.go
index 4862d06..8bc28e6 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -713,3 +713,97 @@
}
}`)
}
+
+func TestDebugReleaseFlags(t *testing.T) {
+ bp := `
+ android_app {
+ name: "app",
+ srcs: ["foo.java"],
+ platform_apis: true,
+ dxflags: ["%s"]
+ }
+ `
+
+ testcases := []struct {
+ name string
+ envVar string
+ isEng bool
+ dxFlags string
+ expectedFlags string
+ }{
+ {
+ name: "app_no_optimize_dx",
+ envVar: "NO_OPTIMIZE_DX",
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_release_no_optimize_dx",
+ envVar: "NO_OPTIMIZE_DX",
+ dxFlags: "--release",
+ // Global env vars override explicit dxflags.
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_generate_dex_debug",
+ envVar: "GENERATE_DEX_DEBUG",
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_release_generate_dex_debug",
+ envVar: "GENERATE_DEX_DEBUG",
+ dxFlags: "--release",
+ // Global env vars override explicit dxflags.
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_eng",
+ isEng: true,
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_release_eng",
+ isEng: true,
+ dxFlags: "--release",
+ // Eng mode does *not* override explicit dxflags.
+ expectedFlags: "--release",
+ },
+ }
+
+ for _, tc := range testcases {
+ t.Run(tc.name, func(t *testing.T) {
+ fixturePreparer := PrepareForTestWithJavaDefaultModules
+ fixturePreparer = android.GroupFixturePreparers(
+ fixturePreparer,
+ android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.Eng = proptools.BoolPtr(tc.isEng)
+ },
+ ),
+ )
+ if tc.envVar != "" {
+ fixturePreparer = android.GroupFixturePreparers(
+ fixturePreparer,
+ android.FixtureMergeEnv(map[string]string{
+ tc.envVar: "true",
+ }),
+ )
+ }
+ result := fixturePreparer.RunTestWithBp(t, fmt.Sprintf(bp, tc.dxFlags))
+
+ appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
+ android.AssertStringDoesContain(t, "expected flag in R8 flags",
+ appR8.Args["r8Flags"], tc.expectedFlags)
+
+ var unexpectedFlags string
+ if tc.expectedFlags == "--debug" {
+ unexpectedFlags = "--release"
+ } else if tc.expectedFlags == "--release" {
+ unexpectedFlags = "--debug"
+ }
+ if unexpectedFlags != "" {
+ android.AssertStringDoesNotContain(t, "unexpected flag in R8 flags",
+ appR8.Args["r8Flags"], unexpectedFlags)
+ }
+ })
+ }
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 4734357..63a8634 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -147,25 +147,25 @@
type DexpreoptProperties struct {
Dex_preopt struct {
// If false, prevent dexpreopting. Defaults to true.
- Enabled *bool
+ Enabled proptools.Configurable[bool] `android:"replace_instead_of_append"`
// If true, generate an app image (.art file) for this module.
- App_image *bool
+ App_image proptools.Configurable[bool] `android:"replace_instead_of_append"`
// If true, use a checked-in profile to guide optimization. Defaults to false unless
// a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR
// that matches the name of this module, in which case it is defaulted to true.
- Profile_guided *bool
+ Profile_guided proptools.Configurable[bool] `android:"replace_instead_of_append"`
// If set, provides the path to profile relative to the Android.bp file. If not set,
// defaults to searching for a file that matches the name of this module in the default
// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
- Profile *string `android:"path"`
+ Profile proptools.Configurable[string] `android:"path,replace_instead_of_append"`
// If set to true, r8/d8 will use `profile` as input to generate a new profile that matches
// the optimized dex.
// The new profile will be subsequently used as the profile to dexpreopt the dex file.
- Enable_profile_rewriting *bool
+ Enable_profile_rewriting proptools.Configurable[bool] `android:"replace_instead_of_append"`
}
Dex_preopt_result struct {
@@ -244,7 +244,7 @@
return true
}
- if !BoolDefault(d.dexpreoptProperties.Dex_preopt.Enabled, true) {
+ if !d.dexpreoptProperties.Dex_preopt.Enabled.GetOrDefault(ctx, true) {
return true
}
@@ -433,12 +433,12 @@
if d.inputProfilePathOnHost != nil {
profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
- } else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) {
+ } else if d.dexpreoptProperties.Dex_preopt.Profile_guided.GetOrDefault(ctx, true) && !forPrebuiltApex(ctx) {
// If enable_profile_rewriting is set, use the rewritten profile instead of the checked-in profile
- if d.EnableProfileRewriting() {
+ if d.EnableProfileRewriting(ctx) {
profileClassListing = android.OptionalPathForPath(d.GetRewrittenProfile())
profileIsTextListing = true
- } else if profile := d.GetProfile(); profile != "" {
+ } else if profile := d.GetProfile(ctx); profile != "" {
// If dex_preopt.profile_guided is not set, default it based on the existence of the
// dexprepot.profile option or the profile class listing.
profileClassListing = android.OptionalPathForPath(
@@ -458,6 +458,8 @@
// Use the dexJar to create a unique scope for each
dexJarStem := strings.TrimSuffix(dexJarFile.Base(), dexJarFile.Ext())
+ appImage := d.dexpreoptProperties.Dex_preopt.App_image.Get(ctx)
+
// Full dexpreopt config, used to create dexpreopt build rules.
dexpreoptConfig := &dexpreopt.ModuleConfig{
Name: libName,
@@ -486,8 +488,8 @@
PreoptBootClassPathDexFiles: dexFiles.Paths(),
PreoptBootClassPathDexLocations: dexLocations,
- NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
- ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
+ NoCreateAppImage: !appImage.GetOrDefault(true),
+ ForceCreateAppImage: appImage.GetOrDefault(false),
PresignedPrebuilt: d.isPresignedPrebuilt,
}
@@ -657,16 +659,16 @@
d.shouldDisableDexpreopt = true
}
-func (d *dexpreopter) EnableProfileRewriting() bool {
- return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting)
+func (d *dexpreopter) EnableProfileRewriting(ctx android.BaseModuleContext) bool {
+ return d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting.GetOrDefault(ctx, false)
}
-func (d *dexpreopter) GetProfile() string {
- return proptools.String(d.dexpreoptProperties.Dex_preopt.Profile)
+func (d *dexpreopter) GetProfile(ctx android.BaseModuleContext) string {
+ return d.dexpreoptProperties.Dex_preopt.Profile.GetOrDefault(ctx, "")
}
-func (d *dexpreopter) GetProfileGuided() bool {
- return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Profile_guided)
+func (d *dexpreopter) GetProfileGuided(ctx android.BaseModuleContext) bool {
+ return d.dexpreoptProperties.Dex_preopt.Profile_guided.GetOrDefault(ctx, false)
}
func (d *dexpreopter) GetRewrittenProfile() android.Path {
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index a2e4734..ad0e0a7 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -463,6 +463,7 @@
func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
+ ctx.RegisterModuleType("art_boot_images", artBootImagesFactory)
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator).Parallel()
})
@@ -601,6 +602,7 @@
d.defaultBootImage = defaultBootImageConfig(ctx)
d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
var profileInstalls android.RuleBuilderInstalls
+ var artBootImageHostInstalls android.RuleBuilderInstalls
for _, name := range getImageNames() {
config := imageConfigs[name]
if config != d.defaultBootImage {
@@ -616,6 +618,18 @@
d.bootFrameworkProfile = bootProfile
profileInstalls = append(profileInstalls, installs...)
}
+ // Gather the install files of the host variant of the ART boot image.
+ // These installed files will be used in ART tests.
+ if config.name == "art" {
+ for _, variant := range config.variants {
+ if variant.target.Os != ctx.Config().BuildOS {
+ // not a host variant
+ continue
+ }
+ artBootImageHostInstalls = append(artBootImageHostInstalls, variant.installs...)
+ artBootImageHostInstalls = append(artBootImageHostInstalls, variant.vdexInstalls...)
+ }
+ }
}
if len(profileInstalls) > 0 {
android.SetProvider(ctx, profileInstallInfoProvider, profileInstallInfo{
@@ -626,6 +640,15 @@
installFile(ctx, install)
}
}
+ // Set a provider containing the install files of the host variant of the ART boot image.
+ // The actual install rules will be created by `art_boot_images`
+ android.SetProvider(
+ ctx,
+ artBootImageHostInfoProvider,
+ artBootImageHostInfo{
+ installs: artBootImageHostInstalls,
+ },
+ )
}
// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make.
@@ -968,6 +991,14 @@
}
}
+var artBootImageHostInfoProvider = blueprint.NewProvider[artBootImageHostInfo]()
+
+// artBootImageHostInfo contains the install locations of the host variant of ART boot image
+// this contains both the primary and secondary arch locations
+type artBootImageHostInfo struct {
+ installs android.RuleBuilderInstalls
+}
+
// Generate boot image build rules for a specific target.
func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs {
@@ -1396,3 +1427,70 @@
OutputFile: android.OptionalPathForPath(d.bootFrameworkProfile),
}}
}
+
+// artBootImages is a thin wrapper around `dex_bootjars`.
+// it creates the installation rules for the host variant of the ART boot image.
+type artBootImages struct {
+ android.ModuleBase
+
+ // A non-empty file that will be written as `LOCAL_SOONG_INSTALLED_MODULE` in out/soong/Android-*.mk
+ outputFile android.OptionalPath
+}
+
+func artBootImagesFactory() android.Module {
+ m := &artBootImages{}
+ android.InitAndroidMultiTargetsArchModule(m, android.HostSupported, android.MultilibCommon)
+ return m
+}
+
+func (dbj *artBootImages) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Create a dependency on `dex_bootjars` to access the intermediate locations of host art boot image.
+ ctx.AddDependency(ctx.Module(), dexpreoptBootJarDepTag, "dex_bootjars")
+}
+
+func (d *artBootImages) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(m android.Module) {
+ hostInstallsInfo, ok := android.OtherModuleProvider(ctx, m, artBootImageHostInfoProvider)
+ if !ok {
+ ctx.ModuleErrorf("Could not find information about the host variant of ART boot image")
+ }
+ installs := d.installFile(ctx, hostInstallsInfo.installs)
+ if len(installs) > 0 {
+ d.outputFile = android.OptionalPathForPath(installs[0])
+ // Create a phony target that can ART run-tests can depend on.
+ ctx.Phony(d.Name(), installs...)
+ } else {
+ // this might be true e.g. when building with `WITH_DEXPREOPT=false`
+ // create an empty file so that the `art_boot_images` is known to the packaging system.
+ d.outputFile = android.OptionalPathForPath(android.PathForModuleOut(ctx, "undefined_art_boot_images"))
+ }
+ })
+}
+
+// Creates an installation rule for host variant of ART boot image files.
+// Returns the list of install locations (out/host/linux-x86/...)
+func (d *artBootImages) installFile(ctx android.ModuleContext, ruleBuilderInstalls android.RuleBuilderInstalls) android.Paths {
+ var ret android.Paths
+ for _, ruleBuilderInstall := range ruleBuilderInstalls {
+ installDir := android.PathForModuleInstall(
+ ctx,
+ strings.TrimPrefix(filepath.Dir(ruleBuilderInstall.To), "/"),
+ )
+ filename := filepath.Base(ruleBuilderInstall.To)
+ ctx.InstallFile(
+ installDir,
+ filename,
+ ruleBuilderInstall.From,
+ )
+ ret = append(ret, installDir.Join(ctx, filename))
+ }
+ return ret
+}
+
+// Set `OutputFile` expclitly so that this module does not get elided when generating out/soong/Android-*.mk
+func (d *artBootImages) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: d.outputFile,
+ }}
+}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 2929bb8..a7e92d9 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -373,8 +373,11 @@
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
}
case libTag, sdkLibTag:
- if dep, ok := module.(SdkLibraryDependency); ok {
- deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
+ if _, ok := module.(SdkLibraryDependency); ok {
+ sdkInfo, _ := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider)
+ generatingLibsString := android.PrettyConcat(
+ getGeneratingLibs(ctx, j.SdkVersion(ctx), module.Name(), sdkInfo), true, "or")
+ ctx.ModuleErrorf("cannot depend directly on java_sdk_library %q; try depending on %s instead", module.Name(), generatingLibsString)
} else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
deps.classpath = append(deps.classpath, dep.HeaderJars...)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
diff --git a/java/java.go b/java/java.go
index 1fa0830..c6fa663 100644
--- a/java/java.go
+++ b/java/java.go
@@ -356,12 +356,17 @@
// TODO(jungjw): Move this to kythe.go once it's created.
type xref interface {
XrefJavaFiles() android.Paths
+ XrefKotlinFiles() android.Paths
}
func (j *Module) XrefJavaFiles() android.Paths {
return j.kytheFiles
}
+func (j *Module) XrefKotlinFiles() android.Paths {
+ return j.kytheKotlinFiles
+}
+
func (d dependencyTag) PropagateAconfigValidation() bool {
return d.static
}
@@ -2691,13 +2696,13 @@
transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
}
}
- } else if dep, ok := module.(SdkLibraryDependency); ok {
+ } else if _, ok := module.(SdkLibraryDependency); ok {
switch tag {
case libTag, sdkLibTag:
- depHeaderJars := dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))
- flags.classpath = append(flags.classpath, depHeaderJars...)
- transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars,
- android.NewDepSet(android.PREORDER, depHeaderJars, nil))
+ sdkInfo, _ := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider)
+ generatingLibsString := android.PrettyConcat(
+ getGeneratingLibs(ctx, j.SdkVersion(ctx), module.Name(), sdkInfo), true, "or")
+ ctx.ModuleErrorf("cannot depend directly on java_sdk_library %q; try depending on %s instead", module.Name(), generatingLibsString)
}
}
@@ -2809,41 +2814,14 @@
}
if ctx.Device() {
- // If this is a variant created for a prebuilt_apex then use the dex implementation jar
- // obtained from the associated deapexer module.
+ // Shared libraries deapexed from prebuilt apexes are no longer supported.
+ // Set the dexJarBuildPath to a fake path.
+ // This allows soong analysis pass, but will be an error during ninja execution if there are
+ // any rdeps.
ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex {
- // Get the path of the dex implementation jar from the `deapexer` module.
- di, err := android.FindDeapexerProviderForModule(ctx)
- if err != nil {
- // An error was found, possibly due to multiple apexes in the tree that export this library
- // Defer the error till a client tries to call DexJarBuildPath
- j.dexJarFileErr = err
- j.initHiddenAPIError(err)
- return
- }
- dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(j.BaseModuleName())
- if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
- dexJarFile := makeDexJarPathFromPath(dexOutputPath)
- j.dexJarFile = dexJarFile
- installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, ApexRootRelativePathToJavaLib(j.BaseModuleName()))
- j.dexJarInstallFile = installPath
-
- j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
- setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
- j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
-
- if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
- j.dexpreopter.inputProfilePathOnHost = profilePath
- }
-
- // Initialize the hiddenapi structure.
- j.initHiddenAPI(ctx, dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
- } else {
- // This should never happen as a variant for a prebuilt_apex is only created if the
- // prebuilt_apex has been configured to export the java library dex file.
- ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
- }
+ j.dexJarFile = makeDexJarPathFromPath(android.PathForModuleInstall(ctx, "intentionally_no_longer_supported"))
+ j.initHiddenAPI(ctx, j.dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
} else if Bool(j.dexProperties.Compile_dex) {
sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
if sdkDep.invalidVersion {
@@ -3296,15 +3274,20 @@
func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var xrefTargets android.Paths
+ var xrefKotlinTargets android.Paths
ctx.VisitAllModules(func(module android.Module) {
if javaModule, ok := module.(xref); ok {
xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...)
+ xrefKotlinTargets = append(xrefKotlinTargets, javaModule.XrefKotlinFiles()...)
}
})
// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
if len(xrefTargets) > 0 {
ctx.Phony("xref_java", xrefTargets...)
}
+ if len(xrefKotlinTargets) > 0 {
+ ctx.Phony("xref_kotlin", xrefKotlinTargets...)
+ }
}
var Bool = proptools.Bool
@@ -3327,6 +3310,10 @@
if lib, ok := depModule.(SdkLibraryDependency); ok && lib.sharedLibrary() {
// A shared SDK library. This should be added as a top-level CLC element.
sdkLib = &depName
+ } else if lib, ok := depModule.(SdkLibraryComponentDependency); ok && lib.OptionalSdkLibraryImplementation() != nil {
+ if depModule.Name() == proptools.String(lib.OptionalSdkLibraryImplementation())+".impl" {
+ sdkLib = lib.OptionalSdkLibraryImplementation()
+ }
} else if ulib, ok := depModule.(ProvidesUsesLib); ok {
// A non-SDK library disguised as an SDK library by the means of `provides_uses_lib`
// property. This should be handled in the same way as a shared SDK library.
diff --git a/java/java_test.go b/java/java_test.go
index dbbf4a8..641bf40 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -670,7 +670,7 @@
java_library {
name: "foo",
srcs: ["a.java", ":stubs-source"],
- libs: ["bar", "sdklib"],
+ libs: ["bar", "sdklib.stubs"],
static_libs: ["baz"],
}
diff --git a/java/kotlin.go b/java/kotlin.go
index c28bc3f..f42d163 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -64,6 +64,28 @@
"kotlincFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "classesDir",
"headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name")
+var kotlinKytheExtract = pctx.AndroidStaticRule("kotlinKythe",
+ blueprint.RuleParams{
+ Command: `rm -rf "$srcJarDir" && mkdir -p "$srcJarDir" && ` +
+ `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" -f "*.kt" $srcJars && ` +
+ `${config.KotlinKytheExtractor} -corpus ${kytheCorpus} --srcs @$out.rsp --srcs @"$srcJarDir/list" $commonSrcFilesList --cp @$classpath -o $out --kotlin_out $outJar ` +
+ // wrap the additional kotlin args.
+ // Skip Xbuild file, pass the cp explicitly.
+ // Skip header jars, those should not have an effect on kythe results.
+ ` --args '${config.KotlincGlobalFlags} ` +
+ ` ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` +
+ ` $kotlincFlags -jvm-target $kotlinJvmTarget ` +
+ `${config.KotlincKytheGlobalFlags}'`,
+ CommandDeps: []string{
+ "${config.KotlinKytheExtractor}",
+ "${config.ZipSyncCmd}",
+ },
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
+ },
+ "classpath", "kotlincFlags", "commonSrcFilesList", "kotlinJvmTarget", "outJar", "srcJars", "srcJarDir",
+)
+
func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Paths) android.OptionalPath {
if len(commonSrcFiles) > 0 {
// The list of common_srcs may be too long to put on the command line, but
@@ -81,7 +103,7 @@
}
// kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile.
-func kotlinCompile(ctx android.ModuleContext, outputFile, headerOutputFile android.WritablePath,
+func (j *Module) kotlinCompile(ctx android.ModuleContext, outputFile, headerOutputFile android.WritablePath,
srcFiles, commonSrcFiles, srcJars android.Paths,
flags javaBuilderFlags) {
@@ -127,6 +149,31 @@
"name": kotlinName,
},
})
+
+ // Emit kythe xref rule
+ if (ctx.Config().EmitXrefRules()) && ctx.Module() == ctx.PrimaryModule() {
+ extractionFile := outputFile.ReplaceExtension(ctx, "kzip")
+ args := map[string]string{
+ "classpath": classpathRspFile.String(),
+ "kotlincFlags": flags.kotlincFlags,
+ "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(),
+ "outJar": outputFile.String(),
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars.xref").String(),
+ }
+ if commonSrcsList.Valid() {
+ args["commonSrcFilesList"] = "--common_srcs @" + commonSrcsList.String()
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: kotlinKytheExtract,
+ Description: "kotlinKythe",
+ Output: extractionFile,
+ Inputs: srcFiles,
+ Implicits: deps,
+ Args: args,
+ })
+ j.kytheKotlinFiles = append(j.kytheKotlinFiles, extractionFile)
+ }
}
var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupports{Goma: true},
diff --git a/java/metalava/Android.bp b/java/metalava/Android.bp
index ccbd191..6bf1832 100644
--- a/java/metalava/Android.bp
+++ b/java/metalava/Android.bp
@@ -15,4 +15,5 @@
filegroup {
name: "metalava-config-files",
srcs: ["*-config.xml"],
+ visibility: ["//visibility:public"],
}
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 67ed84e..5b145c6 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -110,6 +110,7 @@
p.installConfigFile = android.PathForModuleInstall(ctx, "etc", "compatconfig", p.configFile.Base())
rule.Build(configFileName, "Extract compat/compat_config.xml and install it")
ctx.InstallFile(p.installDirPath, p.configFile.Base(), p.configFile)
+ ctx.SetOutputFiles(android.Paths{p.configFile}, "")
}
func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 00613ee..527e479 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -124,8 +124,8 @@
return
}
-func prebuiltApiModuleName(mctx android.LoadHookContext, module, scope, version string) string {
- return fmt.Sprintf("%s_%s_%s_%s", mctx.ModuleName(), scope, version, module)
+func prebuiltApiModuleName(moduleName, module, scope, version string) string {
+ return fmt.Sprintf("%s_%s_%s_%s", moduleName, scope, version, module)
}
func createImport(mctx android.LoadHookContext, module, scope, version, path, sdkVersion string, compileDex bool) {
props := struct {
@@ -135,7 +135,7 @@
Installable *bool
Compile_dex *bool
}{
- Name: proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, version)),
+ Name: proptools.StringPtr(prebuiltApiModuleName(mctx.ModuleName(), module, scope, version)),
Jars: []string{path},
Sdk_version: proptools.StringPtr(sdkVersion),
Installable: proptools.BoolPtr(false),
@@ -257,8 +257,8 @@
Name *string
Libs []string
}{}
- props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", scope, version))
- props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", scope, version))
+ props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx.ModuleName(), "system_modules", scope, version))
+ props.Libs = append(props.Libs, prebuiltApiModuleName(mctx.ModuleName(), "core-for-system-modules", scope, version))
mctx.CreateModule(systemModulesImportFactory, &props)
}
diff --git a/java/ravenwood.go b/java/ravenwood.go
index bb136cf..9239bbd 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -33,8 +33,8 @@
var ravenwoodLibContentTag = dependencyTag{name: "ravenwoodlibcontent"}
var ravenwoodUtilsTag = dependencyTag{name: "ravenwoodutils"}
var ravenwoodRuntimeTag = dependencyTag{name: "ravenwoodruntime"}
-var ravenwoodDataTag = dependencyTag{name: "ravenwooddata"}
var ravenwoodTestResourceApkTag = dependencyTag{name: "ravenwoodtestresapk"}
+var ravenwoodTestInstResourceApkTag = dependencyTag{name: "ravenwoodtest-inst-res-apk"}
const ravenwoodUtilsName = "ravenwood-utils"
const ravenwoodRuntimeName = "ravenwood-runtime"
@@ -57,11 +57,17 @@
Jni_libs []string
// Specify another android_app module here to copy it to the test directory, so that
- // the ravenwood test can access it.
+ // the ravenwood test can access it. This APK will be loaded as resources of the test
+ // target app.
// TODO: For now, we simply refer to another android_app module and copy it to the
// test directory. Eventually, android_ravenwood_test should support all the resource
// related properties and build resources from the `res/` directory.
Resource_apk *string
+
+ // Specify another android_app module here to copy it to the test directory, so that
+ // the ravenwood test can access it. This APK will be loaded as resources of the test
+ // instrumentation app itself.
+ Inst_resource_apk *string
}
type ravenwoodTest struct {
@@ -128,6 +134,10 @@
if resourceApk := proptools.String(r.ravenwoodTestProperties.Resource_apk); resourceApk != "" {
ctx.AddVariationDependencies(nil, ravenwoodTestResourceApkTag, resourceApk)
}
+
+ if resourceApk := proptools.String(r.ravenwoodTestProperties.Inst_resource_apk); resourceApk != "" {
+ ctx.AddVariationDependencies(nil, ravenwoodTestInstResourceApkTag, resourceApk)
+ }
}
func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -195,13 +205,16 @@
}
resApkInstallPath := installPath.Join(ctx, "ravenwood-res-apks")
- if resApk := ctx.GetDirectDepsWithTag(ravenwoodTestResourceApkTag); len(resApk) > 0 {
- for _, installFile := range android.OtherModuleProviderOrDefault(
- ctx, resApk[0], android.InstallFilesProvider).InstallFiles {
- installResApk := ctx.InstallFile(resApkInstallPath, "ravenwood-res.apk", installFile)
+
+ copyResApk := func(tag blueprint.DependencyTag, toFileName string) {
+ if resApk := ctx.GetDirectDepsWithTag(tag); len(resApk) > 0 {
+ installFile := android.OutputFileForModule(ctx, resApk[0], "")
+ installResApk := ctx.InstallFile(resApkInstallPath, toFileName, installFile)
installDeps = append(installDeps, installResApk)
}
}
+ copyResApk(ravenwoodTestResourceApkTag, "ravenwood-res.apk")
+ copyResApk(ravenwoodTestInstResourceApkTag, "ravenwood-inst-res.apk")
// Install our JAR with all dependencies
ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
@@ -228,7 +241,10 @@
Jni_libs []string
// We use this to copy framework-res.apk to the ravenwood runtime directory.
- Data []string
+ Data []string `android:"path,arch_variant"`
+
+ // We use this to copy font files to the ravenwood runtime directory.
+ Fonts []string `android:"path,arch_variant"`
}
type ravenwoodLibgroup struct {
@@ -267,9 +283,6 @@
for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs {
ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
}
- for _, data := range r.ravenwoodLibgroupProperties.Data {
- ctx.AddVariationDependencies(nil, ravenwoodDataTag, data)
- }
}
func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -309,12 +322,17 @@
}
dataInstallPath := installPath.Join(ctx, "ravenwood-data")
- for _, data := range r.ravenwoodLibgroupProperties.Data {
- libModule := ctx.GetDirectDepWithTag(data, ravenwoodDataTag)
- file := android.OutputFileForModule(ctx, libModule, "")
+ data := android.PathsForModuleSrc(ctx, r.ravenwoodLibgroupProperties.Data)
+ for _, file := range data {
ctx.InstallFile(dataInstallPath, file.Base(), file)
}
+ fontsInstallPath := installPath.Join(ctx, "fonts")
+ fonts := android.PathsForModuleSrc(ctx, r.ravenwoodLibgroupProperties.Fonts)
+ for _, file := range fonts {
+ ctx.InstallFile(fontsInstallPath, file.Base(), file)
+ }
+
// Normal build should perform install steps
ctx.Phony(r.BaseModuleName(), android.PathForPhony(ctx, r.BaseModuleName()+"-install"))
}
diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go
index d26db93..753a118 100644
--- a/java/ravenwood_test.go
+++ b/java/ravenwood_test.go
@@ -19,6 +19,7 @@
"testing"
"android/soong/android"
+ "android/soong/etc"
)
var prepareRavenwoodRuntime = android.GroupFixturePreparers(
@@ -59,11 +60,19 @@
}
android_app {
name: "app1",
- sdk_version: "current",
+ sdk_version: "current",
}
android_app {
name: "app2",
- sdk_version: "current",
+ sdk_version: "current",
+ }
+ android_app {
+ name: "app3",
+ sdk_version: "current",
+ }
+ prebuilt_font {
+ name: "Font.ttf",
+ src: "Font.ttf",
}
android_ravenwood_libgroup {
name: "ravenwood-runtime",
@@ -76,7 +85,10 @@
"ravenwood-runtime-jni2",
],
data: [
- "app1",
+ ":app1",
+ ],
+ fonts: [
+ ":Font.ttf"
],
}
android_ravenwood_libgroup {
@@ -97,6 +109,7 @@
ctx := android.GroupFixturePreparers(
PrepareForIntegrationTestWithJava,
+ etc.PrepareForTestWithPrebuiltEtc,
prepareRavenwoodRuntime,
).RunTest(t)
@@ -114,6 +127,7 @@
runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/libred.so")
runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so")
runtime.Output(installPathPrefix + "/ravenwood-runtime/ravenwood-data/app1.apk")
+ runtime.Output(installPathPrefix + "/ravenwood-runtime/fonts/Font.ttf")
utils := ctx.ModuleForTests("ravenwood-utils", "android_common")
utils.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar")
}
@@ -125,29 +139,30 @@
ctx := android.GroupFixturePreparers(
PrepareForIntegrationTestWithJava,
+ etc.PrepareForTestWithPrebuiltEtc,
prepareRavenwoodRuntime,
).RunTestWithBp(t, `
- cc_library_shared {
- name: "jni-lib1",
- host_supported: true,
- srcs: ["jni.cpp"],
- }
- cc_library_shared {
- name: "jni-lib2",
- host_supported: true,
- srcs: ["jni.cpp"],
- stem: "libblue",
- shared_libs: [
- "jni-lib3",
- ],
- }
- cc_library_shared {
- name: "jni-lib3",
- host_supported: true,
- srcs: ["jni.cpp"],
- stem: "libpink",
- }
- android_ravenwood_test {
+ cc_library_shared {
+ name: "jni-lib1",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ }
+ cc_library_shared {
+ name: "jni-lib2",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libblue",
+ shared_libs: [
+ "jni-lib3",
+ ],
+ }
+ cc_library_shared {
+ name: "jni-lib3",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libpink",
+ }
+ android_ravenwood_test {
name: "ravenwood-test",
srcs: ["Test.java"],
jni_libs: [
@@ -156,6 +171,7 @@
"ravenwood-runtime-jni2",
],
resource_apk: "app2",
+ inst_resource_apk: "app3",
sdk_version: "test_current",
}
`)
@@ -183,6 +199,7 @@
module.Output(installPathPrefix + "/ravenwood-test/lib64/libblue.so")
module.Output(installPathPrefix + "/ravenwood-test/lib64/libpink.so")
module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-res.apk")
+ module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-inst-res.apk")
// ravenwood-runtime*.so are included in the runtime, so it shouldn't be emitted.
for _, o := range module.AllOutputs() {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 9cd07d0..eb9fa5f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -29,11 +29,6 @@
"android/soong/android"
"android/soong/dexpreopt"
- "android/soong/etc"
-)
-
-const (
- sdkXmlFileSuffix = ".xml"
)
// A tag to associated a dependency with a specific api scope.
@@ -268,10 +263,6 @@
return baseName + ".stubs.source" + scope.moduleSuffix
}
-func (scope *apiScope) apiModuleName(baseName string) string {
- return baseName + ".api" + scope.moduleSuffix
-}
-
func (scope *apiScope) String() string {
return scope.name
}
@@ -961,56 +952,6 @@
return c.implLibraryModule
}
-// Module name of the runtime implementation library
-func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
- return c.module.RootLibraryName() + ".impl"
-}
-
-// Module name of the XML file for the lib
-func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
- return c.module.RootLibraryName() + sdkXmlFileSuffix
-}
-
-// Name of the java_library module that compiles the stubs source.
-func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return apiScope.stubsLibraryModuleName(baseName)
-}
-
-// Name of the java_library module that compiles the exportable stubs source.
-func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return apiScope.exportableStubsLibraryModuleName(baseName)
-}
-
-// Name of the droidstubs module that generates the stubs source and may also
-// generate/check the API.
-func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return apiScope.stubsSourceModuleName(baseName)
-}
-
-// Name of the java_api_library module that generates the from-text stubs source
-// and compiles to a jar file.
-func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return apiScope.apiLibraryModuleName(baseName)
-}
-
-// Name of the java_library module that compiles the stubs
-// generated from source Java files.
-func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return apiScope.sourceStubsLibraryModuleName(baseName)
-}
-
-// Name of the java_library module that compiles the exportable stubs
-// generated from source Java files.
-func (c *commonToSdkLibraryAndImport) exportableSourceStubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return apiScope.exportableSourceStubsLibraryModuleName(baseName)
-}
-
// The component names for different outputs of the java_sdk_library.
//
// They are similar to the names used for the child modules it creates
@@ -1082,21 +1023,6 @@
return nil
}
-func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
-
- // If a specific numeric version has been requested then use prebuilt versions of the sdk.
- if !sdkVersion.ApiLevel.IsPreview() {
- return PrebuiltJars(ctx, c.module.RootLibraryName(), sdkVersion)
- }
-
- paths := c.selectScopePaths(ctx, sdkVersion.Kind)
- if paths == nil {
- return nil
- }
-
- return paths.stubsHeaderPath
-}
-
// selectScopePaths returns the *scopePaths appropriate for the specific kind.
//
// If the module does not support the specific kind then it will return the *scopePaths for the
@@ -1263,12 +1189,6 @@
type SdkLibraryDependency interface {
SdkLibraryComponentDependency
- // Get the header jars appropriate for the supplied sdk_version.
- //
- // These are turbine generated jars so they only change if the externals of the
- // class changes but it does not contain and implementation or JavaDoc.
- SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
-
// SdkApiStubDexJar returns the dex jar for the stubs for the prebuilt
// java_sdk_library_import module. It is needed by the hiddenapi processing tool which
// processes dex files.
@@ -1285,9 +1205,36 @@
// sharedLibrary returns true if this can be used as a shared library.
sharedLibrary() bool
+ // getImplLibraryModule returns the pointer to the implementation library submodule of this
+ // sdk library.
getImplLibraryModule() *Library
}
+type SdkLibraryInfo struct {
+ // GeneratingLibs is the names of the library modules that this sdk library
+ // generates. Note that this only includes the name of the modules that other modules can
+ // depend on, and is not a holistic list of generated modules.
+ GeneratingLibs []string
+}
+
+var SdkLibraryInfoProvider = blueprint.NewProvider[SdkLibraryInfo]()
+
+func getGeneratingLibs(ctx android.ModuleContext, sdkVersion android.SdkSpec, sdkLibraryModuleName string, sdkInfo SdkLibraryInfo) []string {
+ apiLevel := sdkVersion.ApiLevel
+ if apiLevel.IsPreview() {
+ return sdkInfo.GeneratingLibs
+ }
+
+ generatingPrebuilts := []string{}
+ for _, apiScope := range AllApiScopes {
+ scopePrebuiltModuleName := prebuiltApiModuleName("sdk", sdkLibraryModuleName, apiScope.name, apiLevel.String())
+ if ctx.OtherModuleExists(scopePrebuiltModuleName) {
+ generatingPrebuilts = append(generatingPrebuilts, scopePrebuiltModuleName)
+ }
+ }
+ return generatingPrebuilts
+}
+
type SdkLibrary struct {
Library
@@ -1431,7 +1378,7 @@
ctx.AddVariationDependencies(nil, apiScope.exportableStubsTag, exportableStubModuleName)
// Add a dependency on the stubs source in order to access both stubs source and api information.
- ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
+ ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.droidstubsModuleName(apiScope))
if module.compareAgainstLatestApi(apiScope) {
// Add dependencies on the latest finalized version of the API .txt file.
@@ -1613,9 +1560,22 @@
}
android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
module.setOutputFiles(ctx)
+
+ var generatingLibs []string
+ for _, apiScope := range AllApiScopes {
+ if _, ok := module.scopePaths[apiScope]; ok {
+ generatingLibs = append(generatingLibs, module.stubsLibraryModuleName(apiScope))
+ }
+ }
+
if module.requiresRuntimeImplementationLibrary() && module.implLibraryModule != nil {
+ generatingLibs = append(generatingLibs, module.implLibraryModuleName())
setOutputFiles(ctx, module.implLibraryModule.Module)
}
+
+ android.SetProvider(ctx, SdkLibraryInfoProvider, SdkLibraryInfo{
+ GeneratingLibs: generatingLibs,
+ })
}
func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall {
@@ -1722,411 +1682,6 @@
return visibility
}
-// Creates the implementation java library
-func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
- visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)
-
- staticLibs := module.properties.Static_libs.Clone()
- staticLibs.AppendSimpleValue(module.sdkLibraryProperties.Impl_only_static_libs)
- props := struct {
- Name *string
- Visibility []string
- Libs []string
- Static_libs proptools.Configurable[[]string]
- Apex_available []string
- Stem *string
- }{
- Name: proptools.StringPtr(module.implLibraryModuleName()),
- Visibility: visibility,
-
- Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...),
-
- Static_libs: staticLibs,
- // Pass the apex_available settings down so that the impl library can be statically
- // embedded within a library that is added to an APEX. Needed for updatable-media.
- Apex_available: module.ApexAvailable(),
-
- Stem: proptools.StringPtr(module.Name()),
- }
-
- properties := []interface{}{
- &module.properties,
- &module.protoProperties,
- &module.deviceProperties,
- &module.dexProperties,
- &module.dexpreoptProperties,
- &module.linter.properties,
- &module.overridableProperties,
- &props,
- module.sdkComponentPropertiesForChildLibrary(),
- }
- mctx.CreateModule(LibraryFactory, properties...)
-}
-
-type libraryProperties struct {
- Name *string
- Visibility []string
- Srcs []string
- Installable *bool
- Sdk_version *string
- System_modules *string
- Patch_module *string
- Libs []string
- Static_libs []string
- Compile_dex *bool
- Java_version *string
- Openjdk9 struct {
- Srcs []string
- Javacflags []string
- }
- Dist struct {
- Targets []string
- Dest *string
- Dir *string
- Tag *string
- }
- Is_stubs_module *bool
- Stub_contributing_api *string
-}
-
-func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
- props := libraryProperties{}
- props.Visibility = []string{"//visibility:override", "//visibility:private"}
- // sources are generated from the droiddoc
- sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
- props.Sdk_version = proptools.StringPtr(sdkVersion)
- props.System_modules = module.deviceProperties.System_modules
- props.Patch_module = module.properties.Patch_module
- props.Installable = proptools.BoolPtr(false)
- props.Libs = module.sdkLibraryProperties.Stub_only_libs
- props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
- props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
- // The stub-annotations library contains special versions of the annotations
- // with CLASS retention policy, so that they're kept.
- if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
- props.Libs = append(props.Libs, "stub-annotations")
- }
- props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
- props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
- // 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")
- props.Is_stubs_module = proptools.BoolPtr(true)
- props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String())
-
- return props
-}
-
-// Creates a static java library that has API stubs
-func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
-
- props := module.stubsLibraryProps(mctx, apiScope)
- props.Name = proptools.StringPtr(module.sourceStubsLibraryModuleName(apiScope))
- props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
-
- mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-// Create a static java library that compiles the "exportable" stubs
-func (module *SdkLibrary) createExportableStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
- props := module.stubsLibraryProps(mctx, apiScope)
- props.Name = proptools.StringPtr(module.exportableSourceStubsLibraryModuleName(apiScope))
- props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope) + "{.exportable}"}
-
- mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-// Creates a droidstubs module that creates stubs source files from the given full source
-// files and also updates and checks the API specification files.
-func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
- props := struct {
- Name *string
- Visibility []string
- Srcs []string
- Installable *bool
- Sdk_version *string
- Api_surface *string
- System_modules *string
- Libs proptools.Configurable[[]string]
- Output_javadoc_comments *bool
- Arg_files []string
- Args *string
- Java_version *string
- Annotations_enabled *bool
- Merge_annotations_dirs []string
- Merge_inclusion_annotations_dirs []string
- Generate_stubs *bool
- Previous_api *string
- Aconfig_declarations []string
- Check_api struct {
- Current ApiToCheck
- Last_released ApiToCheck
-
- Api_lint struct {
- Enabled *bool
- New_since *string
- Baseline_file *string
- }
- }
- Aidl struct {
- Include_dirs []string
- Local_include_dirs []string
- }
- Dists []android.Dist
- }{}
-
- // The stubs source processing uses the same compile time classpath when extracting the
- // API from the implementation library as it does when compiling it. i.e. the same
- // * sdk version
- // * system_modules
- // * libs (static_libs/libs)
-
- props.Name = proptools.StringPtr(name)
- props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility)
- props.Srcs = append(props.Srcs, module.properties.Srcs...)
- props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...)
- props.Sdk_version = module.deviceProperties.Sdk_version
- props.Api_surface = &apiScope.name
- props.System_modules = module.deviceProperties.System_modules
- props.Installable = proptools.BoolPtr(false)
- // A droiddoc module has only one Libs property and doesn't distinguish between
- // shared libs and static libs. So we need to add both of these libs to Libs property.
- props.Libs = proptools.NewConfigurable[[]string](nil, nil)
- props.Libs.AppendSimpleValue(module.properties.Libs)
- props.Libs.Append(module.properties.Static_libs)
- props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs)
- props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs)
- props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
- props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
- props.Java_version = module.properties.Java_version
-
- props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
- props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
- props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
- props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations
-
- droidstubsArgs := []string{}
- if len(module.sdkLibraryProperties.Api_packages) != 0 {
- droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
- }
- droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
- disabledWarnings := []string{"HiddenSuperclass"}
- if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) {
- disabledWarnings = append(disabledWarnings,
- "BroadcastBehavior",
- "DeprecationMismatch",
- "MissingPermission",
- "SdkConstant",
- "Todo",
- )
- }
- droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
-
- // Output Javadoc comments for public scope.
- if apiScope == apiScopePublic {
- props.Output_javadoc_comments = proptools.BoolPtr(true)
- }
-
- // Add in scope specific arguments.
- droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
- props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
- props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
-
- // List of APIs identified from the provided source files are created. They are later
- // compared against to the not-yet-released (a.k.a current) list of APIs and to the
- // last-released (a.k.a numbered) list of API.
- currentApiFileName := apiScope.apiFilePrefix + "current.txt"
- removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
- apiDir := module.getApiDir()
- currentApiFileName = path.Join(apiDir, currentApiFileName)
- removedApiFileName = path.Join(apiDir, removedApiFileName)
-
- // check against the not-yet-release API
- props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
- props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
-
- if module.compareAgainstLatestApi(apiScope) {
- // check against the latest released API
- latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
- props.Previous_api = latestApiFilegroupName
- props.Check_api.Last_released.Api_file = latestApiFilegroupName
- props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
- module.latestRemovedApiFilegroupName(apiScope))
- props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
- module.latestIncompatibilitiesFilegroupName(apiScope))
-
- if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
- // Enable api lint.
- props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
- props.Check_api.Api_lint.New_since = latestApiFilegroupName
-
- // If it exists then pass a lint-baseline.txt through to droidstubs.
- baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
- baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
- paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
- if err != nil {
- mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
- }
- if len(paths) == 1 {
- props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
- } else if len(paths) != 0 {
- mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
- }
- }
- }
-
- if !Bool(module.sdkLibraryProperties.No_dist) {
- // Dist the api txt and removed api txt artifacts for sdk builds.
- distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
- stubsTypeTagPrefix := ""
- if mctx.Config().ReleaseHiddenApiExportableStubs() {
- stubsTypeTagPrefix = ".exportable"
- }
- for _, p := range []struct {
- tag string
- pattern string
- }{
- // "exportable" api files are copied to the dist directory instead of the
- // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
- // is set. Otherwise, the "everything" api files are copied to the dist directory.
- {tag: "%s.api.txt", pattern: "%s.txt"},
- {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
- } {
- props.Dists = append(props.Dists, android.Dist{
- Targets: []string{"sdk", "win_sdk"},
- Dir: distDir,
- Dest: proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
- Tag: proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
- })
- }
- }
-
- mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx)
-}
-
-func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
- props := struct {
- Name *string
- Visibility []string
- Api_contributions []string
- Libs proptools.Configurable[[]string]
- Static_libs []string
- System_modules *string
- Enable_validation *bool
- Stubs_type *string
- Sdk_version *string
- Previous_api *string
- }{}
-
- props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
- props.Visibility = []string{"//visibility:override", "//visibility:private"}
-
- apiContributions := []string{}
-
- // Api surfaces are not independent of each other, but have subset relationships,
- // and so does the api files. To generate from-text stubs for api surfaces other than public,
- // all subset api domains' api_contriubtions must be added as well.
- scope := apiScope
- for scope != nil {
- apiContributions = append(apiContributions, module.stubsSourceModuleName(scope)+".api.contribution")
- scope = scope.extends
- }
- if apiScope == apiScopePublic {
- additionalApiContribution := module.apiLibraryAdditionalApiContribution()
- if additionalApiContribution != "" {
- apiContributions = append(apiContributions, additionalApiContribution)
- }
- }
-
- props.Api_contributions = apiContributions
-
- // Ensure that stub-annotations is added to the classpath before any other libs
- props.Libs = proptools.NewConfigurable[[]string](nil, nil)
- props.Libs.AppendSimpleValue([]string{"stub-annotations"})
- props.Libs.AppendSimpleValue(module.properties.Libs)
- props.Libs.Append(module.properties.Static_libs)
- props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs)
- props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs)
- props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
-
- props.System_modules = module.deviceProperties.System_modules
- props.Enable_validation = proptools.BoolPtr(true)
- props.Stubs_type = proptools.StringPtr("everything")
-
- if module.deviceProperties.Sdk_version != nil {
- props.Sdk_version = module.deviceProperties.Sdk_version
- }
-
- if module.compareAgainstLatestApi(apiScope) {
- // check against the latest released API
- latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
- props.Previous_api = latestApiFilegroupName
- }
-
- mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
- props := libraryProperties{}
-
- props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
- sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
- props.Sdk_version = proptools.StringPtr(sdkVersion)
-
- props.System_modules = module.deviceProperties.System_modules
-
- // The imports need to be compiled to dex if the java_sdk_library requests it.
- compileDex := module.dexProperties.Compile_dex
- if module.stubLibrariesCompiledForDex() {
- compileDex = proptools.BoolPtr(true)
- }
- props.Compile_dex = compileDex
-
- props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String())
-
- if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
- props.Dist.Targets = []string{"sdk", "win_sdk"}
- props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
- props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
- props.Dist.Tag = proptools.StringPtr(".jar")
- }
- props.Is_stubs_module = proptools.BoolPtr(true)
-
- return props
-}
-
-func (module *SdkLibrary) createTopLevelStubsLibrary(
- mctx android.DefaultableHookContext, apiScope *apiScope) {
-
- // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
- doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
- props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
- props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
-
- // Add the stub compiling java_library/java_api_library as static lib based on build config
- staticLib := module.sourceStubsLibraryModuleName(apiScope)
- if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() {
- staticLib = module.apiLibraryModuleName(apiScope)
- }
- props.Static_libs = append(props.Static_libs, staticLib)
-
- mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
- mctx android.DefaultableHookContext, apiScope *apiScope) {
-
- // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
- doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
- props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
- props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
-
- staticLib := module.exportableSourceStubsLibraryModuleName(apiScope)
- props.Static_libs = append(props.Static_libs, staticLib)
-
- mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool {
return !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api)
}
@@ -2152,104 +1707,6 @@
return proptools.BoolDefault(module.sdkLibraryProperties.Build_from_text_stub, true)
}
-// Creates the xml file that publicizes the runtime library
-func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
- moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
- var moduleMinApiLevelStr = moduleMinApiLevel.String()
- if moduleMinApiLevel == android.NoneApiLevel {
- moduleMinApiLevelStr = "current"
- }
- props := struct {
- Name *string
- Lib_name *string
- Apex_available []string
- On_bootclasspath_since *string
- On_bootclasspath_before *string
- Min_device_sdk *string
- Max_device_sdk *string
- Sdk_library_min_api_level *string
- Uses_libs_dependencies []string
- }{
- Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
- Lib_name: proptools.StringPtr(module.BaseModuleName()),
- Apex_available: module.ApexProperties.Apex_available,
- On_bootclasspath_since: module.commonSdkLibraryProperties.On_bootclasspath_since,
- On_bootclasspath_before: module.commonSdkLibraryProperties.On_bootclasspath_before,
- Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
- Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
- Sdk_library_min_api_level: &moduleMinApiLevelStr,
- Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
- }
-
- mctx.CreateModule(sdkLibraryXmlFactory, &props)
-}
-
-func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkSpec) android.Paths {
- var ver android.ApiLevel
- var kind android.SdkKind
- if s.UsePrebuilt(ctx) {
- ver = s.ApiLevel
- kind = s.Kind
- } else {
- // We don't have prebuilt SDK for the specific sdkVersion.
- // Instead of breaking the build, fallback to use "system_current"
- ver = android.FutureApiLevel
- kind = android.SdkSystem
- }
-
- dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String())
- jar := filepath.Join(dir, baseName+".jar")
- jarPath := android.ExistentPathForSource(ctx, jar)
- if !jarPath.Valid() {
- if ctx.Config().AllowMissingDependencies() {
- return android.Paths{android.PathForSource(ctx, jar)}
- } else {
- ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.Raw, jar)
- }
- return nil
- }
- return android.Paths{jarPath.Path()}
-}
-
-// Check to see if the other module is within the same set of named APEXes as this module.
-//
-// If either this or the other module are on the platform then this will return
-// false.
-func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool {
- apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
- otherApexInfo, _ := android.OtherModuleProvider(ctx, other, android.ApexInfoProvider)
- return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants)
-}
-
-func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- // If the client doesn't set sdk_version, but if this library prefers stubs over
- // the impl library, let's provide the widest API surface possible. To do so,
- // force override sdk_version to module_current so that the closest possible API
- // surface could be found in selectHeaderJarsForSdkVersion
- if module.defaultsToStubs() && !sdkVersion.Specified() {
- sdkVersion = android.SdkSpecFrom(ctx, "module_current")
- }
-
- // Only provide access to the implementation library if it is actually built.
- if module.requiresRuntimeImplementationLibrary() {
- // Check any special cases for java_sdk_library.
- //
- // Only allow access to the implementation library in the following condition:
- // * No sdk_version specified on the referencing module.
- // * The referencing module is in the same apex as this.
- if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) {
- return module.implLibraryHeaderJars
- }
- }
-
- return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
-}
-
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- return module.sdkJars(ctx, sdkVersion)
-}
-
var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries")
func javaSdkLibraries(config android.Config) *[]string {
@@ -2266,11 +1723,6 @@
// runtime libs and xml file. If requested, the stubs and docs are created twice
// once for public API level and once for system API level
func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) {
- // If the module has been disabled then don't create any child modules.
- if !module.Enabled(mctx) {
- return
- }
-
if len(module.properties.Srcs) == 0 {
mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
return
@@ -2320,10 +1772,10 @@
for _, scope := range generatedScopes {
// Use the stubs source name for legacy reasons.
- module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)
+ module.createDroidstubs(mctx, scope, module.droidstubsModuleName(scope), scope.droidstubsArgs)
- module.createStubsLibrary(mctx, scope)
- module.createExportableStubsLibrary(mctx, scope)
+ module.createFromSourceStubsLibrary(mctx, scope)
+ module.createExportableFromSourceStubsLibrary(mctx, scope)
if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() {
module.createApiLibrary(mctx, scope)
@@ -2373,10 +1825,6 @@
return !proptools.Bool(module.sdkLibraryProperties.Api_only)
}
-func (module *SdkLibrary) defaultsToStubs() bool {
- return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs)
-}
-
func moduleStubLinkType(j *Module) (stub bool, ret sdkLinkType) {
kind := android.ToSdkKind(proptools.String(j.properties.Stub_contributing_api))
switch kind {
@@ -2628,86 +2076,6 @@
*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
}
-func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
- // Creates a java import for the jar with ".stubs" suffix
- props := struct {
- Name *string
- Source_module_name *string
- Created_by_java_sdk_library_name *string
- Sdk_version *string
- Libs []string
- Jars []string
- Compile_dex *bool
- Is_stubs_module *bool
-
- android.UserSuppliedPrebuiltProperties
- }{}
- props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
- props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName()))
- props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
- props.Sdk_version = scopeProperties.Sdk_version
- // Prepend any of the libs from the legacy public properties to the libs for each of the
- // scopes to avoid having to duplicate them in each scope.
- props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
- props.Jars = scopeProperties.Jars
-
- // The imports are preferred if the java_sdk_library_import is preferred.
- props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
-
- // The imports need to be compiled to dex if the java_sdk_library_import requests it.
- compileDex := module.properties.Compile_dex
- if module.stubLibrariesCompiledForDex() {
- compileDex = proptools.BoolPtr(true)
- }
- props.Compile_dex = compileDex
- props.Is_stubs_module = proptools.BoolPtr(true)
-
- mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
- props := struct {
- Name *string
- Source_module_name *string
- Created_by_java_sdk_library_name *string
- Srcs []string
-
- android.UserSuppliedPrebuiltProperties
- }{}
- props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
- props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
- props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
- props.Srcs = scopeProperties.Stub_srcs
-
- // The stubs source is preferred if the java_sdk_library_import is preferred.
- props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
-
- mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
- api_file := scopeProperties.Current_api
- api_surface := &apiScope.name
-
- props := struct {
- Name *string
- Source_module_name *string
- Created_by_java_sdk_library_name *string
- Api_surface *string
- Api_file *string
- Visibility []string
- }{}
-
- props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution")
- props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution")
- props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
- props.Api_surface = api_surface
- props.Api_file = api_file
- props.Visibility = []string{"//visibility:override", "//visibility:public"}
-
- mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
// Add the dependencies on the child module in the component deps mutator so that it
// creates references to the prebuilt and not the source modules.
func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -2721,7 +2089,7 @@
if len(scopeProperties.Stub_srcs) > 0 {
// Add dependencies to the prebuilt stubs source library
- ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.stubsSourceModuleName(apiScope)))
+ ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.droidstubsModuleName(apiScope)))
}
}
}
@@ -2820,69 +2188,36 @@
}
if ctx.Device() {
- // If this is a variant created for a prebuilt_apex then use the dex implementation jar
- // obtained from the associated deapexer module.
+ // Shared libraries deapexed from prebuilt apexes are no longer supported.
+ // Set the dexJarBuildPath to a fake path.
+ // This allows soong analysis pass, but will be an error during ninja execution if there are
+ // any rdeps.
ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex {
- // Get the path of the dex implementation jar from the `deapexer` module.
- di, err := android.FindDeapexerProviderForModule(ctx)
- if err != nil {
- // An error was found, possibly due to multiple apexes in the tree that export this library
- // Defer the error till a client tries to call DexJarBuildPath
- module.dexJarFileErr = err
- module.initHiddenAPIError(err)
- return
- }
- dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(module.BaseModuleName())
- if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
- dexJarFile := makeDexJarPathFromPath(dexOutputPath)
- module.dexJarFile = dexJarFile
- installPath := android.PathForModuleInPartitionInstall(
- ctx, "apex", ai.ApexVariationName, dexJarFileApexRootRelative)
- module.installFile = installPath
- module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
+ module.dexJarFile = makeDexJarPathFromPath(android.PathForModuleInstall(ctx, "intentionally_no_longer_supported"))
+ module.initHiddenAPI(ctx, module.dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
+ }
+ }
- module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
- module.dexpreopter.isSDKLibrary = true
- module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &module.dexpreopter)
-
- if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
- module.dexpreopter.inputProfilePathOnHost = profilePath
- }
- } else {
- // This should never happen as a variant for a prebuilt_apex is only created if the
- // prebuilt_apex has been configured to export the java library dex file.
- ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
+ var generatingLibs []string
+ for _, apiScope := range AllApiScopes {
+ if scopeProperties, ok := module.scopeProperties[apiScope]; ok {
+ if len(scopeProperties.Jars) == 0 {
+ continue
}
+ generatingLibs = append(generatingLibs, module.stubsLibraryModuleName(apiScope))
}
}
module.setOutputFiles(ctx)
if module.implLibraryModule != nil {
+ generatingLibs = append(generatingLibs, module.implLibraryModuleName())
setOutputFiles(ctx, module.implLibraryModule.Module)
}
-}
-func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
-
- // For consistency with SdkLibrary make the implementation jar available to libraries that
- // are within the same APEX.
- implLibraryModule := module.implLibraryModule
- if implLibraryModule != nil && withinSameApexesAs(ctx, module) {
- if headerJars {
- return implLibraryModule.HeaderJars()
- } else {
- return implLibraryModule.ImplementationJars()
- }
- }
-
- return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
-}
-
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- // This module is just a wrapper for the prebuilt stubs.
- return module.sdkJars(ctx, sdkVersion, true)
+ android.SetProvider(ctx, SdkLibraryInfoProvider, SdkLibraryInfo{
+ GeneratingLibs: generatingLibs,
+ })
}
// to satisfy UsesLibraryDependency interface
@@ -2977,333 +2312,6 @@
return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
}
-// java_sdk_library_xml
-type sdkLibraryXml struct {
- android.ModuleBase
- android.DefaultableModuleBase
- android.ApexModuleBase
-
- properties sdkLibraryXmlProperties
-
- outputFilePath android.OutputPath
- installDirPath android.InstallPath
-
- hideApexVariantFromMake bool
-}
-
-type sdkLibraryXmlProperties struct {
- // canonical name of the lib
- Lib_name *string
-
- // Signals that this shared library is part of the bootclasspath starting
- // on the version indicated in this attribute.
- //
- // This will make platforms at this level and above to ignore
- // <uses-library> tags with this library name because the library is already
- // available
- On_bootclasspath_since *string
-
- // Signals that this shared library was part of the bootclasspath before
- // (but not including) the version indicated in this attribute.
- //
- // The system will automatically add a <uses-library> tag with this library to
- // apps that target any SDK less than the version indicated in this attribute.
- On_bootclasspath_before *string
-
- // Indicates that PackageManager should ignore this shared library if the
- // platform is below the version indicated in this attribute.
- //
- // This means that the device won't recognise this library as installed.
- Min_device_sdk *string
-
- // Indicates that PackageManager should ignore this shared library if the
- // platform is above the version indicated in this attribute.
- //
- // This means that the device won't recognise this library as installed.
- Max_device_sdk *string
-
- // The SdkLibrary's min api level as a string
- //
- // This value comes from the ApiLevel of the MinSdkVersion property.
- Sdk_library_min_api_level *string
-
- // Uses-libs dependencies that the shared library requires to work correctly.
- //
- // This will add dependency="foo:bar" to the <library> section.
- Uses_libs_dependencies []string
-}
-
-// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
-// Not to be used directly by users. java_sdk_library internally uses this.
-func sdkLibraryXmlFactory() android.Module {
- module := &sdkLibraryXml{}
-
- module.AddProperties(&module.properties)
-
- android.InitApexModule(module)
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
-
- return module
-}
-
-func (module *sdkLibraryXml) UniqueApexVariations() bool {
- // sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
- // mounted APEX, which contains the name of the APEX.
- return true
-}
-
-// from android.PrebuiltEtcModule
-func (module *sdkLibraryXml) BaseDir() string {
- return "etc"
-}
-
-// from android.PrebuiltEtcModule
-func (module *sdkLibraryXml) SubDir() string {
- return "permissions"
-}
-
-var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)
-
-// from android.ApexModule
-func (module *sdkLibraryXml) AvailableFor(what string) bool {
- return true
-}
-
-func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
- // do nothing
-}
-
-var _ android.ApexModule = (*sdkLibraryXml)(nil)
-
-// Implements android.ApexModule
-func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked
- return nil
-}
-
-// File path to the runtime implementation library
-func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
- implName := proptools.String(module.properties.Lib_name)
- if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
- // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
- // In most cases, this works fine. But when apex_name is set or override_apex is used
- // this can be wrong.
- return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.BaseApexName, implName)
- }
- partition := "system"
- if module.SocSpecific() {
- partition = "vendor"
- } else if module.DeviceSpecific() {
- partition = "odm"
- } else if module.ProductSpecific() {
- partition = "product"
- } else if module.SystemExtSpecific() {
- partition = "system_ext"
- }
- return "/" + partition + "/framework/" + implName + ".jar"
-}
-
-func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string {
- if value == nil {
- return ""
- }
- apiLevel, err := android.ApiLevelFromUser(ctx, *value)
- if err != nil {
- // attributes in bp files have underscores but in the xml have dashes.
- ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
- return ""
- }
- if apiLevel.IsCurrent() {
- // passing "current" would always mean a future release, never the current (or the current in
- // progress) which means some conditions would never be triggered.
- ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"),
- `"current" is not an allowed value for this attribute`)
- return ""
- }
- // "safeValue" is safe because it translates finalized codenames to a string
- // with their SDK int.
- safeValue := apiLevel.String()
- return formattedOptionalAttribute(attrName, &safeValue)
-}
-
-// formats an attribute for the xml permissions file if the value is not null
-// returns empty string otherwise
-func formattedOptionalAttribute(attrName string, value *string) string {
- if value == nil {
- return ""
- }
- return fmt.Sprintf(" %s=\"%s\"\n", attrName, *value)
-}
-
-func formattedDependenciesAttribute(dependencies []string) string {
- if dependencies == nil {
- return ""
- }
- return fmt.Sprintf(" dependency=\"%s\"\n", strings.Join(dependencies, ":"))
-}
-
-func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
- libName := proptools.String(module.properties.Lib_name)
- libNameAttr := formattedOptionalAttribute("name", &libName)
- filePath := module.implPath(ctx)
- filePathAttr := formattedOptionalAttribute("file", &filePath)
- implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since)
- implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
- minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
- maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
- dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
- // <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
- // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
- var libraryTag string
- if module.properties.Min_device_sdk != nil {
- libraryTag = " <apex-library\n"
- } else {
- libraryTag = " <library\n"
- }
-
- return strings.Join([]string{
- "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
- "<!-- Copyright (C) 2018 The Android Open Source Project\n",
- "\n",
- " Licensed under the Apache License, Version 2.0 (the \"License\");\n",
- " you may not use this file except in compliance with the License.\n",
- " You may obtain a copy of the License at\n",
- "\n",
- " http://www.apache.org/licenses/LICENSE-2.0\n",
- "\n",
- " Unless required by applicable law or agreed to in writing, software\n",
- " distributed under the License is distributed on an \"AS IS\" BASIS,\n",
- " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
- " See the License for the specific language governing permissions and\n",
- " limitations under the License.\n",
- "-->\n",
- "<permissions>\n",
- libraryTag,
- libNameAttr,
- filePathAttr,
- implicitFromAttr,
- implicitUntilAttr,
- minSdkAttr,
- maxSdkAttr,
- dependenciesAttr,
- " />\n",
- "</permissions>\n",
- }, "")
-}
-
-func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
- module.hideApexVariantFromMake = !apexInfo.IsForPlatform()
-
- libName := proptools.String(module.properties.Lib_name)
- module.selfValidate(ctx)
- xmlContent := module.permissionsContents(ctx)
-
- module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
- android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)
-
- module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
- ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
-
- ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "")
-}
-
-func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
- if module.hideApexVariantFromMake {
- return []android.AndroidMkEntries{{
- Disabled: true,
- }}
- }
-
- return []android.AndroidMkEntries{{
- Class: "ETC",
- OutputFile: android.OptionalPathForPath(module.outputFilePath),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_TAGS", "optional")
- entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())
- },
- },
- }}
-}
-
-func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) {
- module.validateAtLeastTAttributes(ctx)
- module.validateMinAndMaxDeviceSdk(ctx)
- module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx)
- module.validateOnBootclasspathBeforeRequirements(ctx)
-}
-
-func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) {
- t := android.ApiLevelOrPanic(ctx, "Tiramisu")
- module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk")
- module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk")
- module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before")
- module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since")
-}
-
-func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) {
- if attr != nil {
- if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil {
- // we will inform the user of invalid inputs when we try to write the
- // permissions xml file so we don't need to do it here
- if t.GreaterThan(level) {
- ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T")
- }
- }
- }
-}
-
-func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) {
- if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil {
- min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
- max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
- if minErr == nil && maxErr == nil {
- // we will inform the user of invalid inputs when we try to write the
- // permissions xml file so we don't need to do it here
- if min.GreaterThan(max) {
- ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk")
- }
- }
- }
-}
-
-func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) {
- moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
- if module.properties.Min_device_sdk != nil {
- api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
- if err == nil {
- if moduleMinApi.GreaterThan(api) {
- ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
- }
- }
- }
- if module.properties.Max_device_sdk != nil {
- api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
- if err == nil {
- if moduleMinApi.GreaterThan(api) {
- ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
- }
- }
- }
-}
-
-func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) {
- moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
- if module.properties.On_bootclasspath_before != nil {
- t := android.ApiLevelOrPanic(ctx, "Tiramisu")
- // if we use the attribute, then we need to do this validation
- if moduleMinApi.LessThan(t) {
- // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+)
- if module.properties.Min_device_sdk == nil {
- ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T")
- }
- }
- }
-}
-
type sdkLibrarySdkMemberType struct {
android.SdkMemberTypeBase
}
diff --git a/java/sdk_library_external.go b/java/sdk_library_external.go
deleted file mode 100644
index 4f83981..0000000
--- a/java/sdk_library_external.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2020 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package java
-
-import (
- "android/soong/android"
-)
-
-type partitionGroup int
-
-// Representation of partition group for checking inter-partition library dependencies.
-// Between system and system_ext, there are no restrictions of dependencies,
-// so we can treat these partitions as the same in terms of inter-partition dependency.
-// Same policy is applied between vendor and odm partiton.
-const (
- partitionGroupNone partitionGroup = iota
- // group for system, and system_ext partition
- partitionGroupSystem
- // group for vendor and odm partition
- partitionGroupVendor
- // product partition
- partitionGroupProduct
-)
-
-func (g partitionGroup) String() string {
- switch g {
- case partitionGroupSystem:
- return "system"
- case partitionGroupVendor:
- return "vendor"
- case partitionGroupProduct:
- return "product"
- }
-
- return ""
-}
-
-// Get partition group of java module that can be used at inter-partition dependency check.
-// We currently have three groups
-//
-// (system, system_ext) => system partition group
-// (vendor, odm) => vendor partition group
-// (product) => product partition group
-func (j *Module) partitionGroup(ctx android.EarlyModuleContext) partitionGroup {
- // system and system_ext partition can be treated as the same in terms of inter-partition dependency.
- if j.Platform() || j.SystemExtSpecific() {
- return partitionGroupSystem
- }
-
- // vendor and odm partition can be treated as the same in terms of inter-partition dependency.
- if j.SocSpecific() || j.DeviceSpecific() {
- return partitionGroupVendor
- }
-
- // product partition is independent.
- if j.ProductSpecific() {
- return partitionGroupProduct
- }
-
- panic("Cannot determine partition type")
-}
-
-func (j *Module) allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleContext) bool {
- return inList(j.Name(), ctx.Config().InterPartitionJavaLibraryAllowList())
-}
-
-func (j *Module) syspropWithPublicStubs() bool {
- return j.deviceProperties.SyspropPublicStub != ""
-}
-
-type javaSdkLibraryEnforceContext interface {
- Name() string
- allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleContext) bool
- partitionGroup(ctx android.EarlyModuleContext) partitionGroup
- syspropWithPublicStubs() bool
-}
-
-var _ javaSdkLibraryEnforceContext = (*Module)(nil)
-
-func (j *Module) checkPartitionsForJavaDependency(ctx android.EarlyModuleContext, propName string, dep javaSdkLibraryEnforceContext) {
- if dep.allowListedInterPartitionJavaLibrary(ctx) {
- return
- }
-
- if dep.syspropWithPublicStubs() {
- return
- }
-
- // If product interface is not enforced, skip check between system and product partition.
- // But still need to check between product and vendor partition because product interface flag
- // just represents enforcement between product and system, and vendor interface enforcement
- // that is enforced here by precondition is representing enforcement between vendor and other partitions.
- if !ctx.Config().EnforceProductPartitionInterface() {
- productToSystem := j.partitionGroup(ctx) == partitionGroupProduct && dep.partitionGroup(ctx) == partitionGroupSystem
- systemToProduct := j.partitionGroup(ctx) == partitionGroupSystem && dep.partitionGroup(ctx) == partitionGroupProduct
-
- if productToSystem || systemToProduct {
- return
- }
- }
-
- // If module and dependency library is inter-partition
- if j.partitionGroup(ctx) != dep.partitionGroup(ctx) {
- errorFormat := "dependency on java_library (%q) is not allowed across the partitions (%s -> %s), use java_sdk_library instead"
- ctx.PropertyErrorf(propName, errorFormat, dep.Name(), j.partitionGroup(ctx), dep.partitionGroup(ctx))
- }
-}
diff --git a/java/sdk_library_internal.go b/java/sdk_library_internal.go
new file mode 100644
index 0000000..6f24902
--- /dev/null
+++ b/java/sdk_library_internal.go
@@ -0,0 +1,1013 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "android/soong/android"
+ "android/soong/etc"
+ "fmt"
+ "path"
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+)
+
+// ---------------------------------------------------------------------------------------------
+// Naming scheme of the submodules generated by java_sdk_library and java_sdk_library_import
+// ---------------------------------------------------------------------------------------------
+
+const (
+ sdkXmlFileSuffix = ".xml"
+ implLibSuffix = ".impl"
+)
+
+// Module name of the runtime implementation library
+func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
+ return c.module.RootLibraryName() + implLibSuffix
+}
+
+// Module name of the XML file for the lib
+func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
+ return c.module.RootLibraryName() + sdkXmlFileSuffix
+}
+
+// Name of the java_library module that compiles the stubs source.
+func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.stubsLibraryModuleName(baseName)
+}
+
+// Name of the java_library module that compiles the exportable stubs source.
+func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.exportableStubsLibraryModuleName(baseName)
+}
+
+// Name of the droidstubs module that generates the stubs source and may also
+// generate/check the API.
+func (c *commonToSdkLibraryAndImport) droidstubsModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.stubsSourceModuleName(baseName)
+}
+
+// Name of the java_api_library module that generates the from-text stubs source
+// and compiles to a jar file.
+func (c *commonToSdkLibraryAndImport) fromTextStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.apiLibraryModuleName(baseName)
+}
+
+// Name of the java_library module that compiles the stubs
+// generated from source Java files.
+func (c *commonToSdkLibraryAndImport) fromSourceStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.sourceStubsLibraryModuleName(baseName)
+}
+
+// Name of the java_library module that compiles the exportable stubs
+// generated from source Java files.
+func (c *commonToSdkLibraryAndImport) exportableFromSourceStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.exportableSourceStubsLibraryModuleName(baseName)
+}
+
+// ---------------------------------------------------------------------------------------------
+// Build rules of the submodules generated by java_sdk_library.
+// java_sdk_library "framework-foo" generates the following submodules:
+//
+// - "framework-foo.impl" (type: [Library]): the implementation library, which generates the
+// compilation outputs that include the implementation details and the private apis
+// (i.e. class/methods that are annotated @hide).
+//
+// - "framework-foo.stubs.source.<[apiScope.name]>" (type: [Droidstubs]): droidstubs module that
+// generates the stubs and the api files for the given api scope.
+//
+// - "framework-foo.stubs.<[apiScope.name]>" (type: [Library]): stub library module that
+// provides the compilation output of the stubs to the reverse dependencies. The module
+// itself does not perform any compilation actions; the module statically depends on one of
+// the from-source stub module or the from-text stub configuration based on the build
+// configuration.
+//
+// - "framework-foo.stubs.<[apiScope.name]>.from-source" (type: [Library]): stub library module
+// that compiles the stubs generated by the droidstubs submodule. This module is a static
+// dependency of the stub library module when
+// [android/soong/android/config.BuildFromTextStub()] is false.
+//
+// - "framework-foo.stubs.<[apiScope.name]>.from-text" (type: [ApiLibrary]): api library module
+// that generates and compiles the stubs from the api files checked in the tree instead of
+// the source Java files (e.g. *-current.txt files). This module is a static dependency of
+// the stub library module when [android/soong/android/config.BuildFromTextStub()] is true.
+//
+// - "framework-foo.stubs.exportable.<[apiScope.name]>" (type: [Library]): stub library module
+// that provides the "exportable" stubs. "exportable" stubs are the stubs that do not
+// include in-development flagged apis. This module is only used for SDK builds to generate
+// the SDK artifacts, and not purposed for consumption for other modules.
+//
+// - "framework-foo.stubs.exportable.<[apiScope.name]>.from-source" (type: [Library]): stub
+// library module that compiles the "exportable" stubs generated by the droidstubs
+// submodule. This module is always a static dependency of the "exportable" stub library
+// module given that from-text stubs cannot be used for SDK builds as it does not contain
+// documentations.
+//
+// - "framework-foo.xml" (type: [sdkLibraryXml]): xml library that generates the permission xml
+// file, which allows [SdkLibrary] to be used with <uses-permission> tag in the
+// AndroidManifest.xml files.
+// ---------------------------------------------------------------------------------------------
+
+// Creates the implementation [Library] with ".impl" suffix.
+func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
+ visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)
+
+ staticLibs := module.properties.Static_libs.Clone()
+ staticLibs.AppendSimpleValue(module.sdkLibraryProperties.Impl_only_static_libs)
+ props := struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Visibility []string
+ Libs []string
+ Static_libs proptools.Configurable[[]string]
+ Apex_available []string
+ Stem *string
+ }{
+ Name: proptools.StringPtr(module.implLibraryModuleName()),
+ Enabled: module.EnabledProperty(),
+ Visibility: visibility,
+
+ Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...),
+
+ Static_libs: staticLibs,
+ // Pass the apex_available settings down so that the impl library can be statically
+ // embedded within a library that is added to an APEX. Needed for updatable-media.
+ Apex_available: module.ApexAvailable(),
+
+ Stem: proptools.StringPtr(module.Name()),
+ }
+
+ properties := []interface{}{
+ &module.properties,
+ &module.protoProperties,
+ &module.deviceProperties,
+ &module.dexProperties,
+ &module.dexpreoptProperties,
+ &module.linter.properties,
+ &module.overridableProperties,
+ &props,
+ module.sdkComponentPropertiesForChildLibrary(),
+ }
+ mctx.CreateModule(LibraryFactory, properties...)
+}
+
+// Creates the [Droidstubs] module with ".stubs.source.<[apiScope.name]>" that creates stubs
+// source files from the given full source files and also updates and checks the API
+// specification files (i.e. "*-current.txt", "*-removed.txt" files).
+func (module *SdkLibrary) createDroidstubs(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
+ props := struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Visibility []string
+ Srcs []string
+ Installable *bool
+ Sdk_version *string
+ Api_surface *string
+ System_modules *string
+ Libs proptools.Configurable[[]string]
+ Output_javadoc_comments *bool
+ Arg_files []string
+ Args *string
+ Java_version *string
+ Annotations_enabled *bool
+ Merge_annotations_dirs []string
+ Merge_inclusion_annotations_dirs []string
+ Generate_stubs *bool
+ Previous_api *string
+ Aconfig_declarations []string
+ Check_api struct {
+ Current ApiToCheck
+ Last_released ApiToCheck
+
+ Api_lint struct {
+ Enabled *bool
+ New_since *string
+ Baseline_file *string
+ }
+ }
+ Aidl struct {
+ Include_dirs []string
+ Local_include_dirs []string
+ }
+ Dists []android.Dist
+ }{}
+
+ // The stubs source processing uses the same compile time classpath when extracting the
+ // API from the implementation library as it does when compiling it. i.e. the same
+ // * sdk version
+ // * system_modules
+ // * libs (static_libs/libs)
+
+ props.Name = proptools.StringPtr(name)
+ props.Enabled = module.EnabledProperty()
+ props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility)
+ props.Srcs = append(props.Srcs, module.properties.Srcs...)
+ props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...)
+ props.Sdk_version = module.deviceProperties.Sdk_version
+ props.Api_surface = &apiScope.name
+ props.System_modules = module.deviceProperties.System_modules
+ props.Installable = proptools.BoolPtr(false)
+ // A droiddoc module has only one Libs property and doesn't distinguish between
+ // shared libs and static libs. So we need to add both of these libs to Libs property.
+ props.Libs = proptools.NewConfigurable[[]string](nil, nil)
+ props.Libs.AppendSimpleValue(module.properties.Libs)
+ props.Libs.Append(module.properties.Static_libs)
+ props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs)
+ props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs)
+ props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
+ props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
+ props.Java_version = module.properties.Java_version
+
+ props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
+ props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
+ props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
+ props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations
+
+ droidstubsArgs := []string{}
+ if len(module.sdkLibraryProperties.Api_packages) != 0 {
+ droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
+ }
+ droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
+ disabledWarnings := []string{"HiddenSuperclass"}
+ if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) {
+ disabledWarnings = append(disabledWarnings,
+ "BroadcastBehavior",
+ "DeprecationMismatch",
+ "MissingPermission",
+ "SdkConstant",
+ "Todo",
+ )
+ }
+ droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
+
+ // Output Javadoc comments for public scope.
+ if apiScope == apiScopePublic {
+ props.Output_javadoc_comments = proptools.BoolPtr(true)
+ }
+
+ // Add in scope specific arguments.
+ droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
+ props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
+ props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
+
+ // List of APIs identified from the provided source files are created. They are later
+ // compared against to the not-yet-released (a.k.a current) list of APIs and to the
+ // last-released (a.k.a numbered) list of API.
+ currentApiFileName := apiScope.apiFilePrefix + "current.txt"
+ removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
+ apiDir := module.getApiDir()
+ currentApiFileName = path.Join(apiDir, currentApiFileName)
+ removedApiFileName = path.Join(apiDir, removedApiFileName)
+
+ // check against the not-yet-release API
+ props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
+ props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
+
+ if module.compareAgainstLatestApi(apiScope) {
+ // check against the latest released API
+ latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
+ props.Previous_api = latestApiFilegroupName
+ props.Check_api.Last_released.Api_file = latestApiFilegroupName
+ props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
+ module.latestRemovedApiFilegroupName(apiScope))
+ props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
+ module.latestIncompatibilitiesFilegroupName(apiScope))
+
+ if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
+ // Enable api lint.
+ props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
+ props.Check_api.Api_lint.New_since = latestApiFilegroupName
+
+ // If it exists then pass a lint-baseline.txt through to droidstubs.
+ baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
+ baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
+ paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
+ if err != nil {
+ mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
+ }
+ if len(paths) == 1 {
+ props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
+ } else if len(paths) != 0 {
+ mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
+ }
+ }
+ }
+
+ if !Bool(module.sdkLibraryProperties.No_dist) {
+ // Dist the api txt and removed api txt artifacts for sdk builds.
+ distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
+ stubsTypeTagPrefix := ""
+ if mctx.Config().ReleaseHiddenApiExportableStubs() {
+ stubsTypeTagPrefix = ".exportable"
+ }
+ for _, p := range []struct {
+ tag string
+ pattern string
+ }{
+ // "exportable" api files are copied to the dist directory instead of the
+ // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
+ // is set. Otherwise, the "everything" api files are copied to the dist directory.
+ {tag: "%s.api.txt", pattern: "%s.txt"},
+ {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
+ } {
+ props.Dists = append(props.Dists, android.Dist{
+ Targets: []string{"sdk", "win_sdk"},
+ Dir: distDir,
+ Dest: proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
+ Tag: proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
+ })
+ }
+ }
+
+ mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx)
+}
+
+type libraryProperties struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Visibility []string
+ Srcs []string
+ Installable *bool
+ Sdk_version *string
+ System_modules *string
+ Patch_module *string
+ Libs []string
+ Static_libs []string
+ Compile_dex *bool
+ Java_version *string
+ Openjdk9 struct {
+ Srcs []string
+ Javacflags []string
+ }
+ Dist struct {
+ Targets []string
+ Dest *string
+ Dir *string
+ Tag *string
+ }
+ Is_stubs_module *bool
+ Stub_contributing_api *string
+}
+
+func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
+ props := libraryProperties{}
+ props.Enabled = module.EnabledProperty()
+ props.Visibility = []string{"//visibility:override", "//visibility:private"}
+ // sources are generated from the droiddoc
+ sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
+ props.Sdk_version = proptools.StringPtr(sdkVersion)
+ props.System_modules = module.deviceProperties.System_modules
+ props.Patch_module = module.properties.Patch_module
+ props.Installable = proptools.BoolPtr(false)
+ props.Libs = module.sdkLibraryProperties.Stub_only_libs
+ props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
+ props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
+ // The stub-annotations library contains special versions of the annotations
+ // with CLASS retention policy, so that they're kept.
+ if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
+ props.Libs = append(props.Libs, "stub-annotations")
+ }
+ props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
+ props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
+ // 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")
+ props.Is_stubs_module = proptools.BoolPtr(true)
+ props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String())
+
+ return props
+}
+
+// Creates the from-source stub [Library] with ".stubs.<[apiScope.name]>.from-source" suffix.
+func (module *SdkLibrary) createFromSourceStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ props := module.stubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.fromSourceStubsLibraryModuleName(apiScope))
+ props.Srcs = []string{":" + module.droidstubsModuleName(apiScope)}
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the "exportable" from-source stub [Library] with
+// ".stubs.exportable.<[apiScope.name]>" suffix.
+func (module *SdkLibrary) createExportableFromSourceStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+ props := module.stubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.exportableFromSourceStubsLibraryModuleName(apiScope))
+ props.Srcs = []string{":" + module.droidstubsModuleName(apiScope) + "{.exportable}"}
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the from-text stub [ApiLibrary] with ".stubs.<[apiScope.name]>.from-text" suffix.
+func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+ props := struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Visibility []string
+ Api_contributions []string
+ Libs proptools.Configurable[[]string]
+ Static_libs []string
+ System_modules *string
+ Enable_validation *bool
+ Stubs_type *string
+ Sdk_version *string
+ Previous_api *string
+ }{}
+
+ props.Name = proptools.StringPtr(module.fromTextStubsLibraryModuleName(apiScope))
+ props.Enabled = module.EnabledProperty()
+ props.Visibility = []string{"//visibility:override", "//visibility:private"}
+
+ apiContributions := []string{}
+
+ // Api surfaces are not independent of each other, but have subset relationships,
+ // and so does the api files. To generate from-text stubs for api surfaces other than public,
+ // all subset api domains' api_contriubtions must be added as well.
+ scope := apiScope
+ for scope != nil {
+ apiContributions = append(apiContributions, module.droidstubsModuleName(scope)+".api.contribution")
+ scope = scope.extends
+ }
+ if apiScope == apiScopePublic {
+ additionalApiContribution := module.apiLibraryAdditionalApiContribution()
+ if additionalApiContribution != "" {
+ apiContributions = append(apiContributions, additionalApiContribution)
+ }
+ }
+
+ props.Api_contributions = apiContributions
+
+ // Ensure that stub-annotations is added to the classpath before any other libs
+ props.Libs = proptools.NewConfigurable[[]string](nil, nil)
+ props.Libs.AppendSimpleValue([]string{"stub-annotations"})
+ props.Libs.AppendSimpleValue(module.properties.Libs)
+ props.Libs.Append(module.properties.Static_libs)
+ props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs)
+ props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs)
+ props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
+
+ props.System_modules = module.deviceProperties.System_modules
+ props.Enable_validation = proptools.BoolPtr(true)
+ props.Stubs_type = proptools.StringPtr("everything")
+
+ if module.deviceProperties.Sdk_version != nil {
+ props.Sdk_version = module.deviceProperties.Sdk_version
+ }
+
+ if module.compareAgainstLatestApi(apiScope) {
+ // check against the latest released API
+ latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
+ props.Previous_api = latestApiFilegroupName
+ }
+
+ mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
+ props := libraryProperties{}
+
+ props.Enabled = module.EnabledProperty()
+ props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
+ sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
+ props.Sdk_version = proptools.StringPtr(sdkVersion)
+
+ props.System_modules = module.deviceProperties.System_modules
+
+ // The imports need to be compiled to dex if the java_sdk_library requests it.
+ compileDex := module.dexProperties.Compile_dex
+ if module.stubLibrariesCompiledForDex() {
+ compileDex = proptools.BoolPtr(true)
+ }
+ props.Compile_dex = compileDex
+
+ props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String())
+
+ if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
+ props.Dist.Targets = []string{"sdk", "win_sdk"}
+ props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
+ props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
+ props.Dist.Tag = proptools.StringPtr(".jar")
+ }
+ props.Is_stubs_module = proptools.BoolPtr(true)
+
+ return props
+}
+
+// Creates the stub [Library] with ".stubs.<[apiScope.name]>" suffix.
+func (module *SdkLibrary) createTopLevelStubsLibrary(
+ mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
+ doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
+ props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
+ props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+
+ // Add the stub compiling java_library/java_api_library as static lib based on build config
+ staticLib := module.fromSourceStubsLibraryModuleName(apiScope)
+ if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() {
+ staticLib = module.fromTextStubsLibraryModuleName(apiScope)
+ }
+ props.Static_libs = append(props.Static_libs, staticLib)
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the "exportable" stub [Library] with ".stubs.exportable.<[apiScope.name]>" suffix.
+func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
+ mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
+ doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
+ props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
+ props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
+
+ staticLib := module.exportableFromSourceStubsLibraryModuleName(apiScope)
+ props.Static_libs = append(props.Static_libs, staticLib)
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the [sdkLibraryXml] with ".xml" suffix.
+func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
+ moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
+ var moduleMinApiLevelStr = moduleMinApiLevel.String()
+ if moduleMinApiLevel == android.NoneApiLevel {
+ moduleMinApiLevelStr = "current"
+ }
+ props := struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Lib_name *string
+ Apex_available []string
+ On_bootclasspath_since *string
+ On_bootclasspath_before *string
+ Min_device_sdk *string
+ Max_device_sdk *string
+ Sdk_library_min_api_level *string
+ Uses_libs_dependencies []string
+ }{
+ Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
+ Enabled: module.EnabledProperty(),
+ Lib_name: proptools.StringPtr(module.BaseModuleName()),
+ Apex_available: module.ApexProperties.Apex_available,
+ On_bootclasspath_since: module.commonSdkLibraryProperties.On_bootclasspath_since,
+ On_bootclasspath_before: module.commonSdkLibraryProperties.On_bootclasspath_before,
+ Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
+ Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
+ Sdk_library_min_api_level: &moduleMinApiLevelStr,
+ Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
+ }
+
+ mctx.CreateModule(sdkLibraryXmlFactory, &props)
+}
+
+// ---------------------------------------------------------------------------------------------
+// Build rules of the submodules generated by java_sdk_library_import.
+// Note that the java_sdk_library_import module does not generate the implementation library.
+// Instead, it will create a dependency to the source implemenetation library if one exists.
+// java_sdk_library_import "framework-foo" generates the following submodules:
+//
+// - "framework-foo.stubs.<[apiScope.name]>" (type: [Import]): prebuilt stub library module that
+// provides the stub jar file checked in the tree.
+//
+// - "framework-foo.stubs.source.<[apiScope.name]>" (type: [PrebuiltStubsSources]): prebuilt
+// droidstubs module that provides the stub source jar file checked in the tree.
+//
+// - "framework-foo.stubs.source.<[apiScope.name]>.api.contribution"
+// (type [JavaApiContributionImport]): prebuilt java_api_contribution module that provides
+// the prebuilt api file for previously released from-text stub generation.
+// ---------------------------------------------------------------------------------------------
+
+// Creates the prebuilt stub [Import] with ".stubs.<[apiScope.name]>" suffix.
+func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ // Creates a java import for the jar with ".stubs" suffix
+ props := struct {
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Sdk_version *string
+ Libs []string
+ Jars []string
+ Compile_dex *bool
+ Is_stubs_module *bool
+
+ android.UserSuppliedPrebuiltProperties
+ }{}
+ props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName()))
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
+ props.Sdk_version = scopeProperties.Sdk_version
+ // Prepend any of the libs from the legacy public properties to the libs for each of the
+ // scopes to avoid having to duplicate them in each scope.
+ props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
+ props.Jars = scopeProperties.Jars
+
+ // The imports are preferred if the java_sdk_library_import is preferred.
+ props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
+
+ // The imports need to be compiled to dex if the java_sdk_library_import requests it.
+ compileDex := module.properties.Compile_dex
+ if module.stubLibrariesCompiledForDex() {
+ compileDex = proptools.BoolPtr(true)
+ }
+ props.Compile_dex = compileDex
+ props.Is_stubs_module = proptools.BoolPtr(true)
+
+ mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ props := struct {
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Srcs []string
+
+ android.UserSuppliedPrebuiltProperties
+ }{}
+ props.Name = proptools.StringPtr(module.droidstubsModuleName(apiScope))
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
+ props.Srcs = scopeProperties.Stub_srcs
+
+ // The stubs source is preferred if the java_sdk_library_import is preferred.
+ props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
+
+ mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the prebuilt api contribution [JavaApiContributionImport] with
+// ".stubs.source.<[apiScope.name]>.api.contribution" suffix.
+func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ api_file := scopeProperties.Current_api
+ api_surface := &apiScope.name
+
+ props := struct {
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Api_surface *string
+ Api_file *string
+ Visibility []string
+ }{}
+
+ props.Name = proptools.StringPtr(module.droidstubsModuleName(apiScope) + ".api.contribution")
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution")
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
+ props.Api_surface = api_surface
+ props.Api_file = api_file
+ props.Visibility = []string{"//visibility:override", "//visibility:public"}
+
+ mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// ---------------------------------------------------------------------------------------------
+// End of the build rules of the submodules generated by java_sdk_library_import.
+// ---------------------------------------------------------------------------------------------
+
+// Definition of the [sdkLibraryXml] module. The module generates the permissions xml file,
+// so that the apps can specify the java_sdk_library using <uses-permission> tag in the
+// AndroidManifest.xml file.
+type sdkLibraryXml struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.ApexModuleBase
+
+ properties sdkLibraryXmlProperties
+
+ outputFilePath android.OutputPath
+ installDirPath android.InstallPath
+
+ hideApexVariantFromMake bool
+}
+
+type sdkLibraryXmlProperties struct {
+ // canonical name of the lib
+ Lib_name *string
+
+ // Signals that this shared library is part of the bootclasspath starting
+ // on the version indicated in this attribute.
+ //
+ // This will make platforms at this level and above to ignore
+ // <uses-library> tags with this library name because the library is already
+ // available
+ On_bootclasspath_since *string
+
+ // Signals that this shared library was part of the bootclasspath before
+ // (but not including) the version indicated in this attribute.
+ //
+ // The system will automatically add a <uses-library> tag with this library to
+ // apps that target any SDK less than the version indicated in this attribute.
+ On_bootclasspath_before *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is below the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Min_device_sdk *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is above the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Max_device_sdk *string
+
+ // The SdkLibrary's min api level as a string
+ //
+ // This value comes from the ApiLevel of the MinSdkVersion property.
+ Sdk_library_min_api_level *string
+
+ // Uses-libs dependencies that the shared library requires to work correctly.
+ //
+ // This will add dependency="foo:bar" to the <library> section.
+ Uses_libs_dependencies []string
+}
+
+// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
+// Not to be used directly by users. java_sdk_library internally uses this.
+func sdkLibraryXmlFactory() android.Module {
+ module := &sdkLibraryXml{}
+
+ module.AddProperties(&module.properties)
+
+ android.InitApexModule(module)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+
+ return module
+}
+
+func (module *sdkLibraryXml) UniqueApexVariations() bool {
+ // sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
+ // mounted APEX, which contains the name of the APEX.
+ return true
+}
+
+// from android.PrebuiltEtcModule
+func (module *sdkLibraryXml) BaseDir() string {
+ return "etc"
+}
+
+// from android.PrebuiltEtcModule
+func (module *sdkLibraryXml) SubDir() string {
+ return "permissions"
+}
+
+var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)
+
+// from android.ApexModule
+func (module *sdkLibraryXml) AvailableFor(what string) bool {
+ return true
+}
+
+func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // do nothing
+}
+
+var _ android.ApexModule = (*sdkLibraryXml)(nil)
+
+// Implements android.ApexModule
+func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+ sdkVersion android.ApiLevel) error {
+ // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked
+ return nil
+}
+
+// File path to the runtime implementation library
+func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
+ implName := proptools.String(module.properties.Lib_name)
+ if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
+ // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
+ // In most cases, this works fine. But when apex_name is set or override_apex is used
+ // this can be wrong.
+ return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.BaseApexName, implName)
+ }
+ partition := "system"
+ if module.SocSpecific() {
+ partition = "vendor"
+ } else if module.DeviceSpecific() {
+ partition = "odm"
+ } else if module.ProductSpecific() {
+ partition = "product"
+ } else if module.SystemExtSpecific() {
+ partition = "system_ext"
+ }
+ return "/" + partition + "/framework/" + implName + ".jar"
+}
+
+func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string {
+ if value == nil {
+ return ""
+ }
+ apiLevel, err := android.ApiLevelFromUser(ctx, *value)
+ if err != nil {
+ // attributes in bp files have underscores but in the xml have dashes.
+ ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
+ return ""
+ }
+ if apiLevel.IsCurrent() {
+ // passing "current" would always mean a future release, never the current (or the current in
+ // progress) which means some conditions would never be triggered.
+ ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"),
+ `"current" is not an allowed value for this attribute`)
+ return ""
+ }
+ // "safeValue" is safe because it translates finalized codenames to a string
+ // with their SDK int.
+ safeValue := apiLevel.String()
+ return formattedOptionalAttribute(attrName, &safeValue)
+}
+
+// formats an attribute for the xml permissions file if the value is not null
+// returns empty string otherwise
+func formattedOptionalAttribute(attrName string, value *string) string {
+ if value == nil {
+ return ""
+ }
+ return fmt.Sprintf(" %s=\"%s\"\n", attrName, *value)
+}
+
+func formattedDependenciesAttribute(dependencies []string) string {
+ if dependencies == nil {
+ return ""
+ }
+ return fmt.Sprintf(" dependency=\"%s\"\n", strings.Join(dependencies, ":"))
+}
+
+func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
+ libName := proptools.String(module.properties.Lib_name)
+ libNameAttr := formattedOptionalAttribute("name", &libName)
+ filePath := module.implPath(ctx)
+ filePathAttr := formattedOptionalAttribute("file", &filePath)
+ implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since)
+ implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
+ minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
+ maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
+ dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
+ // <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
+ // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
+ var libraryTag string
+ if module.properties.Min_device_sdk != nil {
+ libraryTag = " <apex-library\n"
+ } else {
+ libraryTag = " <library\n"
+ }
+
+ return strings.Join([]string{
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
+ "<!-- Copyright (C) 2018 The Android Open Source Project\n",
+ "\n",
+ " Licensed under the Apache License, Version 2.0 (the \"License\");\n",
+ " you may not use this file except in compliance with the License.\n",
+ " You may obtain a copy of the License at\n",
+ "\n",
+ " http://www.apache.org/licenses/LICENSE-2.0\n",
+ "\n",
+ " Unless required by applicable law or agreed to in writing, software\n",
+ " distributed under the License is distributed on an \"AS IS\" BASIS,\n",
+ " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
+ " See the License for the specific language governing permissions and\n",
+ " limitations under the License.\n",
+ "-->\n",
+ "<permissions>\n",
+ libraryTag,
+ libNameAttr,
+ filePathAttr,
+ implicitFromAttr,
+ implicitUntilAttr,
+ minSdkAttr,
+ maxSdkAttr,
+ dependenciesAttr,
+ " />\n",
+ "</permissions>\n",
+ }, "")
+}
+
+func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ module.hideApexVariantFromMake = !apexInfo.IsForPlatform()
+
+ libName := proptools.String(module.properties.Lib_name)
+ module.selfValidate(ctx)
+ xmlContent := module.permissionsContents(ctx)
+
+ module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
+ android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)
+
+ module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
+ ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
+
+ ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "")
+}
+
+func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
+ if module.hideApexVariantFromMake {
+ return []android.AndroidMkEntries{{
+ Disabled: true,
+ }}
+ }
+
+ return []android.AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(module.outputFilePath),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_TAGS", "optional")
+ entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())
+ },
+ },
+ }}
+}
+
+func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) {
+ module.validateAtLeastTAttributes(ctx)
+ module.validateMinAndMaxDeviceSdk(ctx)
+ module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx)
+ module.validateOnBootclasspathBeforeRequirements(ctx)
+}
+
+func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) {
+ t := android.ApiLevelOrPanic(ctx, "Tiramisu")
+ module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk")
+ module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk")
+ module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before")
+ module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since")
+}
+
+func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) {
+ if attr != nil {
+ if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil {
+ // we will inform the user of invalid inputs when we try to write the
+ // permissions xml file so we don't need to do it here
+ if t.GreaterThan(level) {
+ ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T")
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) {
+ if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil {
+ min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
+ max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
+ if minErr == nil && maxErr == nil {
+ // we will inform the user of invalid inputs when we try to write the
+ // permissions xml file so we don't need to do it here
+ if min.GreaterThan(max) {
+ ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk")
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) {
+ moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
+ if module.properties.Min_device_sdk != nil {
+ api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
+ if err == nil {
+ if moduleMinApi.GreaterThan(api) {
+ ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
+ }
+ }
+ }
+ if module.properties.Max_device_sdk != nil {
+ api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
+ if err == nil {
+ if moduleMinApi.GreaterThan(api) {
+ ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) {
+ moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
+ if module.properties.On_bootclasspath_before != nil {
+ t := android.ApiLevelOrPanic(ctx, "Tiramisu")
+ // if we use the attribute, then we need to do this validation
+ if moduleMinApi.LessThan(t) {
+ // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+)
+ if module.properties.Min_device_sdk == nil {
+ ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T")
+ }
+ }
+ }
+}
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 31fbc5a..6031d72 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -22,8 +22,6 @@
"testing"
"android/soong/android"
-
- "github.com/google/blueprint/proptools"
)
func TestJavaSdkLibrary(t *testing.T) {
@@ -55,7 +53,7 @@
java_library {
name: "baz",
srcs: ["c.java"],
- libs: ["foo", "bar.stubs"],
+ libs: ["foo.stubs.system", "bar.stubs"],
sdk_version: "system_current",
}
java_sdk_library {
@@ -92,25 +90,25 @@
java_library {
name: "qux",
srcs: ["c.java"],
- libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"],
+ libs: ["baz", "fred.stubs", "quuz.stubs", "wilma.stubs", "barney.stubs.system", "betty.stubs.system"],
sdk_version: "system_current",
}
java_library {
name: "baz-test",
srcs: ["c.java"],
- libs: ["foo"],
+ libs: ["foo.stubs.test"],
sdk_version: "test_current",
}
java_library {
name: "baz-29",
srcs: ["c.java"],
- libs: ["foo"],
+ libs: ["sdk_system_29_foo"],
sdk_version: "system_29",
}
java_library {
name: "baz-module-30",
srcs: ["c.java"],
- libs: ["foo"],
+ libs: ["sdk_module-lib_30_foo"],
sdk_version: "module_30",
}
`)
@@ -162,11 +160,11 @@
baz29Javac := result.ModuleForTests("baz-29", "android_common").Rule("javac")
// tests if baz-29 is actually linked to the system 29 stubs lib
- android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/29/system/foo.jar")
+ android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/sdk_system_29_foo/android_common/combined/sdk_system_29_foo.jar")
bazModule30Javac := result.ModuleForTests("baz-module-30", "android_common").Rule("javac")
// tests if "baz-module-30" is actually linked to the module 30 stubs lib
- android.AssertStringDoesContain(t, "baz-module-30 javac classpath", bazModule30Javac.Args["classpath"], "prebuilts/sdk/30/module-lib/foo.jar")
+ android.AssertStringDoesContain(t, "baz-module-30 javac classpath", bazModule30Javac.Args["classpath"], "prebuilts/sdk/sdk_module-lib_30_foo/android_common/combined/sdk_module-lib_30_foo.jar")
// test if baz has exported SDK lib names foo and bar to qux
qux := result.ModuleForTests("qux", "android_common")
@@ -445,7 +443,7 @@
java_library {
name: "bar",
srcs: ["b.java"],
- libs: ["foo"],
+ libs: ["foo.stubs"],
}
`)
@@ -763,7 +761,7 @@
java_library {
name: "bar",
srcs: ["a.java"],
- libs: ["foo-public", "foo-system", "foo-module-lib", "foo-system-server"],
+ libs: ["foo-public.stubs", "foo-system.stubs.system", "foo-module-lib.stubs.module_lib", "foo-system-server.stubs.system_server"],
sdk_version: "system_server_current",
}
`)
@@ -789,102 +787,26 @@
}
}
-func TestJavaSdkLibrary_MissingScope(t *testing.T) {
- prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`requires api scope module-lib from foo but it only has \[\] available`)).
- RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- public: {
- enabled: false,
- },
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- sdk_version: "module_current",
- }
- `)
-}
-
-func TestJavaSdkLibrary_FallbackScope(t *testing.T) {
- android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- system: {
- enabled: true,
- },
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- // foo does not have module-lib scope so it should fallback to system
- sdk_version: "module_current",
- }
- `)
-}
-
-func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- system: {
- enabled: true,
- },
- default_to_stubs: true,
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- // does not have sdk_version set, should fallback to module,
- // which will then fallback to system because the module scope
- // is not enabled.
- }
- `)
- // The baz library should depend on the system stubs jar.
- bazLibrary := result.ModuleForTests("baz", "android_common").Rule("javac")
- if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
- t.Errorf("expected %q, found %#q", expected, actual)
- }
-}
-
func TestJavaSdkLibraryImport(t *testing.T) {
result := prepareForJavaTest.RunTestWithBp(t, `
java_library {
name: "foo",
srcs: ["a.java"],
- libs: ["sdklib"],
+ libs: ["sdklib.stubs"],
sdk_version: "current",
}
java_library {
name: "foo.system",
srcs: ["a.java"],
- libs: ["sdklib"],
+ libs: ["sdklib.stubs.system"],
sdk_version: "system_current",
}
java_library {
name: "foo.test",
srcs: ["a.java"],
- libs: ["sdklib"],
+ libs: ["sdklib.stubs.test"],
sdk_version: "test_current",
}
@@ -1017,7 +939,7 @@
java_library {
name: "public",
srcs: ["a.java"],
- libs: ["sdklib"],
+ libs: ["sdklib.stubs"],
sdk_version: "current",
}
`)
@@ -1190,155 +1112,6 @@
}
}
-func TestJavaSdkLibraryEnforce(t *testing.T) {
- partitionToBpOption := func(partition string) string {
- switch partition {
- case "system":
- return ""
- case "vendor":
- return "soc_specific: true,"
- case "product":
- return "product_specific: true,"
- default:
- panic("Invalid partition group name: " + partition)
- }
- }
-
- type testConfigInfo struct {
- libraryType string
- fromPartition string
- toPartition string
- enforceProductInterface bool
- enforceJavaSdkLibraryCheck bool
- allowList []string
- }
-
- createPreparer := func(info testConfigInfo) android.FixturePreparer {
- bpFileTemplate := `
- java_library {
- name: "foo",
- srcs: ["foo.java"],
- libs: ["bar"],
- sdk_version: "current",
- %s
- }
-
- %s {
- name: "bar",
- srcs: ["bar.java"],
- sdk_version: "current",
- %s
- }
- `
-
- bpFile := fmt.Sprintf(bpFileTemplate,
- partitionToBpOption(info.fromPartition),
- info.libraryType,
- partitionToBpOption(info.toPartition))
-
- return android.GroupFixturePreparers(
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("bar"),
- android.FixtureWithRootAndroidBp(bpFile),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
- variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
- variables.InterPartitionJavaLibraryAllowList = info.allowList
- }),
- )
- }
-
- runTest := func(t *testing.T, info testConfigInfo, expectedErrorPattern string) {
- t.Run(fmt.Sprintf("%v", info), func(t *testing.T) {
- errorHandler := android.FixtureExpectsNoErrors
- if expectedErrorPattern != "" {
- errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorPattern)
- }
- android.GroupFixturePreparers(
- prepareForJavaTest,
- createPreparer(info),
- ).
- ExtendWithErrorHandler(errorHandler).
- RunTest(t)
- })
- }
-
- errorMessage := "is not allowed across the partitions"
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: false,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceProductInterface: false,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- allowList: []string{"bar"},
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "product",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "product",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "vendor",
- toPartition: "product",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-}
-
func TestJavaSdkLibraryDist(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaBuildComponents,
@@ -1657,7 +1430,7 @@
name: "bar",
srcs: ["c.java", "b.java"],
libs: [
- "foo",
+ "foo.stubs",
],
uses_libs: [
"foo",
@@ -1752,7 +1525,7 @@
name: "mymodule",
srcs: ["a.java"],
sdk_version: "current",
- libs: ["sdklib",], // this should be dynamically resolved to sdklib.stubs (source) or prebuilt_sdklib.stubs (prebuilt)
+ libs: ["sdklib.stubs",], // this should be dynamically resolved to sdklib.stubs (source) or prebuilt_sdklib.stubs (prebuilt)
}
`
@@ -1893,3 +1666,111 @@
}
`)
}
+
+func TestSdkLibDirectDependency(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo", "bar"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern([]string{
+ `module "baz" variant "android_common": cannot depend directly on java_sdk_library ` +
+ `"foo"; try depending on "foo.stubs", or "foo.impl" instead`,
+ `module "baz" variant "android_common": cannot depend directly on java_sdk_library ` +
+ `"prebuilt_bar"; try depending on "bar.stubs", or "bar.impl" instead`,
+ }),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library_import {
+ name: "foo",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library_import {
+ name: "bar",
+ prefer: true,
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["b.java"],
+ libs: [
+ "foo",
+ "bar",
+ ],
+ }
+ `)
+}
+
+func TestSdkLibDirectDependencyWithPrebuiltSdk(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_version = intPtr(34)
+ variables.Platform_sdk_codename = stringPtr("VanillaIceCream")
+ variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+ variables.Platform_systemsdk_versions = []string{"33", "34", "VanillaIceCream"}
+ variables.DeviceSystemSdkVersions = []string{"VanillaIceCream"}
+ }),
+ FixtureWithPrebuiltApis(map[string][]string{
+ "33": {"foo"},
+ "34": {"foo"},
+ "35": {"foo"},
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+ `module "baz" variant "android_common": cannot depend directly on java_sdk_library "foo"; `+
+ `try depending on "sdk_public_33_foo", "sdk_system_33_foo", "sdk_test_33_foo", `+
+ `"sdk_module-lib_33_foo", or "sdk_system-server_33_foo" instead`),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["b.java"],
+ libs: [
+ "foo",
+ ],
+ sdk_version: "system_33",
+ }
+ `)
+}
diff --git a/java/testing.go b/java/testing.go
index 0c79e9f..6cc9fd1 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -424,7 +424,9 @@
"kotlin-stdlib-jdk8",
"kotlin-annotations",
"stub-annotations",
+
"aconfig-annotations-lib",
+ "aconfig_storage_reader_java",
"unsupportedappusage",
}
diff --git a/linkerconfig/proto/Android.bp b/linkerconfig/proto/Android.bp
index 754e7bf..a930502 100644
--- a/linkerconfig/proto/Android.bp
+++ b/linkerconfig/proto/Android.bp
@@ -15,6 +15,7 @@
"//apex_available:platform",
"//apex_available:anyapex",
],
+ visibility: ["//system/linkerconfig"],
}
python_library_host {
diff --git a/phony/Android.bp b/phony/Android.bp
index db5efc9..2e250c6 100644
--- a/phony/Android.bp
+++ b/phony/Android.bp
@@ -13,4 +13,5 @@
"phony.go",
],
pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
}
diff --git a/response/Android.bp b/response/Android.bp
index e19981f..2f319fe 100644
--- a/response/Android.bp
+++ b/response/Android.bp
@@ -13,4 +13,8 @@
testSrcs: [
"response_test.go",
],
+ visibility: [
+ "//build/make/tools/compliance",
+ "//build/soong:__subpackages__",
+ ],
}
diff --git a/rust/Android.bp b/rust/Android.bp
index 53c9462..781f325 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -61,4 +61,5 @@
"test_test.go",
],
pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
}
diff --git a/rust/clippy.go b/rust/clippy.go
index 6f0ed7f..426fd73 100644
--- a/rust/clippy.go
+++ b/rust/clippy.go
@@ -38,11 +38,14 @@
}
func (c *clippy) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
- enabled, lints, err := config.ClippyLintsForDir(ctx.ModuleDir(), c.Properties.Clippy_lints)
+ dirEnabled, lints, err := config.ClippyLintsForDir(ctx.ModuleDir(), c.Properties.Clippy_lints)
if err != nil {
ctx.PropertyErrorf("clippy_lints", err.Error())
}
- flags.Clippy = enabled
+
+ envDisable := ctx.Config().IsEnvTrue("SOONG_DISABLE_CLIPPY")
+
+ flags.Clippy = dirEnabled && !envDisable
flags.ClippyFlags = append(flags.ClippyFlags, lints)
return flags, deps
}
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index 79ea7a1..25f7580 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -24,4 +24,8 @@
"x86_64_device.go",
"arm64_linux_host.go",
],
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//prebuilts/rust/soong",
+ ],
}
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 9850570..94a4457 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -35,8 +35,13 @@
},
"armv8-2a": []string{},
"armv8-2a-dotprod": []string{},
+
+ // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
"armv9-a": []string{
- // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
+ "-Z branch-protection=bti,pac-ret",
+ "-Z stack-protector=none",
+ },
+ "armv9-2a": []string{
"-Z branch-protection=bti,pac-ret",
"-Z stack-protector=none",
},
diff --git a/rust/config/x86_64_device.go b/rust/config/x86_64_device.go
index fee1923..3c484d8 100644
--- a/rust/config/x86_64_device.go
+++ b/rust/config/x86_64_device.go
@@ -29,6 +29,7 @@
x86_64ArchVariantRustFlags = map[string][]string{
"": []string{},
+ "alderlake": []string{"-C target-cpu=alderlake"},
"broadwell": []string{"-C target-cpu=broadwell"},
"goldmont": []string{"-C target-cpu=goldmont"},
"goldmont-plus": []string{"-C target-cpu=goldmont-plus"},
diff --git a/rust/config/x86_device.go b/rust/config/x86_device.go
index 5d9d88a..3c597cc 100644
--- a/rust/config/x86_device.go
+++ b/rust/config/x86_device.go
@@ -27,6 +27,7 @@
x86ArchVariantRustFlags = map[string][]string{
"": []string{},
+ "alderlake": []string{"-C target-cpu=alderlake"},
"atom": []string{"-C target-cpu=atom"},
"broadwell": []string{"-C target-cpu=broadwell"},
"goldmont": []string{"-C target-cpu=goldmont"},
diff --git a/rust/coverage.go b/rust/coverage.go
index 91a7806..381fcf1 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -87,10 +87,6 @@
}
func (cov *coverage) begin(ctx BaseModuleContext) {
- if ctx.Host() {
- // Host coverage not yet supported.
- } else {
- // Update useSdk and sdkVersion args if Rust modules become SDK aware.
- cov.Properties = cc.SetCoverageProperties(ctx, cov.Properties, ctx.RustModule().nativeCoverage(), false, "")
- }
+ // Update useSdk and sdkVersion args if Rust modules become SDK aware.
+ cov.Properties = cc.SetCoverageProperties(ctx, cov.Properties, ctx.RustModule().nativeCoverage(), false, "")
}
diff --git a/scripts/check_prebuilt_presigned_apk.py b/scripts/check_prebuilt_presigned_apk.py
index abab2e1..db64f90 100755
--- a/scripts/check_prebuilt_presigned_apk.py
+++ b/scripts/check_prebuilt_presigned_apk.py
@@ -36,7 +36,7 @@
if fail:
sys.exit(args.apk + ': Contains compressed JNI libraries')
return True
- # It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides
+ # It's ok for non-privileged apps to have compressed dex files
if args.privileged and args.uncompress_priv_app_dex:
if info.filename.endswith('.dex') and info.compress_type != zipfile.ZIP_STORED:
if fail:
@@ -46,6 +46,10 @@
def main():
+ # This script enforces requirements for presigned apps as documented in:
+ # go/gms-uncompressed-jni-slides
+ # https://docs.partner.android.com/gms/building/integrating/jni-libs
+ # https://docs.partner.android.com/gms/policies/domains/mba#jni-lib
parser = argparse.ArgumentParser()
parser.add_argument('--aapt2', help = "the path to the aapt2 executable")
parser.add_argument('--zipalign', help = "the path to the zipalign executable")
diff --git a/scripts/manifest.py b/scripts/manifest.py
index 81f9c61..32603e8 100755
--- a/scripts/manifest.py
+++ b/scripts/manifest.py
@@ -23,9 +23,40 @@
android_ns = 'http://schemas.android.com/apk/res/android'
+def get_or_create_applications(doc, manifest):
+ """Get all <application> tags from the manifest, or create one if none exist.
+ Multiple <application> tags may exist when manifest feature flagging is used.
+ """
+ applications = get_children_with_tag(manifest, 'application')
+ if len(applications) == 0:
+ application = doc.createElement('application')
+ indent = get_indent(manifest.firstChild, 1)
+ first = manifest.firstChild
+ manifest.insertBefore(doc.createTextNode(indent), first)
+ manifest.insertBefore(application, first)
+ applications.append(application)
+ return applications
+
+
+def get_or_create_uses_sdks(doc, manifest):
+ """Get all <uses-sdk> tags from the manifest, or create one if none exist.
+ Multiple <uses-sdk> tags may exist when manifest feature flagging is used.
+ """
+ uses_sdks = get_children_with_tag(manifest, 'uses-sdk')
+ if len(uses_sdks) == 0:
+ uses_sdk = doc.createElement('uses-sdk')
+ indent = get_indent(manifest.firstChild, 1)
+ manifest.insertBefore(uses_sdk, manifest.firstChild)
+
+ # Insert an indent before uses-sdk to line it up with the indentation of the
+ # other children of the <manifest> tag.
+ manifest.insertBefore(doc.createTextNode(indent), manifest.firstChild)
+ uses_sdks.append(uses_sdk)
+ return uses_sdks
+
def get_children_with_tag(parent, tag_name):
children = []
- for child in parent.childNodes:
+ for child in parent.childNodes:
if child.nodeType == minidom.Node.ELEMENT_NODE and \
child.tagName == tag_name:
children.append(child)
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index b101259..1e32d1d 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -25,10 +25,7 @@
import sys
from xml.dom import minidom
-from manifest import android_ns
-from manifest import get_children_with_tag
-from manifest import parse_manifest
-from manifest import write_xml
+from manifest import *
class ManifestMismatchError(Exception):
@@ -122,7 +119,7 @@
# handles module names specified in Android.bp properties. However not all
# <uses-library> entries in the manifest correspond to real modules: some of
# the optional libraries may be missing at build time. Therefor this script
- # accepts raw module names as spelled in Android.bp/Amdroid.mk and trims the
+ # accepts raw module names as spelled in Android.bp/Android.mk and trims the
# optional namespace part manually.
required = trim_namespace_parts(required)
optional = trim_namespace_parts(optional)
@@ -205,15 +202,9 @@
"""Extract <uses-library> tags from the manifest."""
manifest = parse_manifest(xml)
- elems = get_children_with_tag(manifest, 'application')
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- if not elems:
- return [], [], []
-
- application = elems[0]
-
- libs = get_children_with_tag(application, 'uses-library')
+ libs = [child
+ for application in get_or_create_applications(xml, manifest)
+ for child in get_children_with_tag(application, 'uses-library')]
required = [uses_library_name(x) for x in libs if uses_library_required(x)]
optional = [
@@ -266,7 +257,7 @@
manifest: manifest (either parsed XML or aapt dump of APK)
is_apk: if the manifest comes from an APK or an XML file
"""
- if is_apk: #pylint: disable=no-else-return
+ if is_apk: #pylint: disable=no-else-return
return extract_target_sdk_version_apk(manifest)
else:
return extract_target_sdk_version_xml(manifest)
@@ -376,7 +367,7 @@
# Create a status file that is empty on success, or contains an
# error message on failure. When exceptions are suppressed,
- # dexpreopt command command will check file size to determine if
+ # dexpreopt command will check file size to determine if
# the check has failed.
if args.enforce_uses_libraries_status:
with open(args.enforce_uses_libraries_status, 'w') as f:
@@ -386,7 +377,7 @@
if args.extract_target_sdk_version:
try:
print(extract_target_sdk_version(manifest, is_apk))
- except: #pylint: disable=bare-except
+ except: #pylint: disable=bare-except
# Failed; don't crash, return "any" SDK version. This will
# result in dexpreopt not adding any compatibility libraries.
print(10000)
diff --git a/scripts/manifest_check_test.py b/scripts/manifest_check_test.py
index 8003b3e..abe0d8b 100755
--- a/scripts/manifest_check_test.py
+++ b/scripts/manifest_check_test.py
@@ -44,8 +44,8 @@
class EnforceUsesLibrariesTest(unittest.TestCase):
"""Unit tests for add_extract_native_libs function."""
- def run_test(self, xml, apk, uses_libraries=[], optional_uses_libraries=[],
- missing_optional_uses_libraries=[]): #pylint: disable=dangerous-default-value
+ def run_test(self, xml, apk, uses_libraries=(), optional_uses_libraries=(),
+ missing_optional_uses_libraries=()): #pylint: disable=dangerous-default-value
doc = minidom.parseString(xml)
try:
relax = False
@@ -114,14 +114,14 @@
self.assertFalse(matches)
def test_missing_uses_library(self):
- xml = self.xml_tmpl % ('')
- apk = self.apk_tmpl % ('')
+ xml = self.xml_tmpl % ''
+ apk = self.apk_tmpl % ''
matches = self.run_test(xml, apk, uses_libraries=['foo'])
self.assertFalse(matches)
def test_missing_optional_uses_library(self):
- xml = self.xml_tmpl % ('')
- apk = self.apk_tmpl % ('')
+ xml = self.xml_tmpl % ''
+ apk = self.apk_tmpl % ''
matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
self.assertFalse(matches)
@@ -234,6 +234,32 @@
optional_uses_libraries=['//x/y/z:bar'])
self.assertTrue(matches)
+ def test_multiple_applications(self):
+ xml = """<?xml version="1.0" encoding="utf-8"?>
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <application android:featureFlag="foo">
+ <uses-library android:name="foo" />
+ <uses-library android:name="bar" android:required="false" />
+ </application>
+ <application android:featureFlag="!foo">
+ <uses-library android:name="foo" />
+ <uses-library android:name="qux" android:required="false" />
+ </application>
+ </manifest>
+ """
+ apk = self.apk_tmpl % ('\n'.join([
+ uses_library_apk('foo'),
+ uses_library_apk('bar', required_apk(False)),
+ uses_library_apk('foo'),
+ uses_library_apk('qux', required_apk(False))
+ ]))
+ matches = self.run_test(
+ xml,
+ apk,
+ uses_libraries=['//x/y/z:foo'],
+ optional_uses_libraries=['//x/y/z:bar', '//x/y/z:qux'])
+ self.assertTrue(matches)
+
class ExtractTargetSdkVersionTest(unittest.TestCase):
@@ -256,12 +282,12 @@
"targetSdkVersion:'%s'\n"
"uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n")
- def test_targert_sdk_version_28(self):
+ def test_target_sdk_version_28(self):
xml = self.xml_tmpl % '28'
apk = self.apk_tmpl % '28'
self.run_test(xml, apk, '28')
- def test_targert_sdk_version_29(self):
+ def test_target_sdk_version_29(self):
xml = self.xml_tmpl % '29'
apk = self.apk_tmpl % '29'
self.run_test(xml, apk, '29')
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 58079aa..9847ad5 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -23,15 +23,7 @@
from xml.dom import minidom
-from manifest import android_ns
-from manifest import compare_version_gt
-from manifest import ensure_manifest_android_ns
-from manifest import find_child_with_attribute
-from manifest import get_children_with_tag
-from manifest import get_indent
-from manifest import parse_manifest
-from manifest import write_xml
-
+from manifest import *
def parse_args():
"""Parse commandline arguments."""
@@ -48,9 +40,9 @@
parser.add_argument('--library', dest='library', action='store_true',
help='manifest is for a static library')
parser.add_argument('--uses-library', dest='uses_libraries', action='append',
- help='specify additional <uses-library> tag to add. android:requred is set to true')
+ help='specify additional <uses-library> tag to add. android:required is set to true')
parser.add_argument('--optional-uses-library', dest='optional_uses_libraries', action='append',
- help='specify additional <uses-library> tag to add. android:requred is set to false')
+ help='specify additional <uses-library> tag to add. android:required is set to false')
parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true',
help='manifest is for a package built against the platform')
parser.add_argument('--logging-parent', dest='logging_parent', default='',
@@ -91,47 +83,33 @@
manifest = parse_manifest(doc)
- # Get or insert the uses-sdk element
- uses_sdk = get_children_with_tag(manifest, 'uses-sdk')
- if len(uses_sdk) > 1:
- raise RuntimeError('found multiple uses-sdk elements')
- elif len(uses_sdk) == 1:
- element = uses_sdk[0]
- else:
- element = doc.createElement('uses-sdk')
- indent = get_indent(manifest.firstChild, 1)
- manifest.insertBefore(element, manifest.firstChild)
-
- # Insert an indent before uses-sdk to line it up with the indentation of the
- # other children of the <manifest> tag.
- manifest.insertBefore(doc.createTextNode(indent), manifest.firstChild)
-
- # Get or insert the minSdkVersion attribute. If it is already present, make
- # sure it as least the requested value.
- min_attr = element.getAttributeNodeNS(android_ns, 'minSdkVersion')
- if min_attr is None:
- min_attr = doc.createAttributeNS(android_ns, 'android:minSdkVersion')
- min_attr.value = min_sdk_version
- element.setAttributeNode(min_attr)
- else:
- if compare_version_gt(min_sdk_version, min_attr.value):
+ for uses_sdk in get_or_create_uses_sdks(doc, manifest):
+ # Get or insert the minSdkVersion attribute. If it is already present, make
+ # sure it as least the requested value.
+ min_attr = uses_sdk.getAttributeNodeNS(android_ns, 'minSdkVersion')
+ if min_attr is None:
+ min_attr = doc.createAttributeNS(android_ns, 'android:minSdkVersion')
min_attr.value = min_sdk_version
-
- # Insert the targetSdkVersion attribute if it is missing. If it is already
- # present leave it as is.
- target_attr = element.getAttributeNodeNS(android_ns, 'targetSdkVersion')
- if target_attr is None:
- target_attr = doc.createAttributeNS(android_ns, 'android:targetSdkVersion')
- if library:
- # TODO(b/117122200): libraries shouldn't set targetSdkVersion at all, but
- # ManifestMerger treats minSdkVersion="Q" as targetSdkVersion="Q" if it
- # is empty. Set it to something low so that it will be overriden by the
- # main manifest, but high enough that it doesn't cause implicit
- # permissions grants.
- target_attr.value = '16'
+ uses_sdk.setAttributeNode(min_attr)
else:
- target_attr.value = target_sdk_version
- element.setAttributeNode(target_attr)
+ if compare_version_gt(min_sdk_version, min_attr.value):
+ min_attr.value = min_sdk_version
+
+ # Insert the targetSdkVersion attribute if it is missing. If it is already
+ # present leave it as is.
+ target_attr = uses_sdk.getAttributeNodeNS(android_ns, 'targetSdkVersion')
+ if target_attr is None:
+ target_attr = doc.createAttributeNS(android_ns, 'android:targetSdkVersion')
+ if library:
+ # TODO(b/117122200): libraries shouldn't set targetSdkVersion at all, but
+ # ManifestMerger treats minSdkVersion="Q" as targetSdkVersion="Q" if it
+ # is empty. Set it to something low so that it will be overridden by the
+ # main manifest, but high enough that it doesn't cause implicit
+ # permissions grants.
+ target_attr.value = '16'
+ else:
+ target_attr.value = target_sdk_version
+ uses_sdk.setAttributeNode(target_attr)
def add_logging_parent(doc, logging_parent_value):
@@ -147,37 +125,27 @@
manifest = parse_manifest(doc)
logging_parent_key = 'android.content.pm.LOGGING_PARENT'
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
+ for application in get_or_create_applications(doc, manifest):
+ indent = get_indent(application.firstChild, 2)
- indent = get_indent(application.firstChild, 2)
-
- last = application.lastChild
- if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
- last = None
-
- if not find_child_with_attribute(application, 'meta-data', android_ns,
- 'name', logging_parent_key):
- ul = doc.createElement('meta-data')
- ul.setAttributeNS(android_ns, 'android:name', logging_parent_key)
- ul.setAttributeNS(android_ns, 'android:value', logging_parent_value)
- application.insertBefore(doc.createTextNode(indent), last)
- application.insertBefore(ul, last)
last = application.lastChild
+ if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
+ last = None
- # align the closing tag with the opening tag if it's not
- # indented
- if last and last.nodeType != minidom.Node.TEXT_NODE:
- indent = get_indent(application.previousSibling, 1)
- application.appendChild(doc.createTextNode(indent))
+ if not find_child_with_attribute(application, 'meta-data', android_ns,
+ 'name', logging_parent_key):
+ ul = doc.createElement('meta-data')
+ ul.setAttributeNS(android_ns, 'android:name', logging_parent_key)
+ ul.setAttributeNS(android_ns, 'android:value', logging_parent_value)
+ application.insertBefore(doc.createTextNode(indent), last)
+ application.insertBefore(ul, last)
+ last = application.lastChild
+
+ # align the closing tag with the opening tag if it's not
+ # indented
+ if last and last.nodeType != minidom.Node.TEXT_NODE:
+ indent = get_indent(application.previousSibling, 1)
+ application.appendChild(doc.createTextNode(indent))
def add_uses_libraries(doc, new_uses_libraries, required):
@@ -192,42 +160,32 @@
"""
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
+ for application in get_or_create_applications(doc, manifest):
+ indent = get_indent(application.firstChild, 2)
- indent = get_indent(application.firstChild, 2)
+ last = application.lastChild
+ if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
+ last = None
- last = application.lastChild
- if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
- last = None
+ for name in new_uses_libraries:
+ if find_child_with_attribute(application, 'uses-library', android_ns,
+ 'name', name) is not None:
+ # If the uses-library tag of the same 'name' attribute value exists,
+ # respect it.
+ continue
- for name in new_uses_libraries:
- if find_child_with_attribute(application, 'uses-library', android_ns,
- 'name', name) is not None:
- # If the uses-library tag of the same 'name' attribute value exists,
- # respect it.
- continue
+ ul = doc.createElement('uses-library')
+ ul.setAttributeNS(android_ns, 'android:name', name)
+ ul.setAttributeNS(android_ns, 'android:required', str(required).lower())
- ul = doc.createElement('uses-library')
- ul.setAttributeNS(android_ns, 'android:name', name)
- ul.setAttributeNS(android_ns, 'android:required', str(required).lower())
+ application.insertBefore(doc.createTextNode(indent), last)
+ application.insertBefore(ul, last)
- application.insertBefore(doc.createTextNode(indent), last)
- application.insertBefore(ul, last)
-
- # align the closing tag with the opening tag if it's not
- # indented
- if application.lastChild.nodeType != minidom.Node.TEXT_NODE:
- indent = get_indent(application.previousSibling, 1)
- application.appendChild(doc.createTextNode(indent))
+ # align the closing tag with the opening tag if it's not
+ # indented
+ if application.lastChild.nodeType != minidom.Node.TEXT_NODE:
+ indent = get_indent(application.previousSibling, 1)
+ application.appendChild(doc.createTextNode(indent))
def add_uses_non_sdk_api(doc):
@@ -240,111 +198,63 @@
"""
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
-
- attr = application.getAttributeNodeNS(android_ns, 'usesNonSdkApi')
- if attr is None:
- attr = doc.createAttributeNS(android_ns, 'android:usesNonSdkApi')
- attr.value = 'true'
- application.setAttributeNode(attr)
+ for application in get_or_create_applications(doc, manifest):
+ attr = application.getAttributeNodeNS(android_ns, 'usesNonSdkApi')
+ if attr is None:
+ attr = doc.createAttributeNS(android_ns, 'android:usesNonSdkApi')
+ attr.value = 'true'
+ application.setAttributeNode(attr)
def add_use_embedded_dex(doc):
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
-
- attr = application.getAttributeNodeNS(android_ns, 'useEmbeddedDex')
- if attr is None:
- attr = doc.createAttributeNS(android_ns, 'android:useEmbeddedDex')
- attr.value = 'true'
- application.setAttributeNode(attr)
- elif attr.value != 'true':
- raise RuntimeError('existing attribute mismatches the option of --use-embedded-dex')
+ for application in get_or_create_applications(doc, manifest):
+ attr = application.getAttributeNodeNS(android_ns, 'useEmbeddedDex')
+ if attr is None:
+ attr = doc.createAttributeNS(android_ns, 'android:useEmbeddedDex')
+ attr.value = 'true'
+ application.setAttributeNode(attr)
+ elif attr.value != 'true':
+ raise RuntimeError('existing attribute mismatches the option of --use-embedded-dex')
def add_extract_native_libs(doc, extract_native_libs):
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
-
- value = str(extract_native_libs).lower()
- attr = application.getAttributeNodeNS(android_ns, 'extractNativeLibs')
- if attr is None:
- attr = doc.createAttributeNS(android_ns, 'android:extractNativeLibs')
- attr.value = value
- application.setAttributeNode(attr)
- elif attr.value != value:
- raise RuntimeError('existing attribute extractNativeLibs="%s" conflicts with --extract-native-libs="%s"' %
- (attr.value, value))
+ for application in get_or_create_applications(doc, manifest):
+ value = str(extract_native_libs).lower()
+ attr = application.getAttributeNodeNS(android_ns, 'extractNativeLibs')
+ if attr is None:
+ attr = doc.createAttributeNS(android_ns, 'android:extractNativeLibs')
+ attr.value = value
+ application.setAttributeNode(attr)
+ elif attr.value != value:
+ raise RuntimeError('existing attribute extractNativeLibs="%s" conflicts with --extract-native-libs="%s"' %
+ (attr.value, value))
def set_has_code_to_false(doc):
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
+ for application in get_or_create_applications(doc, manifest):
+ attr = application.getAttributeNodeNS(android_ns, 'hasCode')
+ if attr is not None:
+ # Do nothing if the application already has a hasCode attribute.
+ continue
+ attr = doc.createAttributeNS(android_ns, 'android:hasCode')
+ attr.value = 'false'
+ application.setAttributeNode(attr)
- attr = application.getAttributeNodeNS(android_ns, 'hasCode')
- if attr is not None:
- # Do nothing if the application already has a hasCode attribute.
- return
- attr = doc.createAttributeNS(android_ns, 'android:hasCode')
- attr.value = 'false'
- application.setAttributeNode(attr)
def set_test_only_flag_to_true(doc):
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
+ for application in get_or_create_applications(doc, manifest):
+ attr = application.getAttributeNodeNS(android_ns, 'testOnly')
+ if attr is not None:
+ # Do nothing If the application already has a testOnly attribute.
+ continue
+ attr = doc.createAttributeNS(android_ns, 'android:testOnly')
+ attr.value = 'true'
+ application.setAttributeNode(attr)
- attr = application.getAttributeNodeNS(android_ns, 'testOnly')
- if attr is not None:
- # Do nothing If the application already has a testOnly attribute.
- return
- attr = doc.createAttributeNS(android_ns, 'android:testOnly')
- attr.value = 'true'
- application.setAttributeNode(attr)
def set_max_sdk_version(doc, max_sdk_version):
"""Replace the maxSdkVersion attribute value for permission and
@@ -364,6 +274,7 @@
if max_attr and max_attr.value == 'current':
max_attr.value = max_sdk_version
+
def override_placeholder_version(doc, new_version):
"""Replace the versionCode attribute value if it\'s currently
set to the placeholder version of 0.
@@ -374,9 +285,10 @@
"""
manifest = parse_manifest(doc)
version = manifest.getAttribute("android:versionCode")
- if (version == '0'):
+ if version == '0':
manifest.setAttribute("android:versionCode", new_version)
+
def main():
"""Program entry point."""
try:
@@ -427,5 +339,6 @@
print('error: ' + str(err), file=sys.stderr)
sys.exit(-1)
+
if __name__ == '__main__':
main()
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index 0a62b10..e4d8dc3 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -20,12 +20,13 @@
import sys
import unittest
from xml.dom import minidom
-import xml.etree.ElementTree as ET
+import xml.etree.ElementTree as ElementTree
import manifest_fixer
sys.dont_write_bytecode = True
+
class CompareVersionGtTest(unittest.TestCase):
"""Unit tests for compare_version_gt function."""
@@ -69,25 +70,24 @@
'%s'
'</manifest>\n')
- # pylint: disable=redefined-builtin
- def uses_sdk(self, min=None, target=None, extra=''):
+ def uses_sdk(self, min_sdk=None, target_sdk=None, extra=''):
attrs = ''
- if min:
- attrs += ' android:minSdkVersion="%s"' % (min)
- if target:
- attrs += ' android:targetSdkVersion="%s"' % (target)
+ if min_sdk:
+ attrs += ' android:minSdkVersion="%s"' % min_sdk
+ if target_sdk:
+ attrs += ' android:targetSdkVersion="%s"' % target_sdk
if extra:
attrs += ' ' + extra
- return ' <uses-sdk%s/>\n' % (attrs)
+ return ' <uses-sdk%s/>\n' % attrs
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def test_no_uses_sdk(self):
"""Tests inserting a uses-sdk element into a manifest."""
manifest_input = self.manifest_tmpl % ''
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
@@ -95,7 +95,7 @@
"""Tests inserting a minSdkVersion attribute into a uses-sdk element."""
manifest_input = self.manifest_tmpl % ' <uses-sdk extra="foo"/>\n'
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28',
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28',
extra='extra="foo"')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
@@ -103,64 +103,64 @@
def test_raise_min(self):
"""Tests inserting a minSdkVersion attribute into a uses-sdk element."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
def test_raise(self):
"""Tests raising a minSdkVersion attribute."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
def test_no_raise_min(self):
"""Tests a minSdkVersion that doesn't need raising."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='28')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='28')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27')
output = self.raise_min_sdk_version_test(manifest_input, '27', '27', False)
self.assert_xml_equal(output, expected)
def test_raise_codename(self):
"""Tests raising a minSdkVersion attribute to a codename."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='28')
- expected = self.manifest_tmpl % self.uses_sdk(min='P', target='P')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='28')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='P', target_sdk='P')
output = self.raise_min_sdk_version_test(manifest_input, 'P', 'P', False)
self.assert_xml_equal(output, expected)
def test_no_raise_codename(self):
"""Tests a minSdkVersion codename that doesn't need raising."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='P')
- expected = self.manifest_tmpl % self.uses_sdk(min='P', target='28')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='P')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='P', target_sdk='28')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
def test_target(self):
"""Tests an existing targetSdkVersion is preserved."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='26', target='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='26', target_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False)
self.assert_xml_equal(output, expected)
def test_no_target(self):
"""Tests inserting targetSdkVersion when minSdkVersion exists."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='29')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='29')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False)
self.assert_xml_equal(output, expected)
def test_target_no_min(self):
""""Tests inserting targetSdkVersion when minSdkVersion exists."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(target='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(target_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False)
self.assert_xml_equal(output, expected)
@@ -168,23 +168,23 @@
"""Tests inserting targetSdkVersion when minSdkVersion does not exist."""
manifest_input = self.manifest_tmpl % ''
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='29')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='29')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False)
self.assert_xml_equal(output, expected)
def test_library_no_target(self):
"""Tests inserting targetSdkVersion when minSdkVersion exists."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='16')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='16')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True)
self.assert_xml_equal(output, expected)
def test_library_target_no_min(self):
"""Tests inserting targetSdkVersion when minSdkVersion exists."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(target='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(target_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True)
self.assert_xml_equal(output, expected)
@@ -192,7 +192,7 @@
"""Tests inserting targetSdkVersion when minSdkVersion does not exist."""
manifest_input = self.manifest_tmpl % ''
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='16')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='16')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True)
self.assert_xml_equal(output, expected)
@@ -228,12 +228,24 @@
self.assert_xml_equal(output, expected)
+ def test_multiple_uses_sdks(self):
+ """Tests a manifest that contains multiple uses_sdks elements."""
+
+ manifest_input = self.manifest_tmpl % (
+ ' <uses-sdk android:featureFlag="foo" android:minSdkVersion="21" />\n'
+ ' <uses-sdk android:featureFlag="!foo" android:minSdkVersion="22" />\n')
+ expected = self.manifest_tmpl % (
+ ' <uses-sdk android:featureFlag="foo" android:minSdkVersion="28" android:targetSdkVersion="28" />\n'
+ ' <uses-sdk android:featureFlag="!foo" android:minSdkVersion="28" android:targetSdkVersion="28" />\n')
+
+ output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
+ self.assert_xml_equal(output, expected)
class AddLoggingParentTest(unittest.TestCase):
"""Unit tests for add_logging_parent function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def add_logging_parent_test(self, input_manifest, logging_parent=None):
doc = minidom.parseString(input_manifest)
@@ -253,8 +265,8 @@
attrs = ''
if logging_parent:
meta_text = ('<meta-data android:name="android.content.pm.LOGGING_PARENT" '
- 'android:value="%s"/>\n') % (logging_parent)
- attrs += ' <application>\n %s </application>\n' % (meta_text)
+ 'android:value="%s"/>\n') % logging_parent
+ attrs += ' <application>\n %s </application>\n' % meta_text
return attrs
@@ -277,7 +289,7 @@
"""Unit tests for add_uses_libraries function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest, new_uses_libraries):
doc = minidom.parseString(input_manifest)
@@ -289,18 +301,16 @@
manifest_tmpl = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
- ' <application>\n'
'%s'
- ' </application>\n'
'</manifest>\n')
def uses_libraries(self, name_required_pairs):
- ret = ''
+ ret = ' <application>\n'
for name, required in name_required_pairs:
ret += (
' <uses-library android:name="%s" android:required="%s"/>\n'
) % (name, required)
-
+ ret += ' </application>\n'
return ret
def test_empty(self):
@@ -361,12 +371,23 @@
output = self.run_test(manifest_input, ['foo', 'bar'])
self.assert_xml_equal(output, expected)
+ def test_multiple_application(self):
+ """When there are multiple applications, the libs are added to each."""
+ manifest_input = self.manifest_tmpl % (
+ self.uses_libraries([('foo', 'false')]) +
+ self.uses_libraries([('bar', 'false')]))
+ expected = self.manifest_tmpl % (
+ self.uses_libraries([('foo', 'false'), ('bar', 'true')]) +
+ self.uses_libraries([('bar', 'false'), ('foo', 'true')]))
+ output = self.run_test(manifest_input, ['foo', 'bar'])
+ self.assert_xml_equal(output, expected)
+
class AddUsesNonSdkApiTest(unittest.TestCase):
"""Unit tests for add_uses_libraries function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest):
doc = minidom.parseString(input_manifest)
@@ -378,11 +399,11 @@
manifest_tmpl = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
- ' <application%s/>\n'
+ ' %s\n'
'</manifest>\n')
def uses_non_sdk_api(self, value):
- return ' android:usesNonSdkApi="true"' if value else ''
+ return '<application %s/>' % ('android:usesNonSdkApi="true"' if value else '')
def test_set_true(self):
"""Empty new_uses_libraries must not touch the manifest."""
@@ -398,12 +419,19 @@
output = self.run_test(manifest_input)
self.assert_xml_equal(output, expected)
+ def test_multiple_applications(self):
+ """new_uses_libraries must be added to all applications."""
+ manifest_input = self.manifest_tmpl % (self.uses_non_sdk_api(True) + self.uses_non_sdk_api(False))
+ expected = self.manifest_tmpl % (self.uses_non_sdk_api(True) + self.uses_non_sdk_api(True))
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
class UseEmbeddedDexTest(unittest.TestCase):
"""Unit tests for add_use_embedded_dex function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest):
doc = minidom.parseString(input_manifest)
@@ -415,14 +443,14 @@
manifest_tmpl = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
- ' <application%s/>\n'
+ ' %s\n'
'</manifest>\n')
def use_embedded_dex(self, value):
- return ' android:useEmbeddedDex="%s"' % value
+ return '<application android:useEmbeddedDex="%s" />' % value
def test_manifest_with_undeclared_preference(self):
- manifest_input = self.manifest_tmpl % ''
+ manifest_input = self.manifest_tmpl % '<application/>'
expected = self.manifest_tmpl % self.use_embedded_dex('true')
output = self.run_test(manifest_input)
self.assert_xml_equal(output, expected)
@@ -437,12 +465,24 @@
manifest_input = self.manifest_tmpl % self.use_embedded_dex('false')
self.assertRaises(RuntimeError, self.run_test, manifest_input)
+ def test_multiple_applications(self):
+ manifest_input = self.manifest_tmpl % (
+ self.use_embedded_dex('true') +
+ '<application/>'
+ )
+ expected = self.manifest_tmpl % (
+ self.use_embedded_dex('true') +
+ self.use_embedded_dex('true')
+ )
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
class AddExtractNativeLibsTest(unittest.TestCase):
"""Unit tests for add_extract_native_libs function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest, value):
doc = minidom.parseString(input_manifest)
@@ -454,20 +494,20 @@
manifest_tmpl = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
- ' <application%s/>\n'
+ ' %s\n'
'</manifest>\n')
def extract_native_libs(self, value):
- return ' android:extractNativeLibs="%s"' % value
+ return '<application android:extractNativeLibs="%s" />' % value
def test_set_true(self):
- manifest_input = self.manifest_tmpl % ''
+ manifest_input = self.manifest_tmpl % '<application/>'
expected = self.manifest_tmpl % self.extract_native_libs('true')
output = self.run_test(manifest_input, True)
self.assert_xml_equal(output, expected)
def test_set_false(self):
- manifest_input = self.manifest_tmpl % ''
+ manifest_input = self.manifest_tmpl % '<application/>'
expected = self.manifest_tmpl % self.extract_native_libs('false')
output = self.run_test(manifest_input, False)
self.assert_xml_equal(output, expected)
@@ -482,12 +522,18 @@
manifest_input = self.manifest_tmpl % self.extract_native_libs('true')
self.assertRaises(RuntimeError, self.run_test, manifest_input, False)
+ def test_multiple_applications(self):
+ manifest_input = self.manifest_tmpl % (self.extract_native_libs('true') + '<application/>')
+ expected = self.manifest_tmpl % (self.extract_native_libs('true') + self.extract_native_libs('true'))
+ output = self.run_test(manifest_input, True)
+ self.assert_xml_equal(output, expected)
+
class AddNoCodeApplicationTest(unittest.TestCase):
"""Unit tests for set_has_code_to_false function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest):
doc = minidom.parseString(input_manifest)
@@ -515,7 +561,7 @@
self.assert_xml_equal(output, expected)
def test_has_application_has_code_false(self):
- """ Do nothing if there's already an application elemeent. """
+ """ Do nothing if there's already an application element. """
manifest_input = self.manifest_tmpl % ' <application android:hasCode="false"/>\n'
output = self.run_test(manifest_input)
self.assert_xml_equal(output, manifest_input)
@@ -527,12 +573,25 @@
output = self.run_test(manifest_input)
self.assert_xml_equal(output, manifest_input)
+ def test_multiple_applications(self):
+ """ Apply to all applications """
+ manifest_input = self.manifest_tmpl % (
+ ' <application android:hasCode="true" />\n' +
+ ' <application android:hasCode="false" />\n' +
+ ' <application/>\n')
+ expected = self.manifest_tmpl % (
+ ' <application android:hasCode="true" />\n' +
+ ' <application android:hasCode="false" />\n' +
+ ' <application android:hasCode="false" />\n')
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
class AddTestOnlyApplicationTest(unittest.TestCase):
"""Unit tests for set_test_only_flag_to_true function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest):
doc = minidom.parseString(input_manifest)
@@ -571,12 +630,26 @@
output = self.run_test(manifest_input)
self.assert_xml_equal(output, manifest_input)
+ def test_multiple_applications(self):
+ manifest_input = self.manifest_tmpl % (
+ ' <application android:testOnly="true" />\n' +
+ ' <application android:testOnly="false" />\n' +
+ ' <application/>\n'
+ )
+ expected = self.manifest_tmpl % (
+ ' <application android:testOnly="true" />\n' +
+ ' <application android:testOnly="false" />\n' +
+ ' <application android:testOnly="true" />\n'
+ )
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
class SetMaxSdkVersionTest(unittest.TestCase):
"""Unit tests for set_max_sdk_version function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest, max_sdk_version):
doc = minidom.parseString(input_manifest)
@@ -591,15 +664,15 @@
'%s'
'</manifest>\n')
- def permission(self, max=None):
- if max is None:
+ def permission(self, max_sdk=None):
+ if max_sdk is None:
return ' <permission/>'
- return ' <permission android:maxSdkVersion="%s"/>\n' % max
+ return ' <permission android:maxSdkVersion="%s"/>\n' % max_sdk
- def uses_permission(self, max=None):
- if max is None:
+ def uses_permission(self, max_sdk=None):
+ if max_sdk is None:
return ' <uses-permission/>'
- return ' <uses-permission android:maxSdkVersion="%s"/>\n' % max
+ return ' <uses-permission android:maxSdkVersion="%s"/>\n' % max_sdk
def test_permission_no_max_sdk_version(self):
"""Tests if permission has no maxSdkVersion attribute"""
@@ -643,11 +716,12 @@
output = self.run_test(manifest_input, '9000')
self.assert_xml_equal(output, expected)
+
class OverrideDefaultVersionTest(unittest.TestCase):
"""Unit tests for override_default_version function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest, version):
doc = minidom.parseString(input_manifest)
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 8b994eb..39c8123 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -204,7 +204,19 @@
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core1.jar
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core2.jar
`),
- snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotWithoutSource, android.GroupFixturePreparers(
+ preparerForSnapshot,
+ // Flag ART prebuilts
+ android.FixtureMergeMockFs(android.MockFS{
+ "apex_contributions/Android.bp": []byte(`
+ apex_contributions {
+ name: "prebuilt_art_contributions",
+ contents: ["prebuilt_com.android.art"],
+ api_domain: "com.android.art",
+ }
+ `)}),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"),
+ )),
// Check the behavior of the snapshot without the source.
snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
@@ -212,8 +224,8 @@
checkBootJarsPackageCheckRule(t, result,
append(
[]string{
- "out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
- "out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_com.android.art/deapexer/javalib/core1.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_com.android.art/deapexer/javalib/core2.jar",
"out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar",
},
java.ApexBootJarDexJarPaths...,
diff --git a/soong_ui.bash b/soong_ui.bash
index 7737880..2f688ef 100755
--- a/soong_ui.bash
+++ b/soong_ui.bash
@@ -26,6 +26,7 @@
source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../make/shell_utils.sh
require_top
+setup_cog_env_if_needed
# Save the current PWD for use in soong_ui
export ORIGINAL_PWD=${PWD}
diff --git a/sysprop/Android.bp b/sysprop/Android.bp
index a00a5e4..22cba3b 100644
--- a/sysprop/Android.bp
+++ b/sysprop/Android.bp
@@ -21,4 +21,6 @@
"sysprop_test.go",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/testing/code_metadata_internal_proto/Android.bp b/testing/code_metadata_internal_proto/Android.bp
index a534cc2..396e44f 100644
--- a/testing/code_metadata_internal_proto/Android.bp
+++ b/testing/code_metadata_internal_proto/Android.bp
@@ -20,10 +20,14 @@
name: "soong-testing-code_metadata_internal_proto",
pkgPath: "android/soong/testing/code_metadata_internal_proto",
deps: [
- "golang-protobuf-reflect-protoreflect",
- "golang-protobuf-runtime-protoimpl",
- ],
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
srcs: [
"code_metadata_internal.pb.go",
],
+ visibility: [
+ "//build/make/tools/metadata",
+ "//build/soong:__subpackages__",
+ ],
}
diff --git a/testing/code_metadata_proto/Android.bp b/testing/code_metadata_proto/Android.bp
index f07efff..ae41d4a 100644
--- a/testing/code_metadata_proto/Android.bp
+++ b/testing/code_metadata_proto/Android.bp
@@ -26,6 +26,7 @@
srcs: [
"code_metadata.pb.go",
],
+ visibility: ["//build/make/tools/metadata"],
}
python_library_host {
@@ -40,4 +41,5 @@
proto: {
canonical_path_from_root: false,
},
+ visibility: ["//tools/asuite/team_build_scripts"],
}
diff --git a/testing/test_spec_proto/Android.bp b/testing/test_spec_proto/Android.bp
index d5ad70b..1070d1a 100644
--- a/testing/test_spec_proto/Android.bp
+++ b/testing/test_spec_proto/Android.bp
@@ -26,6 +26,11 @@
srcs: [
"test_spec.pb.go",
],
+ visibility: [
+ "//build/make/tools/metadata",
+ "//build/soong:__subpackages__",
+ "//vendor:__subpackages__",
+ ],
}
python_library_host {
@@ -40,4 +45,5 @@
proto: {
canonical_path_from_root: false,
},
+ visibility: ["//tools/asuite/team_build_scripts"],
}
diff --git a/tests/build_action_caching_test.sh b/tests/build_action_caching_test.sh
new file mode 100755
index 0000000..8ecd037
--- /dev/null
+++ b/tests/build_action_caching_test.sh
@@ -0,0 +1,190 @@
+#!/bin/bash -u
+
+set -o pipefail
+
+# Test that the mk and ninja files generated by Soong don't change if some
+# incremental modules are restored from cache.
+
+OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)"
+
+echo ${OUTPUT_DIR}
+
+function cleanup {
+ rm -rf "${OUTPUT_DIR}"
+}
+trap cleanup EXIT
+
+function run_soong_build {
+ USE_RBE=false TARGET_PRODUCT=aosp_arm TARGET_RELEASE=trunk_staging TARGET_BUILD_VARIANT=userdebug build/soong/soong_ui.bash --make-mode "$@" nothing
+}
+
+function run_soong_clean {
+ build/soong/soong_ui.bash --make-mode clean
+}
+
+function assert_files_equal {
+ if [ $# -ne 2 ]; then
+ echo "Usage: assert_files_equal file1 file2"
+ exit 1
+ fi
+
+ if ! cmp -s "$1" "$2"; then
+ echo "Files are different: $1 $2"
+ exit 1
+ fi
+}
+
+function compare_mtimes() {
+ if [ $# -ne 2 ]; then
+ echo "Usage: compare_mtimes file1 file2"
+ exit 1
+ fi
+
+ file1_mtime=$(stat -c '%Y' $1)
+ file2_mtime=$(stat -c '%Y' $2)
+
+ if [ "$file1_mtime" -eq "$file2_mtime" ]; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+function test_build_action_restoring() {
+ local test_dir="${OUTPUT_DIR}/test_build_action_restoring"
+ mkdir -p ${test_dir}
+ run_soong_clean
+ cat > ${test_dir}/Android.bp <<'EOF'
+python_binary_host {
+ name: "my_little_binary_host",
+ srcs: ["my_little_binary_host.py"],
+}
+EOF
+ touch ${test_dir}/my_little_binary_host.py
+ run_soong_build --incremental-build-actions
+ local dir_before="${test_dir}/before"
+ mkdir -p ${dir_before}
+ cp -pr out/soong/build_aosp_arm_ninja_incremental out/soong/*.mk out/soong/build.aosp_arm*.ninja ${test_dir}/before
+ # add a comment to the bp file, this should force a new analysis but no module
+ # should be really impacted, so all the incremental modules should be skipped.
+ cat >> ${test_dir}/Android.bp <<'EOF'
+// new comments
+EOF
+ run_soong_build --incremental-build-actions
+ local dir_after="${test_dir}/after"
+ mkdir -p ${dir_after}
+ cp -pr out/soong/build_aosp_arm_ninja_incremental out/soong/*.mk out/soong/build.aosp_arm*.ninja ${test_dir}/after
+
+ compare_incremental_files $dir_before $dir_after
+ rm -rf "$test_dir"
+ echo "test_build_action_restoring test passed"
+}
+
+function test_incremental_build_parity() {
+ local test_dir="${OUTPUT_DIR}/test_incremental_build_parity"
+ run_soong_clean
+ run_soong_build
+ local dir_before="${test_dir}/before"
+ mkdir -p ${dir_before}
+ cp -pr out/soong/*.mk out/soong/build.aosp_arm*.ninja ${test_dir}/before
+
+ # Now run clean build with incremental enabled
+ run_soong_clean
+ run_soong_build --incremental-build-actions
+ local dir_after="${test_dir}/after"
+ mkdir -p ${dir_after}
+ cp -pr out/soong/build_aosp_arm_ninja_incremental out/soong/*.mk out/soong/build.aosp_arm*.ninja ${test_dir}/after
+
+ compare_files_parity $dir_before $dir_after
+ rm -rf "$test_dir"
+ echo "test_incremental_build_parity test passed"
+}
+
+function compare_files_parity() {
+ local dir_before=$1; shift
+ local dir_after=$1; shift
+ count=0
+ for file_before in ${dir_before}/*.mk; do
+ file_after="${dir_after}/$(basename "$file_before")"
+ assert_files_equal $file_before $file_after
+ ((count++))
+ done
+ echo "Compared $count mk files"
+
+ combined_before_file="${dir_before}/combined_files.ninja"
+ count=0
+ for file in ${dir_before}/build.aosp_arm.*.ninja; do
+ cat $file >> $combined_before_file
+ ((count++))
+ done
+ echo "Combined $count ninja files from normal build"
+
+ combined_after_file="${dir_after}/combined_files.ninja"
+ count=0
+ for file in ${dir_after}/build.aosp_arm.*.ninja; do
+ cat $file >> $combined_after_file
+ ((count++))
+ done
+ echo "Combined $count ninja files from incremental build"
+
+ combined_incremental_ninjas="${dir_after}/combined_incremental_files.ninja"
+ count=0
+ for file in ${dir_after}/build_aosp_arm_ninja_incremental/*.ninja; do
+ cat $file >> $combined_incremental_ninjas
+ ((count++))
+ done
+ echo "Combined $count incremental ninja files"
+
+ cat $combined_incremental_ninjas >> $combined_after_file
+ sort $combined_after_file -o $combined_after_file
+ sort $combined_before_file -o $combined_before_file
+ assert_files_equal $combined_before_file $combined_after_file
+}
+
+function compare_incremental_files() {
+ local dir_before=$1; shift
+ local dir_after=$1; shift
+ count=0
+ for file_before in ${dir_before}/*.ninja; do
+ file_after="${dir_after}/$(basename "$file_before")"
+ assert_files_equal $file_before $file_after
+ compare_mtimes $file_before $file_after
+ if [ $? -ne 0 ]; then
+ echo "Files have identical mtime: $file_before $file_after"
+ exit 1
+ fi
+ ((count++))
+ done
+ echo "Compared $count ninja files"
+
+ count=0
+ for file_before in ${dir_before}/*.mk; do
+ file_after="${dir_after}/$(basename "$file_before")"
+ assert_files_equal $file_before $file_after
+ compare_mtimes $file_before $file_after
+ # mk files shouldn't be regenerated
+ if [ $? -ne 1 ]; then
+ echo "Files have different mtimes: $file_before $file_after"
+ exit 1
+ fi
+ ((count++))
+ done
+ echo "Compared $count mk files"
+
+ count=0
+ for file_before in ${dir_before}/build_aosp_arm_ninja_incremental/*.ninja; do
+ file_after="${dir_after}/build_aosp_arm_ninja_incremental/$(basename "$file_before")"
+ assert_files_equal $file_before $file_after
+ compare_mtimes $file_before $file_after
+ # ninja files of skipped modules shouldn't be regenerated
+ if [ $? -ne 1 ]; then
+ echo "Files have different mtimes: $file_before $file_after"
+ exit 1
+ fi
+ ((count++))
+ done
+ echo "Compared $count incremental ninja files"
+}
+
+test_incremental_build_parity
+test_build_action_restoring
diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go
index ef18131..7a04c19 100644
--- a/tradefed_modules/test_module_config.go
+++ b/tradefed_modules/test_module_config.go
@@ -242,6 +242,7 @@
entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", m.provider.IsUnitTest)
entries.AddCompatibilityTestSuites(m.tradefedProperties.Test_suites...)
+ entries.AddStrings("LOCAL_HOST_REQUIRED_MODULES", m.provider.HostRequiredModuleNames...)
// The app_prebuilt_internal.mk files try create a copy of the OutputFile as an .apk.
// Normally, this copies the "package.apk" from the intermediate directory here.
diff --git a/tradefed_modules/test_module_config_test.go b/tradefed_modules/test_module_config_test.go
index 1510a03..f76a152 100644
--- a/tradefed_modules/test_module_config_test.go
+++ b/tradefed_modules/test_module_config_test.go
@@ -40,6 +40,7 @@
name: "base",
sdk_version: "current",
data: [":HelperApp", "data/testfile"],
+ host_required: ["other-module"],
test_suites: ["general-tests"],
}
@@ -80,6 +81,7 @@
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{})
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_REQUIRED_MODULES"], []string{"base"})
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_HOST_REQUIRED_MODULES"], []string{"other-module"})
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_CERTIFICATE"], []string{"build/make/target/product/security/testkey.x509.pem"})
android.AssertStringEquals(t, "", entries.Class, "APPS")
diff --git a/ui/build/config.go b/ui/build/config.go
index f02222e..851a22a 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -54,6 +54,16 @@
rbeRandPrefix = rand.Intn(1000)
}
+// Which builder are we using?
+type ninjaCommandType = int
+
+const (
+ _ = iota
+ NINJA_NINJA
+ NINJA_N2
+ NINJA_SISO
+)
+
type Config struct{ *configImpl }
type configImpl struct {
@@ -123,9 +133,8 @@
// could consider merging them.
moduleDebugFile string
- // Whether to use n2 instead of ninja. This is controlled with the
- // environment variable SOONG_USE_N2
- useN2 bool
+ // Which builder are we using
+ ninjaCommand ninjaCommandType
}
type NinjaWeightListSource uint
@@ -288,8 +297,16 @@
ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
}
- if os.Getenv("SOONG_USE_N2") == "true" {
- ret.useN2 = true
+ ret.ninjaCommand = NINJA_NINJA
+ switch os.Getenv("SOONG_NINJA") {
+ case "n2":
+ ret.ninjaCommand = NINJA_N2
+ case "siso":
+ ret.ninjaCommand = NINJA_SISO
+ default:
+ if os.Getenv("SOONG_USE_N2") == "true" {
+ ret.ninjaCommand = NINJA_N2
+ }
}
ret.environ.Unset(
@@ -349,7 +366,8 @@
// We read it here already, don't let others share in the fun
"GENERATE_SOONG_DEBUG",
- // Use config.useN2 instead.
+ // Use config.ninjaCommand instead.
+ "SOONG_NINJA",
"SOONG_USE_N2",
)
@@ -1375,8 +1393,10 @@
// Perform a log directory cleanup only when the log directory
// is auto created by the build rather than user-specified.
for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
- if _, ok := c.environ.Get(f); ok {
- return false
+ if v, ok := c.environ.Get(f); ok {
+ if v != c.rbeTmpDir() {
+ return false
+ }
}
}
return true
@@ -1641,6 +1661,12 @@
return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
}
+func (c *configImpl) SisoBin() string {
+ path := c.PrebuiltBuildTool("siso")
+ // Use musl instead of glibc because glibc on the build server is old and has bugs
+ return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
+}
+
func (c *configImpl) PrebuiltBuildTool(name string) string {
if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
if sanitize := strings.Fields(v); inList("address", sanitize) {
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 4e3e544..def0783 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -49,14 +49,10 @@
nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
defer nr.Close()
- executable := config.NinjaBin()
- args := []string{
- "-d", "keepdepfile",
- "-d", "keeprsp",
- "-d", "stats",
- "--frontend_file", fifo,
- }
- if config.useN2 {
+ var executable string
+ var args []string
+ switch config.ninjaCommand {
+ case NINJA_N2:
executable = config.N2Bin()
args = []string{
"-d", "trace",
@@ -66,8 +62,31 @@
//"-d", "stats",
"--frontend-file", fifo,
}
+ case NINJA_SISO:
+ executable = config.SisoBin()
+ args = []string{
+ "ninja",
+ "--log_dir", config.SoongOutDir(),
+ // TODO: implement these features, or remove them.
+ //"-d", "trace",
+ //"-d", "keepdepfile",
+ //"-d", "keeprsp",
+ //"-d", "stats",
+ //"--frontend-file", fifo,
+ }
+ default:
+ // NINJA_NINJA is the default.
+ executable = config.NinjaBin()
+ args = []string{
+ "-d", "keepdepfile",
+ "-d", "keeprsp",
+ "-d", "stats",
+ "--frontend_file", fifo,
+ "-o", "usesphonyoutputs=yes",
+ "-w", "dupbuild=err",
+ "-w", "missingdepfile=err",
+ }
}
-
args = append(args, config.NinjaArgs()...)
var parallel int
@@ -83,17 +102,10 @@
args = append(args, "-f", config.CombinedNinjaFile())
- if !config.useN2 {
- args = append(args,
- "-o", "usesphonyoutputs=yes",
- "-w", "dupbuild=err",
- "-w", "missingdepfile=err")
- }
-
if !config.BuildBrokenMissingOutputs() {
// Missing outputs will be treated as errors.
// BUILD_BROKEN_MISSING_OUTPUTS can be used to bypass this check.
- if !config.useN2 {
+ if config.ninjaCommand != NINJA_N2 {
args = append(args,
"-w", "missingoutfile=err",
)
@@ -110,21 +122,18 @@
cmd.Environment.AppendFromKati(config.KatiEnvFile())
}
- switch config.NinjaWeightListSource() {
- case NINJA_LOG:
- if !config.useN2 {
+ // TODO(b/346806126): implement this for the other ninjaCommand values.
+ if config.ninjaCommand == NINJA_NINJA {
+ switch config.NinjaWeightListSource() {
+ case NINJA_LOG:
cmd.Args = append(cmd.Args, "-o", "usesninjalogasweightlist=yes")
- }
- case EVENLY_DISTRIBUTED:
- // pass empty weight list means ninja considers every tasks's weight as 1(default value).
- if !config.useN2 {
+ case EVENLY_DISTRIBUTED:
+ // pass empty weight list means ninja considers every tasks's weight as 1(default value).
cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null")
- }
- case EXTERNAL_FILE:
- fallthrough
- case HINT_FROM_SOONG:
- // The weight list is already copied/generated.
- if !config.useN2 {
+ case EXTERNAL_FILE:
+ fallthrough
+ case HINT_FROM_SOONG:
+ // The weight list is already copied/generated.
ninjaWeightListPath := filepath.Join(config.OutDir(), ninjaWeightListFileName)
cmd.Args = append(cmd.Args, "-o", "usesweightlist="+ninjaWeightListPath)
}
@@ -227,6 +236,8 @@
// We don't want this build broken flag to cause reanalysis, so allow it through to the
// actions.
"BUILD_BROKEN_INCORRECT_PARTITION_IMAGES",
+ // Do not do reanalysis just because we changed ninja commands.
+ "SOONG_NINJA",
"SOONG_USE_N2",
"RUST_BACKTRACE",
"RUST_LOG",
@@ -235,8 +246,11 @@
cmd.Environment.Set("DIST_DIR", config.DistDir())
cmd.Environment.Set("SHELL", "/bin/bash")
- if config.useN2 {
+ switch config.ninjaCommand {
+ case NINJA_N2:
cmd.Environment.Set("RUST_BACKTRACE", "1")
+ default:
+ // Only set RUST_BACKTRACE for n2.
}
// Print the environment variables that Ninja is operating in.
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 97bc997..41425ac 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -27,6 +27,7 @@
"strings"
"sync"
"sync/atomic"
+ "syscall"
"time"
"android/soong/ui/tracer"
@@ -588,19 +589,11 @@
nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
defer nr.Close()
- ninjaArgs := []string{
- "-d", "keepdepfile",
- "-d", "stats",
- "-o", "usesphonyoutputs=yes",
- "-o", "preremoveoutputs=yes",
- "-w", "dupbuild=err",
- "-w", "outputdir=err",
- "-w", "missingoutfile=err",
- "-j", strconv.Itoa(config.Parallel()),
- "--frontend_file", fifo,
- "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
- }
- if config.useN2 {
+ var ninjaCmd string
+ var ninjaArgs []string
+ switch config.ninjaCommand {
+ case NINJA_N2:
+ ninjaCmd = config.N2Bin()
ninjaArgs = []string{
// TODO: implement these features, or remove them.
//"-d", "keepdepfile",
@@ -615,6 +608,39 @@
"--frontend-file", fifo,
"-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
}
+ case NINJA_SISO:
+ ninjaCmd = config.SisoBin()
+ ninjaArgs = []string{
+ "ninja",
+ // TODO: implement these features, or remove them.
+ //"-d", "keepdepfile",
+ //"-d", "stats",
+ //"-o", "usesphonyoutputs=yes",
+ //"-o", "preremoveoutputs=yes",
+ //"-w", "dupbuild=err",
+ //"-w", "outputdir=err",
+ //"-w", "missingoutfile=err",
+ "-v",
+ "-j", strconv.Itoa(config.Parallel()),
+ //"--frontend-file", fifo,
+ "--log_dir", config.SoongOutDir(),
+ "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+ }
+ default:
+ // NINJA_NINJA is the default.
+ ninjaCmd = config.NinjaBin()
+ ninjaArgs = []string{
+ "-d", "keepdepfile",
+ "-d", "stats",
+ "-o", "usesphonyoutputs=yes",
+ "-o", "preremoveoutputs=yes",
+ "-w", "dupbuild=err",
+ "-w", "outputdir=err",
+ "-w", "missingoutfile=err",
+ "-j", strconv.Itoa(config.Parallel()),
+ "--frontend_file", fifo,
+ "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+ }
}
if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok {
@@ -623,10 +649,6 @@
}
ninjaArgs = append(ninjaArgs, targets...)
- ninjaCmd := config.NinjaBin()
- if config.useN2 {
- ninjaCmd = config.N2Bin()
- }
cmd := Command(ctx, config, "soong bootstrap",
ninjaCmd, ninjaArgs...)
@@ -759,7 +781,7 @@
hasNewDep := false
for _, dep := range cachedGlob.Deps {
info, err := os.Stat(dep)
- if errors.Is(err, fs.ErrNotExist) {
+ if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) {
hasNewDep = true
break
} else if err != nil {
diff --git a/zip/cmd/Android.bp b/zip/cmd/Android.bp
index 43bf232..16c3f69 100644
--- a/zip/cmd/Android.bp
+++ b/zip/cmd/Android.bp
@@ -24,4 +24,6 @@
srcs: [
"main.go",
],
+ // Used by genrules
+ visibility: ["//visibility:public"],
}