Merge "rustc-1.63.0 Build 8951290"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index a932a91..5c79fa2 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -584,5 +584,15 @@
"prebuilt_android-support-annotations-nodeps",
"prebuilt_android-arch-paging-common-nodeps",
"prebuilt_android-arch-room-common-nodeps",
+ // TODO(b/217750501) exclude_dirs property not supported
+ "prebuilt_kotlin-reflect",
+ "prebuilt_kotlin-stdlib",
+ "prebuilt_kotlin-stdlib-jdk7",
+ "prebuilt_kotlin-stdlib-jdk8",
+ "prebuilt_kotlin-test",
+ // TODO(b/217750501) exclude_files property not supported
+ "prebuilt_platform-robolectric-4.4-prebuilt",
+ "prebuilt_platform-robolectric-4.5.1-prebuilt",
+ "prebuilt_currysrc_org.eclipse",
}
)
diff --git a/android/arch.go b/android/arch.go
index a0895ed..1952b17 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -619,6 +619,12 @@
mctx.ModuleErrorf("%s", err.Error())
}
+ // If there are no supported targets disable the module.
+ if len(targets) == 0 {
+ base.Disable()
+ return
+ }
+
// If the module is using extraMultilib, decode the extraMultilib selection into
// a separate list of Targets.
var multiTargets []Target
@@ -627,6 +633,7 @@
if err != nil {
mctx.ModuleErrorf("%s", err.Error())
}
+ multiTargets = filterHostCross(multiTargets, targets[0].HostCross)
}
// Recovery is always the primary architecture, filter out any other architectures.
@@ -763,6 +770,18 @@
return targets
}
+// filterHostCross takes a list of Targets and a hostCross value, and returns a modified list
+// that contains only Targets that have the specified HostCross.
+func filterHostCross(targets []Target, hostCross bool) []Target {
+ for i := 0; i < len(targets); i++ {
+ if targets[i].HostCross != hostCross {
+ targets = append(targets[:i], targets[i+1:]...)
+ i--
+ }
+ }
+ return targets
+}
+
// archPropRoot is a struct type used as the top level of the arch-specific properties. It
// contains the "arch", "multilib", and "target" property structs. It is used to split up the
// property structs to limit how much is allocated when a single arch-specific property group is
@@ -1795,20 +1814,23 @@
}
// FirstTarget takes a list of Targets and a list of multilib values and returns a list of Targets
-// that contains zero or one Target for each OsType, selecting the one that matches the earliest
-// filter.
+// that contains zero or one Target for each OsType and HostCross, selecting the one that matches
+// the earliest filter.
func FirstTarget(targets []Target, filters ...string) []Target {
// find the first target from each OS
var ret []Target
- hasHost := false
- set := make(map[OsType]bool)
+ type osHostCross struct {
+ os OsType
+ hostCross bool
+ }
+ set := make(map[osHostCross]bool)
for _, filter := range filters {
buildTargets := filterMultilibTargets(targets, filter)
for _, t := range buildTargets {
- if _, found := set[t.Os]; !found {
- hasHost = hasHost || (t.Os.Class == Host)
- set[t.Os] = true
+ key := osHostCross{t.Os, t.HostCross}
+ if _, found := set[key]; !found {
+ set[key] = true
ret = append(ret, t)
}
}
diff --git a/android/arch_test.go b/android/arch_test.go
index ad2076d..6814f8a 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -259,6 +259,27 @@
}
}
+func (m *archTestMultiTargetsModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+func (m *archTestMultiTargetsModule) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
+}
+
+func archTestMultiTargetsModuleFactory() Module {
+ m := &archTestMultiTargetsModule{}
+ m.AddProperties(&m.props)
+ InitAndroidMultiTargetsArchModule(m, HostAndDeviceSupported, MultilibCommon)
+ return m
+}
+
+type archTestMultiTargetsModule struct {
+ ModuleBase
+ props struct {
+ Deps []string
+ }
+}
+
func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
}
@@ -277,19 +298,27 @@
PrepareForTestWithArchMutator,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("module", archTestModuleFactory)
+ ctx.RegisterModuleType("multi_targets_module", archTestMultiTargetsModuleFactory)
}),
)
func TestArchMutator(t *testing.T) {
var buildOSVariants []string
+ var buildOS64Variants []string
var buildOS32Variants []string
+ var buildOSCommonVariant string
+
switch runtime.GOOS {
case "linux":
buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"}
+ buildOS64Variants = []string{"linux_glibc_x86_64"}
buildOS32Variants = []string{"linux_glibc_x86"}
+ buildOSCommonVariant = "linux_glibc_common"
case "darwin":
buildOSVariants = []string{"darwin_x86_64"}
+ buildOS64Variants = []string{"darwin_x86_64"}
buildOS32Variants = nil
+ buildOSCommonVariant = "darwin_common"
}
bp := `
@@ -312,24 +341,46 @@
host_supported: true,
compile_multilib: "32",
}
+
+ module {
+ name: "first",
+ host_supported: true,
+ compile_multilib: "first",
+ }
+
+ multi_targets_module {
+ name: "multi_targets",
+ host_supported: true,
+ }
`
testCases := []struct {
- name string
- preparer FixturePreparer
- fooVariants []string
- barVariants []string
- bazVariants []string
- quxVariants []string
+ name string
+ preparer FixturePreparer
+ fooVariants []string
+ barVariants []string
+ bazVariants []string
+ quxVariants []string
+ firstVariants []string
+
+ multiTargetVariants []string
+ multiTargetVariantsMap map[string][]string
+
+ goOS string
}{
{
- name: "normal",
- preparer: nil,
- fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
- barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
- bazVariants: nil,
- quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
- },
+ name: "normal",
+ preparer: nil,
+ fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
+ barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
+ bazVariants: nil,
+ quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"),
+ firstVariants: append(buildOS64Variants, "android_arm64_armv8-a"),
+ multiTargetVariants: []string{buildOSCommonVariant, "android_common"},
+ multiTargetVariantsMap: map[string][]string{
+ buildOSCommonVariant: buildOS64Variants,
+ "android_common": {"android_arm64_armv8-a"},
+ }},
{
name: "host-only",
preparer: FixtureModifyConfig(func(config Config) {
@@ -337,10 +388,33 @@
config.BuildOSCommonTarget = Target{}
config.Targets[Android] = nil
}),
- fooVariants: nil,
- barVariants: buildOSVariants,
- bazVariants: nil,
- quxVariants: buildOS32Variants,
+ fooVariants: nil,
+ barVariants: buildOSVariants,
+ bazVariants: nil,
+ quxVariants: buildOS32Variants,
+ firstVariants: buildOS64Variants,
+ multiTargetVariants: []string{buildOSCommonVariant},
+ multiTargetVariantsMap: map[string][]string{
+ buildOSCommonVariant: buildOS64Variants,
+ },
+ },
+ {
+ name: "same arch host and host cross",
+ preparer: FixtureModifyConfig(func(config Config) {
+ modifyTestConfigForMusl(config)
+ modifyTestConfigForMuslArm64HostCross(config)
+ }),
+ fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
+ barVariants: []string{"linux_musl_x86_64", "linux_musl_arm64", "linux_musl_x86", "android_arm64_armv8-a", "android_arm_armv7-a-neon"},
+ bazVariants: nil,
+ quxVariants: []string{"linux_musl_x86", "android_arm_armv7-a-neon"},
+ firstVariants: []string{"linux_musl_x86_64", "linux_musl_arm64", "android_arm64_armv8-a"},
+ multiTargetVariants: []string{"linux_musl_common", "android_common"},
+ multiTargetVariantsMap: map[string][]string{
+ "linux_musl_common": {"linux_musl_x86_64"},
+ "android_common": {"android_arm64_armv8-a"},
+ },
+ goOS: "linux",
},
}
@@ -356,8 +430,21 @@
return ret
}
+ moduleMultiTargets := func(ctx *TestContext, name string, variant string) []string {
+ var ret []string
+ targets := ctx.ModuleForTests(name, variant).Module().MultiTargets()
+ for _, t := range targets {
+ ret = append(ret, t.String())
+ }
+ return ret
+ }
+
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
+ if tt.goOS != runtime.GOOS {
+ t.Skipf("requries runtime.GOOS %s", tt.goOS)
+ }
+
result := GroupFixturePreparers(
prepareForArchTest,
// Test specific preparer
@@ -381,6 +468,20 @@
if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) {
t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
}
+ if g, w := enabledVariants(ctx, "first"), tt.firstVariants; !reflect.DeepEqual(w, g) {
+ t.Errorf("want first variants:\n%q\ngot:\n%q\n", w, g)
+ }
+
+ if g, w := enabledVariants(ctx, "multi_targets"), tt.multiTargetVariants; !reflect.DeepEqual(w, g) {
+ t.Fatalf("want multi_target variants:\n%q\ngot:\n%q\n", w, g)
+ }
+
+ for _, variant := range tt.multiTargetVariants {
+ targets := moduleMultiTargets(ctx, "multi_targets", variant)
+ if g, w := targets, tt.multiTargetVariantsMap[variant]; !reflect.DeepEqual(w, g) {
+ t.Errorf("want ctx.MultiTarget() for %q:\n%q\ngot:\n%q\n", variant, w, g)
+ }
+ }
})
}
}
diff --git a/android/bazel.go b/android/bazel.go
index aff6116..71eb036 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -231,16 +231,18 @@
// when they have the same type as one listed.
moduleTypeAlwaysConvert map[string]bool
- // Per-module denylist to always opt modules out of both bp2build and mixed builds.
+ // Per-module denylist to always opt modules out of bp2build conversion.
moduleDoNotConvert map[string]bool
// Per-module denylist of cc_library modules to only generate the static
// variant if their shared variant isn't ready or buildable by Bazel.
ccLibraryStaticOnly map[string]bool
+}
- // Per-module denylist to opt modules out of mixed builds. Such modules will
- // still be generated via bp2build.
- mixedBuildsDisabled map[string]bool
+// GenerateCcLibraryStaticOnly returns whether a cc_library module should only
+// generate a static version of itself based on the current global configuration.
+func (a bp2BuildConversionAllowlist) GenerateCcLibraryStaticOnly(moduleName string) bool {
+ return a.ccLibraryStaticOnly[moduleName]
}
// NewBp2BuildAllowlist creates a new, empty bp2BuildConversionAllowlist
@@ -253,7 +255,6 @@
map[string]bool{},
map[string]bool{},
map[string]bool{},
- map[string]bool{},
}
}
@@ -329,43 +330,24 @@
return a
}
-// SetMixedBuildsDisabledList copies the entries from mixedBuildsDisabled into the allowlist
-func (a bp2BuildConversionAllowlist) SetMixedBuildsDisabledList(mixedBuildsDisabled []string) bp2BuildConversionAllowlist {
- if a.mixedBuildsDisabled == nil {
- a.mixedBuildsDisabled = map[string]bool{}
- }
- for _, m := range mixedBuildsDisabled {
- a.mixedBuildsDisabled[m] = true
- }
-
- return a
-}
-
var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist")
var bp2buildAllowlist OncePer
-func getBp2BuildAllowList() bp2BuildConversionAllowlist {
+func GetBp2BuildAllowList() bp2BuildConversionAllowlist {
return bp2buildAllowlist.Once(bp2BuildAllowListKey, func() interface{} {
return NewBp2BuildAllowlist().SetDefaultConfig(allowlists.Bp2buildDefaultConfig).
SetKeepExistingBuildFile(allowlists.Bp2buildKeepExistingBuildFile).
SetModuleAlwaysConvertList(allowlists.Bp2buildModuleAlwaysConvertList).
SetModuleTypeAlwaysConvertList(allowlists.Bp2buildModuleTypeAlwaysConvertList).
SetModuleDoNotConvertList(allowlists.Bp2buildModuleDoNotConvertList).
- SetCcLibraryStaticOnlyList(allowlists.Bp2buildCcLibraryStaticOnlyList).
- SetMixedBuildsDisabledList(allowlists.MixedBuildsDisabledList)
+ SetCcLibraryStaticOnlyList(allowlists.Bp2buildCcLibraryStaticOnlyList)
}).(bp2BuildConversionAllowlist)
}
-// GenerateCcLibraryStaticOnly returns whether a cc_library module should only
-// generate a static version of itself based on the current global configuration.
-func GenerateCcLibraryStaticOnly(moduleName string) bool {
- return getBp2BuildAllowList().ccLibraryStaticOnly[moduleName]
-}
-
// ShouldKeepExistingBuildFileForDir returns whether an existing BUILD file should be
// added to the build symlink forest based on the current global configuration.
func ShouldKeepExistingBuildFileForDir(dir string) bool {
- return shouldKeepExistingBuildFileForDir(getBp2BuildAllowList(), dir)
+ return shouldKeepExistingBuildFileForDir(GetBp2BuildAllowList(), dir)
}
func shouldKeepExistingBuildFileForDir(allowlist bp2BuildConversionAllowlist, dir string) bool {
@@ -405,20 +387,10 @@
if !ctx.Module().Enabled() {
return false
}
- if !ctx.Config().BazelContext.BazelEnabled() {
- return false
- }
if !convertedToBazel(ctx, ctx.Module()) {
return false
}
-
- if GenerateCcLibraryStaticOnly(ctx.Module().Name()) {
- // Don't use partially-converted cc_library targets in mixed builds,
- // since mixed builds would generally rely on both static and shared
- // variants of a cc_library.
- return false
- }
- return !getBp2BuildAllowList().mixedBuildsDisabled[ctx.Module().Name()]
+ return ctx.Config().BazelContext.BazelAllowlisted(ctx.Module().Name())
}
// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index a5fa043..d87f988 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -27,6 +27,7 @@
"strings"
"sync"
+ "android/soong/android/allowlists"
"android/soong/bazel/cquery"
"android/soong/shared"
@@ -142,8 +143,11 @@
// queued in the BazelContext.
InvokeBazel(config Config) error
- // Returns true if bazel is enabled for the given configuration.
- BazelEnabled() bool
+ // Returns true if Bazel handling is enabled for the module with the given name.
+ // Note that this only implies "bazel mixed build" allowlisting. The caller
+ // should independently verify the module is eligible for Bazel handling
+ // (for example, that it is MixedBuildBuildable).
+ BazelAllowlisted(moduleName string) bool
// Returns the bazel output base (the root directory for all bazel intermediate outputs).
OutputBase() string
@@ -183,6 +187,17 @@
// Depsets which should be used for Bazel's build statements.
depsets []bazel.AqueryDepset
+
+ // Per-module allowlist/denylist functionality to control whether analysis of
+ // modules are handled by Bazel. For modules which do not have a Bazel definition
+ // (or do not sufficiently support bazel handling via MixedBuildBuildable),
+ // this allowlist will have no effect, even if the module is explicitly allowlisted here.
+ // Per-module denylist to opt modules out of bazel handling.
+ bazelDisabledModules map[string]bool
+ // Per-module allowlist to opt modules in to bazel handling.
+ bazelEnabledModules map[string]bool
+ // If true, modules are bazel-enabled by default, unless present in bazelDisabledModules.
+ modulesDefaultToBazel bool
}
var _ BazelContext = &bazelContext{}
@@ -229,7 +244,7 @@
panic("unimplemented")
}
-func (m MockBazelContext) BazelEnabled() bool {
+func (m MockBazelContext) BazelAllowlisted(moduleName string) bool {
return true
}
@@ -315,7 +330,7 @@
return ""
}
-func (n noopBazelContext) BazelEnabled() bool {
+func (n noopBazelContext) BazelAllowlisted(moduleName string) bool {
return false
}
@@ -328,9 +343,7 @@
}
func NewBazelContext(c *config) (BazelContext, error) {
- // TODO(cparsons): Assess USE_BAZEL=1 instead once "mixed Soong/Bazel builds"
- // are production ready.
- if !c.IsEnvTrue("USE_BAZEL_ANALYSIS") {
+ if !c.IsMixedBuildsEnabled() {
return noopBazelContext{}, nil
}
@@ -338,10 +351,26 @@
if err != nil {
return nil, err
}
+
+ // TODO(cparsons): Use a different allowlist depending on prod vs. dev
+ // bazel mode.
+ disabledModules := map[string]bool{}
+ // Don't use partially-converted cc_library targets in mixed builds,
+ // since mixed builds would generally rely on both static and shared
+ // variants of a cc_library.
+ for staticOnlyModule, _ := range GetBp2BuildAllowList().ccLibraryStaticOnly {
+ disabledModules[staticOnlyModule] = true
+ }
+ for _, disabledDevModule := range allowlists.MixedBuildsDisabledList {
+ disabledModules[disabledDevModule] = true
+ }
+
return &bazelContext{
- bazelRunner: &builtinBazelRunner{},
- paths: p,
- requests: make(map[cqueryKey]bool),
+ bazelRunner: &builtinBazelRunner{},
+ paths: p,
+ requests: make(map[cqueryKey]bool),
+ modulesDefaultToBazel: true,
+ bazelDisabledModules: disabledModules,
}, nil
}
@@ -386,8 +415,14 @@
return p.metricsDir
}
-func (context *bazelContext) BazelEnabled() bool {
- return true
+func (context *bazelContext) BazelAllowlisted(moduleName string) bool {
+ if context.bazelDisabledModules[moduleName] {
+ return false
+ }
+ if context.bazelEnabledModules[moduleName] {
+ return true
+ }
+ return context.modulesDefaultToBazel
}
func pwdPrefix() string {
@@ -851,7 +886,7 @@
func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
// bazelSingleton is a no-op if mixed-soong-bazel-builds are disabled.
- if !ctx.Config().BazelContext.BazelEnabled() {
+ if !ctx.Config().IsMixedBuildsEnabled() {
return
}
diff --git a/android/bazel_test.go b/android/bazel_test.go
index da4a915..98f0a46 100644
--- a/android/bazel_test.go
+++ b/android/bazel_test.go
@@ -389,7 +389,7 @@
}
func TestBp2buildAllowList(t *testing.T) {
- allowlist := getBp2BuildAllowList()
+ allowlist := GetBp2BuildAllowList()
for k, v := range allowlists.Bp2buildDefaultConfig {
if allowlist.defaultConfig[k] != v {
t.Errorf("bp2build default config of %s: expected: %v, got: %v", k, v, allowlist.defaultConfig[k])
@@ -415,9 +415,4 @@
t.Errorf("bp2build cc library static only of %s: expected: true, got: %v", k, allowlist.ccLibraryStaticOnly[k])
}
}
- for _, k := range allowlists.MixedBuildsDisabledList {
- if !allowlist.mixedBuildsDisabled[k] {
- t.Errorf("bp2build mix build disabled of %s: expected: true, got: %v", k, allowlist.mixedBuildsDisabled[k])
- }
- }
}
diff --git a/android/config.go b/android/config.go
index 15707a5..5ca9420 100644
--- a/android/config.go
+++ b/android/config.go
@@ -68,6 +68,38 @@
*config
}
+type SoongBuildMode int
+
+// Build modes that soong_build can run as.
+const (
+ // Don't use bazel at all during module analysis.
+ AnalysisNoBazel SoongBuildMode = iota
+
+ // Bp2build mode: Generate BUILD files from blueprint files and exit.
+ Bp2build
+
+ // Generate BUILD files which faithfully represent the dependency graph of
+ // blueprint modules. Individual BUILD targets will not, however, faitfhully
+ // express build semantics.
+ GenerateQueryView
+
+ // Create a JSON representation of the module graph and exit.
+ GenerateModuleGraph
+
+ // Generate a documentation file for module type definitions and exit.
+ GenerateDocFile
+
+ // Use bazel during analysis of many allowlisted build modules. The allowlist
+ // is considered a "developer mode" allowlist, as some modules may be
+ // allowlisted on an experimental basis.
+ BazelDevMode
+
+ // Use bazel during analysis of build modules from an allowlist carefully
+ // curated by the build team to be proven stable.
+ // TODO(cparsons): Implement this mode.
+ BazelProdMode
+)
+
// SoongOutDir returns the build output directory for the configuration.
func (c Config) SoongOutDir() string {
return c.soongOutDir
@@ -157,7 +189,7 @@
fs pathtools.FileSystem
mockBpList string
- runningAsBp2Build bool
+ BuildMode SoongBuildMode
bp2buildPackageConfig bp2BuildConversionAllowlist
Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions
@@ -171,6 +203,12 @@
OncePer
+ // These fields are only used for metrics collection. A module should be added
+ // to these maps only if its implementation supports Bazel handling in mixed
+ // builds. A module being in the "enabled" list indicates that there is a
+ // variant of that module for which bazel-handling actually took place.
+ // A module being in the "disabled" list indicates that there is a variant of
+ // that module for which bazel-handling was denied.
mixedBuildsLock sync.Mutex
mixedBuildEnabledModules map[string]struct{}
mixedBuildDisabledModules map[string]struct{}
@@ -346,7 +384,7 @@
// NewConfig creates a new Config object. The srcDir argument specifies the path
// to the root source directory. It also loads the config file, if found.
-func NewConfig(moduleListFile string, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) {
+func NewConfig(moduleListFile string, buildMode SoongBuildMode, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) {
// Make a config with default options.
config := &config{
ProductVariablesFileName: filepath.Join(soongOutDir, productVariablesFileName),
@@ -443,8 +481,17 @@
config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
}
+ // Checking USE_BAZEL_ANALYSIS must be done here instead of in the caller, so
+ // that we can invoke IsEnvTrue (which also registers the env var as a
+ // dependency of the build).
+ // TODO(cparsons): Remove this hack once USE_BAZEL_ANALYSIS is removed.
+ if buildMode == AnalysisNoBazel && config.IsEnvTrue("USE_BAZEL_ANALYSIS") {
+ buildMode = BazelDevMode
+ }
+
+ config.BuildMode = buildMode
config.BazelContext, err = NewBazelContext(config)
- config.bp2buildPackageConfig = getBp2BuildAllowList()
+ config.bp2buildPackageConfig = GetBp2BuildAllowList()
return Config{config}, err
}
@@ -479,6 +526,12 @@
c.mockBpList = blueprint.MockModuleListFile
}
+// Returns true if "Bazel builds" is enabled. In this mode, part of build
+// analysis is handled by Bazel.
+func (c *config) IsMixedBuildsEnabled() bool {
+ return c.BuildMode == BazelProdMode || c.BuildMode == BazelDevMode
+}
+
func (c *config) SetAllowMissingDependencies() {
c.productVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
}
diff --git a/android/defaults.go b/android/defaults.go
index 03b2efb..7906e94 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -448,7 +448,7 @@
}
for _, defaults := range defaultsList {
- if ctx.Config().runningAsBp2Build {
+ if ctx.Config().BuildMode == Bp2build {
applyNamespacedVariableDefaults(defaults, ctx)
}
diff --git a/android/module.go b/android/module.go
index bf62080..5908233 100644
--- a/android/module.go
+++ b/android/module.go
@@ -942,12 +942,19 @@
// If the test is a hostside (no device required) unittest that shall be run
// during presubmit check.
Unit_test *bool
+
+ // Tags provide additional metadata to customize test execution by downstream
+ // test runners. The tags have no special meaning to Soong.
+ Tags []string
}
// SetAndroidMkEntries sets AndroidMkEntries according to the value of base
// `test_options`.
func (t *CommonTestOptions) SetAndroidMkEntries(entries *AndroidMkEntries) {
entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(t.Unit_test))
+ if len(t.Tags) > 0 {
+ entries.AddStrings("LOCAL_TEST_OPTIONS_TAGS", t.Tags...)
+ }
}
// The key to use in TaggedDistFiles when a Dist structure does not specify a
@@ -2367,9 +2374,6 @@
}
func (m *ModuleBase) isHandledByBazel(ctx ModuleContext) (MixedBuildBuildable, bool) {
- if !ctx.Config().BazelContext.BazelEnabled() {
- return nil, false
- }
if mixedBuildMod, ok := m.module.(MixedBuildBuildable); ok {
if mixedBuildMod.IsMixedBuildSupported(ctx) && MixedBuildsEnabled(ctx) {
return mixedBuildMod, true
diff --git a/android/module_test.go b/android/module_test.go
index 835ab4c..0580bef 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -912,7 +912,7 @@
}
}
-func TestProcessCommonTestOptions(t *testing.T) {
+func TestSetAndroidMkEntriesWithTestOptions(t *testing.T) {
tests := []struct {
name string
testOptions CommonTestOptions
@@ -939,6 +939,31 @@
},
expected: map[string][]string{},
},
+ {
+ name: "empty tag",
+ testOptions: CommonTestOptions{
+ Tags: []string{},
+ },
+ expected: map[string][]string{},
+ },
+ {
+ name: "single tag",
+ testOptions: CommonTestOptions{
+ Tags: []string{"tag1"},
+ },
+ expected: map[string][]string{
+ "LOCAL_TEST_OPTIONS_TAGS": []string{"tag1"},
+ },
+ },
+ {
+ name: "multiple tag",
+ testOptions: CommonTestOptions{
+ Tags: []string{"tag1", "tag2", "tag3"},
+ },
+ expected: map[string][]string{
+ "LOCAL_TEST_OPTIONS_TAGS": []string{"tag1", "tag2", "tag3"},
+ },
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/android/register.go b/android/register.go
index 5832b1b..d4ce5f1 100644
--- a/android/register.go
+++ b/android/register.go
@@ -164,10 +164,6 @@
return ctx
}
-func (ctx *Context) SetRunningAsBp2build() {
- ctx.config.runningAsBp2Build = true
-}
-
// RegisterForBazelConversion registers an alternate shadow pipeline of
// singletons, module types and mutators to register for converting Blueprint
// files to semantically equivalent BUILD files.
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index b25f248..cd36ae0 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -382,7 +382,7 @@
defer r.Close()
mtDef, errs := soongconfig.Parse(r, from)
- if ctx.Config().runningAsBp2Build {
+ if ctx.Config().BuildMode == Bp2build {
ctx.Config().Bp2buildSoongConfigDefinitions.AddVars(*mtDef)
}
@@ -398,7 +398,7 @@
for name, moduleType := range mtDef.ModuleTypes {
factory := globalModuleTypes[moduleType.BaseModuleType]
if factory != nil {
- factories[name] = configModuleFactory(factory, moduleType, ctx.Config().runningAsBp2Build)
+ factories[name] = configModuleFactory(factory, moduleType, ctx.Config().BuildMode == Bp2build)
} else {
reportErrors(ctx, from,
fmt.Errorf("missing global module type factory for %q", moduleType.BaseModuleType))
diff --git a/android/test_config.go b/android/test_config.go
index f36e8ba..0f88d51 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -118,6 +118,11 @@
config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
}
+func modifyTestConfigForMuslArm64HostCross(config Config) {
+ config.Targets[LinuxMusl] = append(config.Targets[LinuxMusl],
+ Target{config.BuildOS, Arch{ArchType: Arm64}, NativeBridgeDisabled, "", "", true})
+}
+
// TestArchConfig returns a Config object suitable for using for tests that
// need to run the arch mutator.
func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
diff --git a/android/testing.go b/android/testing.go
index b4429ca..ef5e5a9 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -457,7 +457,7 @@
// RegisterForBazelConversion prepares a test context for bp2build conversion.
func (ctx *TestContext) RegisterForBazelConversion() {
- ctx.SetRunningAsBp2build()
+ ctx.config.BuildMode = Bp2build
RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch)
}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index ba93439..5954098 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -983,7 +983,7 @@
func bazelLabelForStaticModule(ctx android.BazelConversionPathContext, m blueprint.Module) string {
label := android.BazelModuleLabel(ctx, m)
- if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary && !android.GenerateCcLibraryStaticOnly(m.Name()) {
+ if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary && !android.GetBp2BuildAllowList().GenerateCcLibraryStaticOnly(m.Name()) {
label += "_bp2build_cc_library_static"
}
return label
diff --git a/cc/library.go b/cc/library.go
index 621b58c..41dca01 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -282,7 +282,7 @@
// For some cc_library modules, their static variants are ready to be
// converted, but not their shared variants. For these modules, delegate to
// the cc_library_static bp2build converter temporarily instead.
- if android.GenerateCcLibraryStaticOnly(ctx.Module().Name()) {
+ if android.GetBp2BuildAllowList().GenerateCcLibraryStaticOnly(ctx.Module().Name()) {
sharedOrStaticLibraryBp2Build(ctx, m, true)
return
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 53422cd..6930943 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -121,7 +121,21 @@
}
func newConfig(availableEnv map[string]string) android.Config {
- configuration, err := android.NewConfig(cmdlineArgs.ModuleListFile, runGoTests, outDir, soongOutDir, availableEnv)
+ var buildMode android.SoongBuildMode
+
+ if bp2buildMarker != "" {
+ buildMode = android.Bp2build
+ } else if bazelQueryViewDir != "" {
+ buildMode = android.GenerateQueryView
+ } else if moduleGraphFile != "" {
+ buildMode = android.GenerateModuleGraph
+ } else if docFile != "" {
+ buildMode = android.GenerateDocFile
+ } else {
+ buildMode = android.AnalysisNoBazel
+ }
+
+ configuration, err := android.NewConfig(cmdlineArgs.ModuleListFile, buildMode, runGoTests, outDir, soongOutDir, availableEnv)
if err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
os.Exit(1)
@@ -221,52 +235,40 @@
// or the actual Soong build for the build.ninja file. Returns the top level
// output file of the specific activity.
func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string, logDir string) string {
- mixedModeBuild := configuration.BazelContext.BazelEnabled()
- generateBazelWorkspace := bp2buildMarker != ""
- generateQueryView := bazelQueryViewDir != ""
- generateModuleGraphFile := moduleGraphFile != ""
- generateDocFile := docFile != ""
-
- if generateBazelWorkspace {
+ if configuration.BuildMode == android.Bp2build {
// Run the alternate pipeline of bp2build mutators and singleton to convert
// Blueprint to BUILD files before everything else.
runBp2Build(configuration, extraNinjaDeps)
return bp2buildMarker
- }
-
- blueprintArgs := cmdlineArgs
-
- if mixedModeBuild {
+ } else if configuration.IsMixedBuildsEnabled() {
runMixedModeBuild(configuration, ctx, extraNinjaDeps)
} else {
var stopBefore bootstrap.StopBefore
- if generateModuleGraphFile {
+ if configuration.BuildMode == android.GenerateModuleGraph {
stopBefore = bootstrap.StopBeforeWriteNinja
- } else if generateQueryView {
- stopBefore = bootstrap.StopBeforePrepareBuildActions
- } else if generateDocFile {
+ } else if configuration.BuildMode == android.GenerateQueryView || configuration.BuildMode == android.GenerateDocFile {
stopBefore = bootstrap.StopBeforePrepareBuildActions
} else {
stopBefore = bootstrap.DoEverything
}
- ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, stopBefore, ctx.Context, configuration)
+ ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, stopBefore, ctx.Context, configuration)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
ninjaDeps = append(ninjaDeps, globListFiles...)
// Convert the Soong module graph into Bazel BUILD files.
- if generateQueryView {
+ if configuration.BuildMode == android.GenerateQueryView {
queryviewMarkerFile := bazelQueryViewDir + ".marker"
runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
writeDepFile(queryviewMarkerFile, *ctx.EventHandler, ninjaDeps)
return queryviewMarkerFile
- } else if generateModuleGraphFile {
+ } else if configuration.BuildMode == android.GenerateModuleGraph {
writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
writeDepFile(moduleGraphFile, *ctx.EventHandler, ninjaDeps)
return moduleGraphFile
- } else if generateDocFile {
+ } else if configuration.BuildMode == android.GenerateDocFile {
// TODO: we could make writeDocs() return the list of documentation files
// written and add them to the .d file. Then soong_docs would be re-run
// whenever one is deleted.
@@ -491,11 +493,6 @@
// conversion for Bazel conversion.
bp2buildCtx := android.NewContext(configuration)
- // Soong internals like LoadHooks behave differently when running as
- // bp2build. This is the bit to differentiate between Soong-as-Soong and
- // Soong-as-bp2build.
- bp2buildCtx.SetRunningAsBp2build()
-
// Propagate "allow misssing dependencies" bit. This is normally set in
// newContext(), but we create bp2buildCtx without calling that method.
bp2buildCtx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 6686c87..7a0dac3 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -26,6 +26,7 @@
"strings"
"android/soong/bazel/cquery"
+
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
@@ -468,6 +469,7 @@
return "SOONG_ERROR", nil
}
+ // Apply shell escape to each cases to prevent source file paths containing $ from being evaluated in shell
switch name {
case "location":
if len(g.properties.Tools) == 0 && len(g.properties.Tool_files) == 0 {
@@ -481,15 +483,15 @@
return reportError("default label %q has multiple files, use $(locations %s) to reference it",
firstLabel, firstLabel)
}
- return paths[0], nil
+ return proptools.ShellEscape(paths[0]), nil
case "in":
- return strings.Join(cmd.PathsForInputs(srcFiles), " "), nil
+ return strings.Join(proptools.ShellEscapeList(cmd.PathsForInputs(srcFiles)), " "), nil
case "out":
var sandboxOuts []string
for _, out := range task.out {
sandboxOuts = append(sandboxOuts, cmd.PathForOutput(out))
}
- return strings.Join(sandboxOuts, " "), nil
+ return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil
case "depfile":
referencedDepfile = true
if !Bool(g.properties.Depfile) {
@@ -497,7 +499,7 @@
}
return "__SBOX_DEPFILE__", nil
case "genDir":
- return cmd.PathForOutput(task.genDir), nil
+ return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil
default:
if strings.HasPrefix(name, "location ") {
label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
@@ -509,7 +511,7 @@
return reportError("label %q has multiple files, use $(locations %s) to reference it",
label, label)
}
- return paths[0], nil
+ return proptools.ShellEscape(paths[0]), nil
} else {
return reportError("unknown location label %q is not in srcs, out, tools or tool_files.", label)
}
@@ -520,7 +522,7 @@
if len(paths) == 0 {
return reportError("label %q has no files", label)
}
- return strings.Join(paths, " "), nil
+ return proptools.ShellEscape(strings.Join(paths, " ")), nil
} else {
return reportError("unknown locations label %q is not in srcs, out, tools or tool_files.", label)
}
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index b9be1f7..cd941cc 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -422,7 +422,7 @@
allowMissingDependencies: true,
- expect: "cat ***missing srcs :missing*** > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "cat '***missing srcs :missing***' > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "tool allow missing dependencies",
@@ -434,7 +434,7 @@
allowMissingDependencies: true,
- expect: "***missing tool :missing*** > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "'***missing tool :missing***' > __SBOX_SANDBOX_DIR__/out/out",
},
}
@@ -878,6 +878,92 @@
android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
}
+func TestGenruleWithGlobPaths(t *testing.T) {
+ testcases := []struct {
+ name string
+ bp string
+ additionalFiles android.MockFS
+ expectedCmd string
+ }{
+ {
+ name: "single file in directory with $ sign",
+ bp: `
+ genrule {
+ name: "gen",
+ srcs: ["inn*.txt"],
+ out: ["out.txt"],
+ cmd: "cp $(in) $(out)",
+ }
+ `,
+ additionalFiles: android.MockFS{"inn$1.txt": nil},
+ expectedCmd: "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
+ },
+ {
+ name: "multiple file in directory with $ sign",
+ bp: `
+ genrule {
+ name: "gen",
+ srcs: ["inn*.txt"],
+ out: ["."],
+ cmd: "cp $(in) $(out)",
+ }
+ `,
+ additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil},
+ expectedCmd: "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out",
+ },
+ {
+ name: "file in directory with other shell unsafe character",
+ bp: `
+ genrule {
+ name: "gen",
+ srcs: ["inn*.txt"],
+ out: ["out.txt"],
+ cmd: "cp $(in) $(out)",
+ }
+ `,
+ additionalFiles: android.MockFS{"inn@1.txt": nil},
+ expectedCmd: "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
+ },
+ {
+ name: "glob location param with filepath containing $",
+ bp: `
+ genrule {
+ name: "gen",
+ srcs: ["**/inn*"],
+ out: ["."],
+ cmd: "cp $(in) $(location **/inn*)",
+ }
+ `,
+ additionalFiles: android.MockFS{"a/inn$1.txt": nil},
+ expectedCmd: "cp 'a/inn$1.txt' 'a/inn$1.txt'",
+ },
+ {
+ name: "glob locations param with filepath containing $",
+ bp: `
+ genrule {
+ name: "gen",
+ tool_files: ["**/inn*"],
+ out: ["out.txt"],
+ cmd: "cp $(locations **/inn*) $(out)",
+ }
+ `,
+ additionalFiles: android.MockFS{"a/inn$1.txt": nil},
+ expectedCmd: "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
+ },
+ }
+
+ for _, test := range testcases {
+ t.Run(test.name, func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(test.additionalFiles),
+ ).RunTestWithBp(t, test.bp)
+ gen := result.Module("gen", "").(*Module)
+ android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0])
+ })
+ }
+}
+
type testTool struct {
android.ModuleBase
outputFile android.Path
diff --git a/ui/build/config.go b/ui/build/config.go
index cbf1986..e140867 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -1326,6 +1326,10 @@
return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
}
+func (c *configImpl) SoongVarsFile() string {
+ return filepath.Join(c.SoongOutDir(), "soong.variables")
+}
+
func (c *configImpl) SoongNinjaFile() string {
return filepath.Join(c.SoongOutDir(), "build.ninja")
}
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 519506e..3920ddd 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -502,6 +502,7 @@
}
distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
+ distFile(ctx, config, config.SoongVarsFile(), "soong")
if !config.SkipKati() {
distGzipFile(ctx, config, config.SoongAndroidMk(), "soong")