Merge "Pass the common sources rsp file as `--common_srcs` to extractor" into main
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/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/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..942727a 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -396,20 +396,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 +418,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 +535,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 +566,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 +618,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 +638,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 +646,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 +654,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 +773,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_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/module.go b/android/module.go
index 47fdc23..f5a611c 100644
--- a/android/module.go
+++ b/android/module.go
@@ -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.
@@ -1221,7 +1215,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 +1340,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
}
@@ -2204,9 +2206,14 @@
return proptools.Bool(m.commonProperties.Native_bridge_supported)
}
+type ConfigContext interface {
+ Config() Config
+}
+
type ConfigurableEvaluatorContext interface {
Config() Config
OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+ HasMutatorFinished(mutatorName string) bool
}
type configurationEvalutor struct {
@@ -2228,6 +2235,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/mutator.go b/android/mutator.go
index 2ef4d7f..18a9777 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -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{
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/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/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/filesystem/system_image.go b/filesystem/system_image.go
index a8fd368..805249e 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.
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/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..9d12b9a 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -245,6 +245,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.
diff --git a/java/kotlin.go b/java/kotlin.go
index 3573f1e..f42d163 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -65,8 +65,6 @@
"headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name")
var kotlinKytheExtract = pctx.AndroidStaticRule("kotlinKythe",
- // TODO (b/265428637): To prevent kotlinc version skew between android builds and internal kotlin indexers (g3), consider embedding the kotlinc used by android into the kzip file.
- // This has an impact on .kzip sizes, so defer that for now.
blueprint.RuleParams{
Command: `rm -rf "$srcJarDir" && mkdir -p "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" -f "*.kt" $srcJars && ` +
@@ -76,7 +74,8 @@
// Skip header jars, those should not have an effect on kythe results.
` --args '${config.KotlincGlobalFlags} ` +
` ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` +
- ` $kotlincFlags -jvm-target $kotlinJvmTarget'`,
+ ` $kotlincFlags -jvm-target $kotlinJvmTarget ` +
+ `${config.KotlincKytheGlobalFlags}'`,
CommandDeps: []string{
"${config.KotlinKytheExtractor}",
"${config.ZipSyncCmd}",
diff --git a/java/ravenwood.go b/java/ravenwood.go
index bb136cf..3fa73e6 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -33,7 +33,6 @@
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"}
const ravenwoodUtilsName = "ravenwood-utils"
@@ -228,7 +227,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 +269,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 +308,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..0a1b089 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,15 @@
}
android_app {
name: "app1",
- sdk_version: "current",
+ sdk_version: "current",
}
android_app {
name: "app2",
- sdk_version: "current",
+ sdk_version: "current",
+ }
+ prebuilt_font {
+ name: "Font.ttf",
+ src: "Font.ttf",
}
android_ravenwood_libgroup {
name: "ravenwood-runtime",
@@ -76,7 +81,10 @@
"ravenwood-runtime-jni2",
],
data: [
- "app1",
+ ":app1",
+ ],
+ fonts: [
+ ":Font.ttf"
],
}
android_ravenwood_libgroup {
@@ -97,6 +105,7 @@
ctx := android.GroupFixturePreparers(
PrepareForIntegrationTestWithJava,
+ etc.PrepareForTestWithPrebuiltEtc,
prepareRavenwoodRuntime,
).RunTest(t)
@@ -114,6 +123,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 +135,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: [
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 725aaed..9f0564a 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1727,6 +1727,7 @@
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]
@@ -1734,6 +1735,7 @@
Stem *string
}{
Name: proptools.StringPtr(module.implLibraryModuleName()),
+ Enabled: module.EnabledProperty(),
Visibility: visibility,
Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...),
@@ -1762,6 +1764,7 @@
type libraryProperties struct {
Name *string
+ Enabled proptools.Configurable[bool]
Visibility []string
Srcs []string
Installable *bool
@@ -1788,6 +1791,7 @@
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)
@@ -1838,6 +1842,7 @@
func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
props := struct {
Name *string
+ Enabled proptools.Configurable[bool]
Visibility []string
Srcs []string
Installable *bool
@@ -1879,6 +1884,7 @@
// * 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...)
@@ -2004,6 +2010,7 @@
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]
@@ -2016,6 +2023,7 @@
}{}
props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
+ props.Enabled = module.EnabledProperty()
props.Visibility = []string{"//visibility:override", "//visibility:private"}
apiContributions := []string{}
@@ -2066,6 +2074,7 @@
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)
@@ -2158,6 +2167,7 @@
}
props := struct {
Name *string
+ Enabled proptools.Configurable[bool]
Lib_name *string
Apex_available []string
On_bootclasspath_since *string
@@ -2168,6 +2178,7 @@
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,
@@ -2263,11 +2274,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
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/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/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..eb51022 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -588,19 +588,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 +607,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 +648,6 @@
}
ninjaArgs = append(ninjaArgs, targets...)
- ninjaCmd := config.NinjaBin()
- if config.useN2 {
- ninjaCmd = config.N2Bin()
- }
cmd := Command(ctx, config, "soong bootstrap",
ninjaCmd, ninjaArgs...)