Merge "Handle missing dependencies in mixed builds"
This commit is contained in:
@@ -46,6 +46,10 @@ const (
|
||||
// that is not a platform incompatibility. Example: the module-type is not
|
||||
// enabled, or is not bp2build-converted.
|
||||
ModuleIncompatibility
|
||||
|
||||
// Missing dependencies. We can't query Bazel for modules if it has missing dependencies, there
|
||||
// will be failures.
|
||||
ModuleMissingDeps
|
||||
)
|
||||
|
||||
// FileGroupAsLibrary describes a filegroup module that is converted to some library
|
||||
@@ -367,16 +371,26 @@ func GetBp2BuildAllowList() Bp2BuildConversionAllowlist {
|
||||
// As a side effect, calling this method will also log whether this module is
|
||||
// mixed build enabled for metrics reporting.
|
||||
func MixedBuildsEnabled(ctx BaseModuleContext) MixedBuildEnabledStatus {
|
||||
module := ctx.Module()
|
||||
apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo)
|
||||
withinApex := !apexInfo.IsForPlatform()
|
||||
|
||||
platformIncompatible := isPlatformIncompatible(ctx.Os(), ctx.Arch().ArchType)
|
||||
if platformIncompatible {
|
||||
ctx.Config().LogMixedBuild(ctx, false)
|
||||
return TechnicalIncompatibility
|
||||
}
|
||||
|
||||
if ctx.Config().AllowMissingDependencies() {
|
||||
missingDeps := ctx.getMissingDependencies()
|
||||
// If there are missing dependencies, querying Bazel will fail. Soong instead fails at execution
|
||||
// time, not loading/analysis. disable mixed builds and fall back to Soong to maintain that
|
||||
// behavior.
|
||||
if len(missingDeps) > 0 {
|
||||
ctx.Config().LogMixedBuild(ctx, false)
|
||||
return ModuleMissingDeps
|
||||
}
|
||||
}
|
||||
|
||||
module := ctx.Module()
|
||||
apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo)
|
||||
withinApex := !apexInfo.IsForPlatform()
|
||||
mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() &&
|
||||
module.Enabled() &&
|
||||
convertedToBazel(ctx, module) &&
|
||||
|
@@ -74,14 +74,12 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterMixedBuildsMutator(InitRegistrationContext)
|
||||
func registerMixedBuildsMutator(ctx RegisterMutatorsContext) {
|
||||
ctx.BottomUp("mixed_builds_prep", mixedBuildsPrepareMutator).Parallel()
|
||||
}
|
||||
|
||||
func RegisterMixedBuildsMutator(ctx RegistrationContext) {
|
||||
ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
|
||||
ctx.BottomUp("mixed_builds_prep", mixedBuildsPrepareMutator).Parallel()
|
||||
})
|
||||
ctx.FinalDepsMutators(registerMixedBuildsMutator)
|
||||
}
|
||||
|
||||
func mixedBuildsPrepareMutator(ctx BottomUpMutatorContext) {
|
||||
|
@@ -436,3 +436,150 @@ func TestShouldKeepExistingBuildFileForDir(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type mixedBuildModule struct {
|
||||
ModuleBase
|
||||
BazelModuleBase
|
||||
props struct {
|
||||
Deps []string
|
||||
Mixed_build_incompatible *bool
|
||||
QueuedBazelCall bool `blueprint:"mutated"`
|
||||
}
|
||||
}
|
||||
|
||||
type mixedBuildModuleInfo struct {
|
||||
QueuedBazelCall bool
|
||||
}
|
||||
|
||||
var mixedBuildModuleProvider = blueprint.NewProvider(mixedBuildModuleInfo{})
|
||||
|
||||
func mixedBuildModuleFactory() Module {
|
||||
m := &mixedBuildModule{}
|
||||
m.AddProperties(&m.props)
|
||||
InitAndroidArchModule(m, HostAndDeviceDefault, MultilibBoth)
|
||||
InitBazelModule(m)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mixedBuildModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
|
||||
}
|
||||
|
||||
func (m *mixedBuildModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||
ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
|
||||
}
|
||||
|
||||
func (m *mixedBuildModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
}
|
||||
|
||||
func (m *mixedBuildModule) IsMixedBuildSupported(ctx BaseModuleContext) bool {
|
||||
return !proptools.Bool(m.props.Mixed_build_incompatible)
|
||||
}
|
||||
|
||||
func (m *mixedBuildModule) QueueBazelCall(ctx BaseModuleContext) {
|
||||
m.props.QueuedBazelCall = true
|
||||
}
|
||||
|
||||
func (m *mixedBuildModule) ProcessBazelQueryResponse(ctx ModuleContext) {
|
||||
ctx.SetProvider(mixedBuildModuleProvider, mixedBuildModuleInfo{
|
||||
QueuedBazelCall: m.props.QueuedBazelCall,
|
||||
})
|
||||
}
|
||||
|
||||
var prepareForMixedBuildTests = FixtureRegisterWithContext(func(ctx RegistrationContext) {
|
||||
ctx.RegisterModuleType("deps", mixedBuildModuleFactory)
|
||||
RegisterMixedBuildsMutator(ctx)
|
||||
})
|
||||
|
||||
func TestMixedBuildsEnabledForType(t *testing.T) {
|
||||
baseBp := `
|
||||
deps {
|
||||
name: "foo",
|
||||
deps: ["bar"],
|
||||
target: { windows: { enabled: true } },
|
||||
%s
|
||||
}
|
||||
`
|
||||
depBp := `
|
||||
deps {
|
||||
name: "bar",
|
||||
target: {
|
||||
windows: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
`
|
||||
testCases := []struct {
|
||||
desc string
|
||||
variant *string
|
||||
missingDeps bool
|
||||
extraBpInfo string
|
||||
mixedBuildsEnabled bool
|
||||
}{
|
||||
{
|
||||
desc: "mixed builds works",
|
||||
mixedBuildsEnabled: true,
|
||||
extraBpInfo: `bazel_module: { bp2build_available: true },`,
|
||||
},
|
||||
{
|
||||
desc: "missing deps",
|
||||
missingDeps: true,
|
||||
mixedBuildsEnabled: false,
|
||||
extraBpInfo: `bazel_module: { bp2build_available: true },`,
|
||||
},
|
||||
{
|
||||
desc: "windows no mixed builds",
|
||||
mixedBuildsEnabled: false,
|
||||
variant: proptools.StringPtr("windows_x86"),
|
||||
extraBpInfo: `bazel_module: { bp2build_available: true },`,
|
||||
},
|
||||
{
|
||||
desc: "mixed builds disabled by type",
|
||||
mixedBuildsEnabled: false,
|
||||
extraBpInfo: `mixed_build_incompatible: true,
|
||||
bazel_module: { bp2build_available: true },`,
|
||||
},
|
||||
{
|
||||
desc: "mixed builds not bp2build available",
|
||||
mixedBuildsEnabled: false,
|
||||
extraBpInfo: `bazel_module: { bp2build_available: false },`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
handlers := GroupFixturePreparers(
|
||||
prepareForMixedBuildTests,
|
||||
PrepareForTestWithArchMutator,
|
||||
FixtureModifyConfig(func(config Config) {
|
||||
config.BazelContext = MockBazelContext{
|
||||
OutputBaseDir: "base",
|
||||
}
|
||||
config.Targets[Windows] = []Target{
|
||||
{Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true},
|
||||
{Windows, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", true},
|
||||
}
|
||||
}),
|
||||
)
|
||||
bp := fmt.Sprintf(baseBp, tc.extraBpInfo)
|
||||
if tc.missingDeps {
|
||||
handlers = GroupFixturePreparers(
|
||||
handlers,
|
||||
PrepareForTestWithAllowMissingDependencies,
|
||||
)
|
||||
} else {
|
||||
bp += depBp
|
||||
}
|
||||
result := handlers.RunTestWithBp(t, bp)
|
||||
|
||||
variant := proptools.StringDefault(tc.variant, "android_arm64_armv8-a")
|
||||
|
||||
m := result.ModuleForTests("foo", variant)
|
||||
mixedBuildModuleInfo := result.TestContext.ModuleProvider(m.Module(), mixedBuildModuleProvider).(mixedBuildModuleInfo)
|
||||
if w, g := tc.mixedBuildsEnabled, mixedBuildModuleInfo.QueuedBazelCall; w != g {
|
||||
t.Errorf("Expected mixed builds enabled %t, got mixed builds enabled %t", w, g)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -354,6 +354,10 @@ type BaseModuleContext interface {
|
||||
|
||||
AddMissingDependencies(missingDeps []string)
|
||||
|
||||
// getMissingDependencies returns the list of missing dependencies.
|
||||
// Calling this function prevents adding new dependencies.
|
||||
getMissingDependencies() []string
|
||||
|
||||
// AddUnconvertedBp2buildDep stores module name of a direct dependency that was not converted via bp2build
|
||||
AddUnconvertedBp2buildDep(dep string)
|
||||
|
||||
@@ -939,7 +943,8 @@ type commonProperties struct {
|
||||
|
||||
NamespaceExportedToMake bool `blueprint:"mutated"`
|
||||
|
||||
MissingDeps []string `blueprint:"mutated"`
|
||||
MissingDeps []string `blueprint:"mutated"`
|
||||
CheckedMissingDeps bool `blueprint:"mutated"`
|
||||
|
||||
// Name and variant strings stored by mutators to enable Module.String()
|
||||
DebugName string `blueprint:"mutated"`
|
||||
@@ -2862,6 +2867,20 @@ func (b *baseModuleContext) AddMissingDependencies(deps []string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *baseModuleContext) checkedMissingDeps() bool {
|
||||
return b.Module().base().commonProperties.CheckedMissingDeps
|
||||
}
|
||||
|
||||
func (b *baseModuleContext) getMissingDependencies() []string {
|
||||
checked := &b.Module().base().commonProperties.CheckedMissingDeps
|
||||
*checked = true
|
||||
var missingDeps []string
|
||||
missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
|
||||
missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
|
||||
missingDeps = FirstUniqueStrings(missingDeps)
|
||||
return missingDeps
|
||||
}
|
||||
|
||||
type AllowDisabledModuleDependency interface {
|
||||
blueprint.DependencyTag
|
||||
AllowDisabledModuleDependency(target Module) bool
|
||||
|
@@ -67,6 +67,8 @@ func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []Registe
|
||||
// collateGloballyRegisteredMutators constructs the list of mutators that have been registered
|
||||
// with the InitRegistrationContext and will be used at runtime.
|
||||
func collateGloballyRegisteredMutators() sortableComponents {
|
||||
// ensure mixed builds mutator is the last mutator
|
||||
finalDeps = append(finalDeps, registerMixedBuildsMutator)
|
||||
return collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps)
|
||||
}
|
||||
|
||||
@@ -885,10 +887,16 @@ func (b *bottomUpMutatorContext) Rename(name string) {
|
||||
}
|
||||
|
||||
func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module {
|
||||
if b.baseModuleContext.checkedMissingDeps() {
|
||||
panic("Adding deps not allowed after checking for missing deps")
|
||||
}
|
||||
return b.bp.AddDependency(module, tag, name...)
|
||||
}
|
||||
|
||||
func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) {
|
||||
if b.baseModuleContext.checkedMissingDeps() {
|
||||
panic("Adding deps not allowed after checking for missing deps")
|
||||
}
|
||||
b.bp.AddReverseDependency(module, tag, name)
|
||||
}
|
||||
|
||||
@@ -938,11 +946,17 @@ func (b *bottomUpMutatorContext) SetDefaultDependencyVariation(variation *string
|
||||
|
||||
func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
|
||||
names ...string) []blueprint.Module {
|
||||
if b.baseModuleContext.checkedMissingDeps() {
|
||||
panic("Adding deps not allowed after checking for missing deps")
|
||||
}
|
||||
return b.bp.AddVariationDependencies(variations, tag, names...)
|
||||
}
|
||||
|
||||
func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation,
|
||||
tag blueprint.DependencyTag, names ...string) []blueprint.Module {
|
||||
if b.baseModuleContext.checkedMissingDeps() {
|
||||
panic("Adding deps not allowed after checking for missing deps")
|
||||
}
|
||||
|
||||
return b.bp.AddFarVariationDependencies(variations, tag, names...)
|
||||
}
|
||||
@@ -952,10 +966,16 @@ func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.Depende
|
||||
}
|
||||
|
||||
func (b *bottomUpMutatorContext) ReplaceDependencies(name string) {
|
||||
if b.baseModuleContext.checkedMissingDeps() {
|
||||
panic("Adding deps not allowed after checking for missing deps")
|
||||
}
|
||||
b.bp.ReplaceDependencies(name)
|
||||
}
|
||||
|
||||
func (b *bottomUpMutatorContext) ReplaceDependenciesIf(name string, predicate blueprint.ReplaceDependencyPredicate) {
|
||||
if b.baseModuleContext.checkedMissingDeps() {
|
||||
panic("Adding deps not allowed after checking for missing deps")
|
||||
}
|
||||
b.bp.ReplaceDependenciesIf(name, predicate)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user