Remove infrastructure to run bp2build
Bug: 315353489
Test: m blueprint_tests
Change-Id: Idcf6377d389b94c39e4e6ff4b8efa8a9f9e78b17
diff --git a/android/Android.bp b/android/Android.bp
index 62f534c..2ac1d5f 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -12,14 +12,11 @@
"sbox_proto",
"soong",
"soong-android-soongconfig",
- "soong-bazel",
- "soong-cquery",
"soong-remoteexec",
"soong-response",
"soong-shared",
"soong-starlark",
"soong-starlark-format",
- "soong-ui-bp2build_metrics_proto",
"soong-ui-metrics_proto",
"soong-android-allowlists",
@@ -38,9 +35,6 @@
"arch.go",
"arch_list.go",
"base_module_context.go",
- "bazel.go",
- "bazel_handler.go",
- "bazel_paths.go",
"buildinfo_prop.go",
"config.go",
"test_config.go",
@@ -106,9 +100,6 @@
"androidmk_test.go",
"apex_test.go",
"arch_test.go",
- "bazel_handler_test.go",
- "bazel_paths_test.go",
- "bazel_test.go",
"config_test.go",
"config_bp2build_test.go",
"configured_jars_test.go",
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index 9b188de..f13659a 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -111,9 +111,6 @@
}
}
- if ctx.Config().Bp2buildMode() { // Skip bp2build
- return
- }
p := PrebuiltSelectionInfoMap{}
ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) {
if m, ok := child.(*apexContributions); ok {
diff --git a/android/arch.go b/android/arch.go
index 152016c..7436660 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -425,7 +425,7 @@
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
+ mctx := bottomUpMutatorContextFactory(bpctx, module, false)
base := module.base()
@@ -570,7 +570,7 @@
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
+ mctx := bottomUpMutatorContextFactory(bpctx, module, false)
base := module.base()
diff --git a/android/base_module_context.go b/android/base_module_context.go
index ec9c888..4312e9b 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -112,8 +112,6 @@
// the first DependencyTag.
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
- ModuleFromName(name string) (blueprint.Module, bool)
-
// VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
// direct dependencies on the same module visit will be called multiple times on that module
// and OtherModuleDependencyTag will return a different tag for each.
@@ -209,12 +207,6 @@
// 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)
-
- // AddMissingBp2buildDep stores the module name of a direct dependency that was not found.
- AddMissingBp2buildDep(dep string)
-
Target() Target
TargetPrimary() bool
@@ -243,12 +235,8 @@
strictVisitDeps bool // If true, enforce that all dependencies are enabled
- bazelConversionMode bool
}
-func (b *baseModuleContext) isBazelConversionMode() bool {
- return b.bazelConversionMode
-}
func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
return b.bp.OtherModuleName(m)
}
@@ -296,18 +284,6 @@
return b.bp
}
-// AddUnconvertedBp2buildDep stores module name of a dependency that was not converted to Bazel.
-func (b *baseModuleContext) AddUnconvertedBp2buildDep(dep string) {
- unconvertedDeps := &b.Module().base().commonProperties.BazelConversionStatus.UnconvertedDeps
- *unconvertedDeps = append(*unconvertedDeps, dep)
-}
-
-// AddMissingBp2buildDep stores module name of a dependency that was not found in a Android.bp file.
-func (b *baseModuleContext) AddMissingBp2buildDep(dep string) {
- missingDeps := &b.Module().base().commonProperties.BazelConversionStatus.MissingDeps
- *missingDeps = append(*missingDeps, dep)
-}
-
func (b *baseModuleContext) AddMissingDependencies(deps []string) {
if deps != nil {
missingDeps := &b.Module().base().commonProperties.MissingDeps
@@ -435,27 +411,6 @@
return b.getDirectDepFirstTag(name)
}
-func (b *baseModuleContext) ModuleFromName(name string) (blueprint.Module, bool) {
- if !b.isBazelConversionMode() {
- panic("cannot call ModuleFromName if not in bazel conversion mode")
- }
- var m blueprint.Module
- var ok bool
- if moduleName, _ := SrcIsModuleWithTag(name); moduleName != "" {
- m, ok = b.bp.ModuleFromName(moduleName)
- } else {
- m, ok = b.bp.ModuleFromName(name)
- }
- if !ok {
- return m, ok
- }
- // If this module is not preferred, tried to get the prebuilt version instead
- if a, aOk := m.(Module); aOk && !IsModulePrebuilt(a) && !IsModulePreferred(a) {
- return b.ModuleFromName("prebuilt_" + name)
- }
- return m, ok
-}
-
func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
b.bp.VisitDirectDeps(visit)
}
diff --git a/android/bazel.go b/android/bazel.go
deleted file mode 100644
index 1602b9b..0000000
--- a/android/bazel.go
+++ /dev/null
@@ -1,784 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android
-
-import (
- "bufio"
- "errors"
- "fmt"
- "strings"
-
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
- "github.com/google/blueprint/proptools"
-
- "android/soong/android/allowlists"
-)
-
-const (
- // A sentinel value to be used as a key in Bp2BuildConfig for modules with
- // no package path. This is also the module dir for top level Android.bp
- // modules.
- Bp2BuildTopLevel = "."
-)
-
-type MixedBuildEnabledStatus int
-
-const (
- // This module can be mixed_built.
- MixedBuildEnabled = iota
-
- // There is a technical incompatibility preventing this module from being
- // bazel-analyzed. Note: the module might also be incompatible.
- TechnicalIncompatibility
-
- // This module cannot be mixed_built due to some incompatibility with it
- // 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
-// such as aidl_library or proto_library.
-type FileGroupAsLibrary interface {
- ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool
- ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool
- GetAidlLibraryLabel(ctx BazelConversionPathContext) string
- GetProtoLibraryLabel(ctx BazelConversionPathContext) string
-}
-
-type BazelConversionStatus struct {
- // Information about _all_ bp2build targets generated by this module. Multiple targets are
- // supported as Soong handles some things within a single target that we may choose to split into
- // multiple targets, e.g. renderscript, protos, yacc within a cc module.
- Bp2buildInfo []bp2buildInfo `blueprint:"mutated"`
-
- // UnconvertedBp2buildDep stores the module names of direct dependency that were not converted to
- // Bazel
- UnconvertedDeps []string `blueprint:"mutated"`
-
- // MissingBp2buildDep stores the module names of direct dependency that were not found
- MissingDeps []string `blueprint:"mutated"`
-
- // If non-nil, indicates that the module could not be converted successfully
- // with bp2build. This will describe the reason the module could not be converted.
- UnconvertedReason *UnconvertedReason
-
- // The Partition this module will be installed on.
- // TODO(b/306200980) Investigate how to handle modules that are installed in multiple
- // partitions.
- Partition string `blueprint:"mutated"`
-}
-
-// The reason a module could not be converted to a BUILD target via bp2build.
-// This should match bp2build_metrics_proto.UnconvertedReason, but omits private
-// proto-related fields that prevent copying this struct.
-type UnconvertedReason struct {
- // Should correspond to a valid value in bp2build_metrics_proto.UnconvertedReasonType.
- // A raw int is used here instead, because blueprint logic requires that all transitive
- // fields of module definitions be primitives.
- ReasonType int
- Detail string
-}
-
-type BazelModuleProperties struct {
- // The label of the Bazel target replacing this Soong module. When run in conversion mode, this
- // will import the handcrafted build target into the autogenerated file. Note: this may result in
- // a conflict due to duplicate targets if bp2build_available is also set.
- Label *string
-
- // If true, bp2build will generate the converted Bazel target for this module. Note: this may
- // cause a conflict due to the duplicate targets if label is also set.
- //
- // This is a bool pointer to support tristates: true, false, not set.
- //
- // To opt in a module, set bazel_module: { bp2build_available: true }
- // To opt out a module, set bazel_module: { bp2build_available: false }
- // To defer the default setting for the directory, do not set the value.
- Bp2build_available *bool
-
- // CanConvertToBazel is set via InitBazelModule to indicate that a module type can be converted to
- // Bazel with Bp2build.
- CanConvertToBazel bool `blueprint:"mutated"`
-}
-
-// Properties contains common module properties for Bazel migration purposes.
-type properties struct {
- // In "Bazel mixed build" mode, this represents the Bazel target replacing
- // this Soong module.
- Bazel_module BazelModuleProperties
-}
-
-// namespacedVariableProperties is a map from a string representing a Soong
-// config variable namespace, like "android" or "vendor_name" to a slice of
-// pointer to a struct containing a single field called Soong_config_variables
-// whose value mirrors the structure in the Blueprint file.
-type namespacedVariableProperties map[string][]interface{}
-
-// BazelModuleBase contains the property structs with metadata for modules which can be converted to
-// Bazel.
-type BazelModuleBase struct {
- bazelProperties properties
-
- // namespacedVariableProperties is used for soong_config_module_type support
- // in bp2build. Soong config modules allow users to set module properties
- // based on custom product variables defined in Android.bp files. These
- // variables are namespaced to prevent clobbering, especially when set from
- // Makefiles.
- namespacedVariableProperties namespacedVariableProperties
-
- // baseModuleType is set when this module was created from a module type
- // defined by a soong_config_module_type. Every soong_config_module_type
- // "wraps" another module type, e.g. a soong_config_module_type can wrap a
- // cc_defaults to a custom_cc_defaults, or cc_binary to a custom_cc_binary.
- // This baseModuleType is set to the wrapped module type.
- baseModuleType string
-}
-
-// Bazelable is specifies the interface for modules that can be converted to Bazel.
-type Bazelable interface {
- bazelProps() *properties
- HasHandcraftedLabel() bool
- HandcraftedLabel() string
- GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
- ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool
- shouldConvertWithBp2build(shouldConvertModuleContext, shouldConvertParams) bool
-
- // ConvertWithBp2build either converts the module to a Bazel build target or
- // declares the module as unconvertible (for logging and metrics).
- // Modules must implement this function to be bp2build convertible. The function
- // must either create at least one Bazel target module (using ctx.CreateBazelTargetModule or
- // its related functions), or declare itself unconvertible using ctx.MarkBp2buildUnconvertible.
- ConvertWithBp2build(ctx Bp2buildMutatorContext)
-
- // namespacedVariableProps is a map from a soong config variable namespace
- // (e.g. acme, android) to a map of interfaces{}, which are really
- // reflect.Struct pointers, representing the value of the
- // soong_config_variables property of a module. The struct pointer is the
- // one with the single member called Soong_config_variables, which itself is
- // a struct containing fields for each supported feature in that namespace.
- //
- // The reason for using a slice of interface{} is to support defaults
- // propagation of the struct pointers.
- namespacedVariableProps() namespacedVariableProperties
- setNamespacedVariableProps(props namespacedVariableProperties)
- BaseModuleType() string
- SetBaseModuleType(baseModuleType string)
-}
-
-// ApiProvider is implemented by modules that contribute to an API surface
-type ApiProvider interface {
- ConvertWithApiBp2build(ctx TopDownMutatorContext)
-}
-
-// MixedBuildBuildable is an interface that module types should implement in order
-// to be "handled by Bazel" in a mixed build.
-type MixedBuildBuildable interface {
- // IsMixedBuildSupported returns true if and only if this module should be
- // "handled by Bazel" in a mixed build.
- // This "escape hatch" allows modules with corner-case scenarios to opt out
- // of being built with Bazel.
- IsMixedBuildSupported(ctx BaseModuleContext) bool
-
- // QueueBazelCall invokes request-queueing functions on the BazelContext
- // so that these requests are handled when Bazel's cquery is invoked.
- QueueBazelCall(ctx BaseModuleContext)
-
- // ProcessBazelQueryResponse uses Bazel information (obtained from the BazelContext)
- // to set module fields and providers to propagate this module's metadata upstream.
- // This effectively "bridges the gap" between Bazel and Soong in a mixed build.
- // Soong modules depending on this module should be oblivious to the fact that
- // this module was handled by Bazel.
- ProcessBazelQueryResponse(ctx ModuleContext)
-}
-
-// BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules.
-type BazelModule interface {
- Module
- Bazelable
-}
-
-// InitBazelModule is a wrapper function that decorates a BazelModule with Bazel-conversion
-// properties.
-func InitBazelModule(module BazelModule) {
- module.AddProperties(module.bazelProps())
- module.bazelProps().Bazel_module.CanConvertToBazel = true
-}
-
-// BazelHandcraftedHook is a load hook to possibly register the current module as
-// a "handcrafted" Bazel target of a given name. If the current module should be
-// registered in this way, the hook function should return the target name. If
-// it should not be registered in this way, this function should return the empty string.
-type BazelHandcraftedHook func(ctx LoadHookContext) string
-
-// AddBazelHandcraftedHook adds a load hook to (maybe) mark the given module so that
-// it is treated by bp2build as if it has a handcrafted Bazel target.
-func AddBazelHandcraftedHook(module BazelModule, hook BazelHandcraftedHook) {
- AddLoadHook(module, func(ctx LoadHookContext) {
- var targetName string = hook(ctx)
- if len(targetName) > 0 {
- moduleDir := ctx.ModuleDir()
- if moduleDir == Bp2BuildTopLevel {
- moduleDir = ""
- }
- label := fmt.Sprintf("//%s:%s", moduleDir, targetName)
- module.bazelProps().Bazel_module.Label = &label
- }
- })
-}
-
-// bazelProps returns the Bazel properties for the given BazelModuleBase.
-func (b *BazelModuleBase) bazelProps() *properties {
- return &b.bazelProperties
-}
-
-func (b *BazelModuleBase) namespacedVariableProps() namespacedVariableProperties {
- return b.namespacedVariableProperties
-}
-
-func (b *BazelModuleBase) setNamespacedVariableProps(props namespacedVariableProperties) {
- b.namespacedVariableProperties = props
-}
-
-func (b *BazelModuleBase) BaseModuleType() string {
- return b.baseModuleType
-}
-
-func (b *BazelModuleBase) SetBaseModuleType(baseModuleType string) {
- b.baseModuleType = baseModuleType
-}
-
-// HasHandcraftedLabel returns whether this module has a handcrafted Bazel label.
-func (b *BazelModuleBase) HasHandcraftedLabel() bool {
- return b.bazelProperties.Bazel_module.Label != nil
-}
-
-// HandcraftedLabel returns the handcrafted label for this module, or empty string if there is none
-func (b *BazelModuleBase) HandcraftedLabel() string {
- return proptools.String(b.bazelProperties.Bazel_module.Label)
-}
-
-// GetBazelLabel returns the Bazel label for the given BazelModuleBase.
-func (b *BazelModuleBase) GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
- if b.HasHandcraftedLabel() {
- return b.HandcraftedLabel()
- }
- if b.ShouldConvertWithBp2build(ctx) {
- return bp2buildModuleLabel(ctx, module)
- }
- panic(fmt.Errorf("requested non-existent label for module %s", module.Name()))
-}
-
-type Bp2BuildConversionAllowlist struct {
- // Configure modules in these directories to enable bp2build_available: true or false by default.
- defaultConfig allowlists.Bp2BuildConfig
-
- // Keep any existing BUILD files (and do not generate new BUILD files) for these directories
- // in the synthetic Bazel workspace.
- keepExistingBuildFile map[string]bool
-
- // Per-module allowlist to always opt modules into both bp2build and Bazel Dev Mode mixed
- // builds. These modules are usually in directories with many other modules that are not ready
- // for conversion.
- //
- // A module can either be in this list or its directory allowlisted entirely
- // in bp2buildDefaultConfig, but not both at the same time.
- moduleAlwaysConvert map[string]bool
-
- // Per-module-type allowlist to always opt modules in to both bp2build and
- // Bazel Dev Mode mixed builds when they have the same type as one listed.
- moduleTypeAlwaysConvert map[string]bool
-
- // Per-module denylist to always opt modules out of bp2build conversion.
- moduleDoNotConvert map[string]bool
-}
-
-// NewBp2BuildAllowlist creates a new, empty Bp2BuildConversionAllowlist
-// which can be populated using builder pattern Set* methods
-func NewBp2BuildAllowlist() Bp2BuildConversionAllowlist {
- return Bp2BuildConversionAllowlist{
- allowlists.Bp2BuildConfig{},
- map[string]bool{},
- map[string]bool{},
- map[string]bool{},
- map[string]bool{},
- }
-}
-
-// SetDefaultConfig copies the entries from defaultConfig into the allowlist
-func (a Bp2BuildConversionAllowlist) SetDefaultConfig(defaultConfig allowlists.Bp2BuildConfig) Bp2BuildConversionAllowlist {
- if a.defaultConfig == nil {
- a.defaultConfig = allowlists.Bp2BuildConfig{}
- }
- for k, v := range defaultConfig {
- a.defaultConfig[k] = v
- }
-
- return a
-}
-
-// SetKeepExistingBuildFile copies the entries from keepExistingBuildFile into the allowlist
-func (a Bp2BuildConversionAllowlist) SetKeepExistingBuildFile(keepExistingBuildFile map[string]bool) Bp2BuildConversionAllowlist {
- if a.keepExistingBuildFile == nil {
- a.keepExistingBuildFile = map[string]bool{}
- }
- for k, v := range keepExistingBuildFile {
- a.keepExistingBuildFile[k] = v
- }
-
- return a
-}
-
-// SetModuleAlwaysConvertList copies the entries from moduleAlwaysConvert into the allowlist
-func (a Bp2BuildConversionAllowlist) SetModuleAlwaysConvertList(moduleAlwaysConvert []string) Bp2BuildConversionAllowlist {
- if a.moduleAlwaysConvert == nil {
- a.moduleAlwaysConvert = map[string]bool{}
- }
- for _, m := range moduleAlwaysConvert {
- a.moduleAlwaysConvert[m] = true
- }
-
- return a
-}
-
-// SetModuleTypeAlwaysConvertList copies the entries from moduleTypeAlwaysConvert into the allowlist
-func (a Bp2BuildConversionAllowlist) SetModuleTypeAlwaysConvertList(moduleTypeAlwaysConvert []string) Bp2BuildConversionAllowlist {
- if a.moduleTypeAlwaysConvert == nil {
- a.moduleTypeAlwaysConvert = map[string]bool{}
- }
- for _, m := range moduleTypeAlwaysConvert {
- a.moduleTypeAlwaysConvert[m] = true
- }
-
- return a
-}
-
-// SetModuleDoNotConvertList copies the entries from moduleDoNotConvert into the allowlist
-func (a Bp2BuildConversionAllowlist) SetModuleDoNotConvertList(moduleDoNotConvert []string) Bp2BuildConversionAllowlist {
- if a.moduleDoNotConvert == nil {
- a.moduleDoNotConvert = map[string]bool{}
- }
- for _, m := range moduleDoNotConvert {
- a.moduleDoNotConvert[m] = true
- }
-
- return a
-}
-
-// ShouldKeepExistingBuildFileForDir returns whether an existing BUILD file should be
-// added to the build symlink forest based on the current global configuration.
-func (a Bp2BuildConversionAllowlist) ShouldKeepExistingBuildFileForDir(dir string) bool {
- if _, ok := a.keepExistingBuildFile[dir]; ok {
- // Exact dir match
- return true
- }
- var i int
- // Check if subtree match
- for {
- j := strings.Index(dir[i:], "/")
- if j == -1 {
- return false //default
- }
- prefix := dir[0 : i+j]
- i = i + j + 1 // skip the "/"
- if recursive, ok := a.keepExistingBuildFile[prefix]; ok && recursive {
- return true
- }
- }
-}
-
-var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist")
-var bp2buildAllowlist OncePer
-
-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)
- }).(Bp2BuildConversionAllowlist)
-}
-
-// MixedBuildsEnabled returns a MixedBuildEnabledStatus regarding whether
-// a module is ready to be replaced by a converted or handcrafted Bazel target.
-// 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 {
- 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) &&
- ctx.Config().BazelContext.IsModuleNameAllowed(module.Name(), withinApex)
- ctx.Config().LogMixedBuild(ctx, mixedBuildEnabled)
-
- if mixedBuildEnabled {
- return MixedBuildEnabled
- }
- return ModuleIncompatibility
-}
-
-func isGoModule(module blueprint.Module) bool {
- if _, ok := module.(*bootstrap.GoPackage); ok {
- return true
- }
- if _, ok := module.(*bootstrap.GoBinary); ok {
- return true
- }
- return false
-}
-
-// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
-func convertedToBazel(ctx BazelConversionContext, module blueprint.Module) bool {
- // Special-case bootstrap_go_package and bootstrap_go_binary
- // These do not implement Bazelable, but have been converted
- if isGoModule(module) {
- return true
- }
- b, ok := module.(Bazelable)
- if !ok {
- return false
- }
-
- return b.HasHandcraftedLabel() || b.shouldConvertWithBp2build(ctx, shouldConvertParams{
- module: module,
- moduleDir: ctx.OtherModuleDir(module),
- moduleName: ctx.OtherModuleName(module),
- moduleType: ctx.OtherModuleType(module),
- })
-}
-
-type ShouldConvertWithBazelContext interface {
- ModuleErrorf(format string, args ...interface{})
- Module() Module
- Config() Config
- ModuleType() string
- ModuleName() string
- ModuleDir() string
-}
-
-// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build
-func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool {
- return b.shouldConvertWithBp2build(ctx, shouldConvertParams{
- module: ctx.Module(),
- moduleDir: ctx.ModuleDir(),
- moduleName: ctx.ModuleName(),
- moduleType: ctx.ModuleType(),
- })
-}
-
-type bazelOtherModuleContext interface {
- ModuleErrorf(format string, args ...interface{})
- Config() Config
- OtherModuleType(m blueprint.Module) string
- OtherModuleName(m blueprint.Module) string
- OtherModuleDir(m blueprint.Module) string
-}
-
-func isPlatformIncompatible(osType OsType, arch ArchType) bool {
- return osType == Windows || // Windows toolchains are not currently supported.
- osType == LinuxBionic || // Linux Bionic toolchains are not currently supported.
- osType == LinuxMusl || // Linux musl toolchains are not currently supported (b/259266326).
- arch == Riscv64 // TODO(b/262192655) Riscv64 toolchains are not currently supported.
-}
-
-type shouldConvertModuleContext interface {
- ModuleErrorf(format string, args ...interface{})
- Config() Config
-}
-
-type shouldConvertParams struct {
- module blueprint.Module
- moduleType string
- moduleDir string
- moduleName string
-}
-
-func (b *BazelModuleBase) shouldConvertWithBp2build(ctx shouldConvertModuleContext, p shouldConvertParams) bool {
- if !b.bazelProps().Bazel_module.CanConvertToBazel {
- return false
- }
-
- module := p.module
-
- propValue := b.bazelProperties.Bazel_module.Bp2build_available
- packagePath := moduleDirWithPossibleOverride(ctx, module, p.moduleDir)
-
- // Modules in unit tests which are enabled in the allowlist by type or name
- // trigger this conditional because unit tests run under the "." package path
- isTestModule := packagePath == Bp2BuildTopLevel && proptools.BoolDefault(propValue, false)
- if isTestModule {
- return true
- }
-
- moduleName := moduleNameWithPossibleOverride(ctx, module, p.moduleName)
- // use "prebuilt_" + original module name as the java_import(_host) module name,
- // to avoid the failure that a normal module and a prebuilt module with
- // the same name are both allowlisted. This cannot be applied to all the *_import
- // module types. For example, android_library_import has to use original module
- // name here otherwise the *-nodeps targets cannot be handled correctly.
- // TODO(b/304385140): remove this special casing
- if p.moduleType == "java_import" || p.moduleType == "java_import_host" {
- moduleName = module.Name()
- }
-
- allowlist := ctx.Config().Bp2buildPackageConfig
-
- moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName]
- moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[p.moduleType]
- allowlistConvert := moduleNameAllowed || moduleTypeAllowed
- if moduleNameAllowed && moduleTypeAllowed {
- ctx.ModuleErrorf("A module %q of type %q cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert", moduleName, p.moduleType)
- return false
- }
-
- if allowlist.moduleDoNotConvert[moduleName] {
- if moduleNameAllowed {
- ctx.ModuleErrorf("a module %q cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert", moduleName)
- }
- return false
- }
-
- // This is a tristate value: true, false, or unset.
- if ok, directoryPath := bp2buildDefaultTrueRecursively(packagePath, allowlist.defaultConfig); ok {
- if moduleNameAllowed {
- ctx.ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+
- " or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'"+
- " Module: '%s'", directoryPath, moduleName)
- return false
- }
-
- // Allow modules to explicitly opt-out.
- return proptools.BoolDefault(propValue, true)
- }
-
- // Allow modules to explicitly opt-in.
- return proptools.BoolDefault(propValue, allowlistConvert)
-}
-
-// bp2buildDefaultTrueRecursively checks that the package contains a prefix from the
-// set of package prefixes where all modules must be converted. That is, if the
-// package is x/y/z, and the list contains either x, x/y, or x/y/z, this function will
-// return true.
-//
-// However, if the package is x/y, and it matches a Bp2BuildDefaultFalse "x/y" entry
-// exactly, this module will return false early.
-//
-// This function will also return false if the package doesn't match anything in
-// the config.
-//
-// This function will also return the allowlist entry which caused a particular
-// package to be enabled. Since packages can be enabled via a recursive declaration,
-// the path returned will not always be the same as the one provided.
-func bp2buildDefaultTrueRecursively(packagePath string, config allowlists.Bp2BuildConfig) (bool, string) {
- // Check if the package path has an exact match in the config.
- if config[packagePath] == allowlists.Bp2BuildDefaultTrue || config[packagePath] == allowlists.Bp2BuildDefaultTrueRecursively {
- return true, packagePath
- } else if config[packagePath] == allowlists.Bp2BuildDefaultFalse || config[packagePath] == allowlists.Bp2BuildDefaultFalseRecursively {
- return false, packagePath
- }
-
- // If not, check for the config recursively.
- packagePrefix := packagePath
-
- // e.g. for x/y/z, iterate over x/y, then x, taking the most-specific value from the allowlist.
- for strings.Contains(packagePrefix, "/") {
- dirIndex := strings.LastIndex(packagePrefix, "/")
- packagePrefix = packagePrefix[:dirIndex]
- switch value := config[packagePrefix]; value {
- case allowlists.Bp2BuildDefaultTrueRecursively:
- // package contains this prefix and this prefix should convert all modules
- return true, packagePrefix
- case allowlists.Bp2BuildDefaultFalseRecursively:
- //package contains this prefix and this prefix should NOT convert any modules
- return false, packagePrefix
- }
- // Continue to the next part of the package dir.
-
- }
-
- return false, packagePath
-}
-
-func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("bp2build_conversion", bp2buildConversionMutator).Parallel()
- ctx.BottomUp("bp2build_deps", bp2buildDepsMutator).Parallel()
-}
-
-func bp2buildConversionMutator(ctx BottomUpMutatorContext) {
- // If an existing BUILD file in the module directory has a target defined
- // with this same name as this module, assume that this is an existing
- // definition for this target.
- if ctx.Config().HasBazelBuildTargetInSource(ctx.ModuleDir(), ctx.ModuleName()) {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, ctx.ModuleName())
- return
- }
- bModule, ok := ctx.Module().(Bazelable)
- if !ok {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
- return
- }
- // There may be cases where the target is created by a macro rather than in a BUILD file, those
- // should be captured as well.
- if bModule.HasHandcraftedLabel() {
- // Defer to the BUILD target. Generating an additional target would
- // cause a BUILD file conflict.
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "")
- return
- }
- // TODO: b/285631638 - Differentiate between denylisted modules and missing bp2build capabilities.
- if !bModule.shouldConvertWithBp2build(ctx, shouldConvertParams{
- module: ctx.Module(),
- moduleDir: ctx.ModuleDir(),
- moduleName: ctx.ModuleName(),
- moduleType: ctx.ModuleType(),
- }) {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "")
- return
- }
- if ctx.Module().base().GetUnconvertedReason() != nil {
- return
- }
-
- bModule.ConvertWithBp2build(ctx)
-
- installCtx := &baseModuleContextToModuleInstallPathContext{ctx}
- ctx.Module().base().setPartitionForBp2build(modulePartition(installCtx, true))
-
- if len(ctx.Module().base().Bp2buildTargets()) == 0 && ctx.Module().base().GetUnconvertedReason() == nil {
- panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName()))
- }
-
- // If an existing BUILD file in the module directory has a target defined
- // with the same name as any target generated by this module, assume that this
- // is an existing definition for this target. (These generated target names
- // may be different than the module name, as checked at the beginning of this function!)
- for _, targetInfo := range ctx.Module().base().Bp2buildTargets() {
- if ctx.Config().HasBazelBuildTargetInSource(targetInfo.TargetPackage(), targetInfo.TargetName()) {
- // Defer to the BUILD target. Generating an additional target would
- // cause a BUILD file conflict.
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, targetInfo.TargetName())
- return
- }
- }
-}
-
-// TODO: b/285631638 - Add this as a new mutator to the bp2build conversion mutators.
-// Currently, this only exists to prepare test coverage for the launch of this feature.
-func bp2buildDepsMutator(ctx BottomUpMutatorContext) {
- if ctx.Module().base().GetUnconvertedReason() != nil {
- return
- }
-
- if len(ctx.Module().GetMissingBp2buildDeps()) > 0 {
- exampleDep := ctx.Module().GetMissingBp2buildDeps()[0]
- ctx.MarkBp2buildUnconvertible(
- bp2build_metrics_proto.UnconvertedReasonType_UNCONVERTED_DEP, exampleDep)
- }
-
- // Transitively mark modules unconvertible with the following set of conditions.
- ctx.VisitDirectDeps(func(dep Module) {
- if dep.base().GetUnconvertedReason() == nil {
- return
- }
-
- if dep.base().GetUnconvertedReason().ReasonType ==
- int(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE) {
- return
- }
-
- if ctx.OtherModuleDependencyTag(dep) != Bp2buildDepTag {
- return
- }
-
- ctx.MarkBp2buildUnconvertible(
- bp2build_metrics_proto.UnconvertedReasonType_UNCONVERTED_DEP, dep.Name())
- })
-}
-
-// GetMainClassInManifest scans the manifest file specified in filepath and returns
-// the value of attribute Main-Class in the manifest file if it exists, or returns error.
-// WARNING: this is for bp2build converters of java_* modules only.
-func GetMainClassInManifest(c Config, filepath string) (string, error) {
- file, err := c.fs.Open(filepath)
- if err != nil {
- return "", err
- }
- defer file.Close()
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- line := scanner.Text()
- if strings.HasPrefix(line, "Main-Class:") {
- return strings.TrimSpace(line[len("Main-Class:"):]), nil
- }
- }
-
- return "", errors.New("Main-Class is not found.")
-}
-
-func AttachValidationActions(ctx ModuleContext, outputFilePath Path, validations Paths) ModuleOutPath {
- validatedOutputFilePath := PathForModuleOut(ctx, "validated", outputFilePath.Base())
- ctx.Build(pctx, BuildParams{
- Rule: CpNoPreserveSymlink,
- Description: "run validations " + outputFilePath.Base(),
- Output: validatedOutputFilePath,
- Input: outputFilePath,
- Validations: validations,
- })
- return validatedOutputFilePath
-}
-
-func RunsOn(hostSupported bool, deviceSupported bool, unitTest bool) []string {
- var runsOn []string
-
- if hostSupported && deviceSupported {
- runsOn = []string{"host_without_device", "device"}
- } else if hostSupported {
- if unitTest {
- runsOn = []string{"host_without_device"}
- } else {
- runsOn = []string{"host_with_device"}
- }
- } else if deviceSupported {
- runsOn = []string{"device"}
- }
-
- return runsOn
-}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
deleted file mode 100644
index 0c65415..0000000
--- a/android/bazel_handler.go
+++ /dev/null
@@ -1,1593 +0,0 @@
-// Copyright 2020 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android
-
-import (
- "bytes"
- "crypto/sha1"
- "encoding/hex"
- "fmt"
- "os"
- "path"
- "path/filepath"
- "regexp"
- "runtime"
- "sort"
- "strings"
- "sync"
-
- "android/soong/android/allowlists"
- "android/soong/bazel/cquery"
- "android/soong/shared"
- "android/soong/starlark_import"
-
- "android/soong/bazel"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/metrics"
-)
-
-var (
- _ = pctx.HostBinToolVariable("bazelBuildRunfilesTool", "build-runfiles")
- buildRunfilesRule = pctx.AndroidStaticRule("bazelBuildRunfiles", blueprint.RuleParams{
- Command: "${bazelBuildRunfilesTool} ${in} ${outDir}",
- Depfile: "",
- Description: "",
- CommandDeps: []string{"${bazelBuildRunfilesTool}"},
- }, "outDir")
-)
-
-func registerMixedBuildsMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("mixed_builds_prep", mixedBuildsPrepareMutator).Parallel()
-}
-
-func RegisterMixedBuildsMutator(ctx RegistrationContext) {
- ctx.FinalDepsMutators(registerMixedBuildsMutator)
-}
-
-func mixedBuildsPrepareMutator(ctx BottomUpMutatorContext) {
- if m := ctx.Module(); m.Enabled() {
- if mixedBuildMod, ok := m.(MixedBuildBuildable); ok {
- mixedBuildEnabled := MixedBuildsEnabled(ctx)
- queueMixedBuild := mixedBuildMod.IsMixedBuildSupported(ctx) && mixedBuildEnabled == MixedBuildEnabled
- if queueMixedBuild {
- mixedBuildMod.QueueBazelCall(ctx)
- }
- }
- }
-}
-
-type cqueryRequest interface {
- // Name returns a string name for this request type. Such request type names must be unique,
- // and must only consist of alphanumeric characters.
- Name() string
-
- // StarlarkFunctionBody returns a starlark function body to process this request type.
- // The returned string is the body of a Starlark function which obtains
- // all request-relevant information about a target and returns a string containing
- // this information.
- // The function should have the following properties:
- // - The arguments are `target` (a configured target) and `id_string` (the label + configuration).
- // - The return value must be a string.
- // - The function body should not be indented outside of its own scope.
- StarlarkFunctionBody() string
-}
-
-// Portion of cquery map key to describe target configuration.
-type configKey struct {
- arch string
- osType OsType
- apexKey ApexConfigKey
-}
-
-type ApexConfigKey struct {
- WithinApex bool
- ApexSdkVersion string
- ApiDomain string
-}
-
-func (c ApexConfigKey) String() string {
- return fmt.Sprintf("%s_%s_%s", withinApexToString(c.WithinApex), c.ApexSdkVersion, c.ApiDomain)
-}
-
-func withinApexToString(withinApex bool) string {
- if withinApex {
- return "within_apex"
- }
- return ""
-}
-
-func (c configKey) String() string {
- return fmt.Sprintf("%s::%s::%s", c.arch, c.osType, c.apexKey)
-}
-
-// Map key to describe bazel cquery requests.
-type cqueryKey struct {
- label string
- requestType cqueryRequest
- configKey configKey
-}
-
-func makeCqueryKey(label string, cqueryRequest cqueryRequest, cfgKey configKey) cqueryKey {
- if strings.HasPrefix(label, "//") {
- // Normalize Bazel labels to specify main repository explicitly.
- label = "@" + label
- }
- return cqueryKey{label, cqueryRequest, cfgKey}
-}
-
-func (c cqueryKey) String() string {
- return fmt.Sprintf("cquery(%s,%s,%s)", c.label, c.requestType.Name(), c.configKey)
-}
-
-type invokeBazelContext interface {
- GetEventHandler() *metrics.EventHandler
-}
-
-// BazelContext is a context object useful for interacting with Bazel during
-// the course of a build. Use of Bazel to evaluate part of the build graph
-// is referred to as a "mixed build". (Some modules are managed by Soong,
-// some are managed by Bazel). To facilitate interop between these build
-// subgraphs, Soong may make requests to Bazel and evaluate their responses
-// so that Soong modules may accurately depend on Bazel targets.
-type BazelContext interface {
- // Add a cquery request to the bazel request queue. All queued requests
- // will be sent to Bazel on a subsequent invocation of InvokeBazel.
- QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey)
-
- // ** Cquery Results Retrieval Functions
- // The below functions pertain to retrieving cquery results from a prior
- // InvokeBazel function call and parsing the results.
-
- // Returns result files built by building the given bazel target label.
- GetOutputFiles(label string, cfgKey configKey) ([]string, error)
-
- // Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order).
- GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error)
-
- // Returns the results of the GetApexInfo query (including output files)
- GetApexInfo(label string, cfgkey configKey) (cquery.ApexInfo, error)
-
- // Returns the results of the GetCcUnstrippedInfo query
- GetCcUnstrippedInfo(label string, cfgkey configKey) (cquery.CcUnstrippedInfo, error)
-
- // Returns the results of the GetPrebuiltFileInfo query
- GetPrebuiltFileInfo(label string, cfgKey configKey) (cquery.PrebuiltFileInfo, error)
-
- // ** end Cquery Results Retrieval Functions
-
- // Issues commands to Bazel to receive results for all cquery requests
- // queued in the BazelContext. The ctx argument is optional and is only
- // used for performance data collection
- InvokeBazel(config Config, ctx invokeBazelContext) error
-
- // 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).
- IsModuleNameAllowed(moduleName string, withinApex bool) bool
-
- // Returns the bazel output base (the root directory for all bazel intermediate outputs).
- OutputBase() string
-
- // Returns build statements which should get registered to reflect Bazel's outputs.
- BuildStatementsToRegister() []*bazel.BuildStatement
-
- // Returns the depsets defined in Bazel's aquery response.
- AqueryDepsets() []bazel.AqueryDepset
-
- QueueBazelSandwichCqueryRequests(config Config) error
-}
-
-type bazelRunner interface {
- issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (output string, errorMessage string, error error)
-}
-
-type bazelPaths struct {
- homeDir string
- bazelPath string
- outputBase string
- workspaceDir string
- soongOutDir string
- metricsDir string
- bazelDepsFile string
-}
-
-// A context object which tracks queued requests that need to be made to Bazel,
-// and their results after the requests have been made.
-type mixedBuildBazelContext struct {
- bazelRunner
- paths *bazelPaths
- // cquery requests that have not yet been issued to Bazel. This list is maintained
- // in a sorted state, and is guaranteed to have no duplicates.
- requests []cqueryKey
- requestMutex sync.Mutex // requests can be written in parallel
-
- results map[cqueryKey]string // Results of cquery requests after Bazel invocations
-
- // Build statements which should get registered to reflect Bazel's outputs.
- buildStatements []*bazel.BuildStatement
-
- // 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
- // DCLA modules are enabled when used in apex.
- bazelDclaEnabledModules map[string]bool
-
- targetProduct string
- targetBuildVariant string
-}
-
-var _ BazelContext = &mixedBuildBazelContext{}
-
-// A bazel context to use when Bazel is disabled.
-type noopBazelContext struct{}
-
-var _ BazelContext = noopBazelContext{}
-
-func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) GetOutputFiles(_ string, _ configKey) ([]string, error) {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) GetCcInfo(_ string, _ configKey) (cquery.CcInfo, error) {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexInfo, error) {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) {
- //TODO implement me
- panic("implement me")
-}
-
-func (n noopBazelContext) GetPrebuiltFileInfo(_ string, _ configKey) (cquery.PrebuiltFileInfo, error) {
- panic("implement me")
-}
-
-func (n noopBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
- panic("unimplemented")
-}
-
-func (m noopBazelContext) OutputBase() string {
- return ""
-}
-
-func (n noopBazelContext) IsModuleNameAllowed(_ string, _ bool) bool {
- return false
-}
-
-func (m noopBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
- return []*bazel.BuildStatement{}
-}
-
-func (m noopBazelContext) AqueryDepsets() []bazel.AqueryDepset {
- return []bazel.AqueryDepset{}
-}
-
-// A bazel context to use for tests.
-type MockBazelContext struct {
- OutputBaseDir string
-
- LabelToOutputFiles map[string][]string
- LabelToCcInfo map[string]cquery.CcInfo
- LabelToPythonBinary map[string]string
- LabelToApexInfo map[string]cquery.ApexInfo
- LabelToCcBinary map[string]cquery.CcUnstrippedInfo
- LabelToPrebuiltFileInfo map[string]cquery.PrebuiltFileInfo
-
- BazelRequests map[string]bool
-}
-
-func (m MockBazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
- key := BuildMockBazelContextRequestKey(label, requestType, cfgKey.arch, cfgKey.osType, cfgKey.apexKey)
- if m.BazelRequests == nil {
- m.BazelRequests = make(map[string]bool)
- }
- m.BazelRequests[key] = true
-}
-
-func (m MockBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
- panic("unimplemented")
-}
-
-func (m MockBazelContext) GetOutputFiles(label string, _ configKey) ([]string, error) {
- result, ok := m.LabelToOutputFiles[label]
- if !ok {
- return []string{}, fmt.Errorf("no target with label %q in LabelToOutputFiles", label)
- }
- return result, nil
-}
-
-func (m MockBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
- result, ok := m.LabelToCcInfo[label]
- if !ok {
- key := BuildMockBazelContextResultKey(label, cfgKey.arch, cfgKey.osType, cfgKey.apexKey)
- result, ok = m.LabelToCcInfo[key]
- if !ok {
- return cquery.CcInfo{}, fmt.Errorf("no target with label %q in LabelToCcInfo", label)
- }
- }
- return result, nil
-}
-
-func (m MockBazelContext) GetApexInfo(label string, _ configKey) (cquery.ApexInfo, error) {
- result, ok := m.LabelToApexInfo[label]
- if !ok {
- return cquery.ApexInfo{}, fmt.Errorf("no target with label %q in LabelToApexInfo", label)
- }
- return result, nil
-}
-
-func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery.CcUnstrippedInfo, error) {
- result, ok := m.LabelToCcBinary[label]
- if !ok {
- return cquery.CcUnstrippedInfo{}, fmt.Errorf("no target with label %q in LabelToCcBinary", label)
- }
- return result, nil
-}
-
-func (m MockBazelContext) GetPrebuiltFileInfo(label string, _ configKey) (cquery.PrebuiltFileInfo, error) {
- result, ok := m.LabelToPrebuiltFileInfo[label]
- if !ok {
- return cquery.PrebuiltFileInfo{}, fmt.Errorf("no target with label %q in LabelToPrebuiltFileInfo", label)
- }
- return result, nil
-}
-
-func (m MockBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
- panic("unimplemented")
-}
-
-func (m MockBazelContext) IsModuleNameAllowed(_ string, _ bool) bool {
- return true
-}
-
-func (m MockBazelContext) OutputBase() string { return m.OutputBaseDir }
-
-func (m MockBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
- return []*bazel.BuildStatement{}
-}
-
-func (m MockBazelContext) AqueryDepsets() []bazel.AqueryDepset {
- return []bazel.AqueryDepset{}
-}
-
-var _ BazelContext = MockBazelContext{}
-
-func BuildMockBazelContextRequestKey(label string, request cqueryRequest, arch string, osType OsType, apexKey ApexConfigKey) string {
- cfgKey := configKey{
- arch: arch,
- osType: osType,
- apexKey: apexKey,
- }
-
- return strings.Join([]string{label, request.Name(), cfgKey.String()}, "_")
-}
-
-func BuildMockBazelContextResultKey(label string, arch string, osType OsType, apexKey ApexConfigKey) string {
- cfgKey := configKey{
- arch: arch,
- osType: osType,
- apexKey: apexKey,
- }
-
- return strings.Join([]string{label, cfgKey.String()}, "_")
-}
-
-func (bazelCtx *mixedBuildBazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
- key := makeCqueryKey(label, requestType, cfgKey)
- bazelCtx.requestMutex.Lock()
- defer bazelCtx.requestMutex.Unlock()
-
- // Insert key into requests, maintaining the sort, and only if it's not duplicate.
- keyString := key.String()
- foundEqual := false
- notLessThanKeyString := func(i int) bool {
- s := bazelCtx.requests[i].String()
- v := strings.Compare(s, keyString)
- if v == 0 {
- foundEqual = true
- }
- return v >= 0
- }
- targetIndex := sort.Search(len(bazelCtx.requests), notLessThanKeyString)
- if foundEqual {
- return
- }
-
- if targetIndex == len(bazelCtx.requests) {
- bazelCtx.requests = append(bazelCtx.requests, key)
- } else {
- bazelCtx.requests = append(bazelCtx.requests[:targetIndex+1], bazelCtx.requests[targetIndex:]...)
- bazelCtx.requests[targetIndex] = key
- }
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
- key := makeCqueryKey(label, cquery.GetOutputFiles, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- bazelOutput := strings.TrimSpace(rawString)
-
- return cquery.GetOutputFiles.ParseResult(bazelOutput), nil
- }
- return nil, fmt.Errorf("no bazel response found for %v", key)
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
- key := makeCqueryKey(label, cquery.GetCcInfo, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- bazelOutput := strings.TrimSpace(rawString)
- return cquery.GetCcInfo.ParseResult(bazelOutput)
- }
- return cquery.CcInfo{}, fmt.Errorf("no bazel response found for %v", key)
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetApexInfo(label string, cfgKey configKey) (cquery.ApexInfo, error) {
- key := makeCqueryKey(label, cquery.GetApexInfo, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- return cquery.GetApexInfo.ParseResult(strings.TrimSpace(rawString))
- }
- return cquery.ApexInfo{}, fmt.Errorf("no bazel response found for %v", key)
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetCcUnstrippedInfo(label string, cfgKey configKey) (cquery.CcUnstrippedInfo, error) {
- key := makeCqueryKey(label, cquery.GetCcUnstrippedInfo, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- return cquery.GetCcUnstrippedInfo.ParseResult(strings.TrimSpace(rawString))
- }
- return cquery.CcUnstrippedInfo{}, fmt.Errorf("no bazel response for %s", key)
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetPrebuiltFileInfo(label string, cfgKey configKey) (cquery.PrebuiltFileInfo, error) {
- key := makeCqueryKey(label, cquery.GetPrebuiltFileInfo, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- return cquery.GetPrebuiltFileInfo.ParseResult(strings.TrimSpace(rawString))
- }
- return cquery.PrebuiltFileInfo{}, fmt.Errorf("no bazel response for %s", key)
-}
-
-func AddToStringSet(set map[string]bool, items []string) {
- for _, item := range items {
- set[item] = true
- }
-}
-
-func GetBazelEnabledAndDisabledModules(buildMode SoongBuildMode, forceEnabled map[string]struct{}) (map[string]bool, map[string]bool) {
- disabledModules := map[string]bool{}
- enabledModules := map[string]bool{}
-
- switch buildMode {
- case BazelProdMode:
- AddToStringSet(enabledModules, allowlists.ProdMixedBuildsEnabledList)
- for enabledAdHocModule := range forceEnabled {
- enabledModules[enabledAdHocModule] = true
- }
- case BazelStagingMode:
- // Staging mode includes all prod modules plus all staging modules.
- AddToStringSet(enabledModules, allowlists.ProdMixedBuildsEnabledList)
- AddToStringSet(enabledModules, allowlists.StagingMixedBuildsEnabledList)
- for enabledAdHocModule := range forceEnabled {
- enabledModules[enabledAdHocModule] = true
- }
- default:
- panic("Expected BazelProdMode or BazelStagingMode")
- }
- return enabledModules, disabledModules
-}
-
-func GetBazelEnabledModules(buildMode SoongBuildMode) []string {
- enabledModules, disabledModules := GetBazelEnabledAndDisabledModules(buildMode, nil)
- enabledList := make([]string, 0, len(enabledModules))
- for module := range enabledModules {
- if !disabledModules[module] {
- enabledList = append(enabledList, module)
- }
- }
- sort.Strings(enabledList)
- return enabledList
-}
-
-func NewBazelContext(c *config) (BazelContext, error) {
- if c.BuildMode != BazelProdMode && c.BuildMode != BazelStagingMode {
- return noopBazelContext{}, nil
- }
-
- enabledModules, disabledModules := GetBazelEnabledAndDisabledModules(c.BuildMode, c.BazelModulesForceEnabledByFlag())
-
- paths := bazelPaths{
- soongOutDir: c.soongOutDir,
- }
- var missing []string
- vars := []struct {
- name string
- ptr *string
-
- // True if the environment variable needs to be tracked so that changes to the variable
- // cause the ninja file to be regenerated, false otherwise. False should only be set for
- // environment variables that have no effect on the generated ninja file.
- track bool
- }{
- {"BAZEL_HOME", &paths.homeDir, true},
- {"BAZEL_PATH", &paths.bazelPath, true},
- {"BAZEL_OUTPUT_BASE", &paths.outputBase, true},
- {"BAZEL_WORKSPACE", &paths.workspaceDir, true},
- {"BAZEL_METRICS_DIR", &paths.metricsDir, false},
- {"BAZEL_DEPS_FILE", &paths.bazelDepsFile, true},
- }
- for _, v := range vars {
- if v.track {
- if s := c.Getenv(v.name); len(s) > 1 {
- *v.ptr = s
- continue
- }
- } else if s, ok := c.env[v.name]; ok {
- *v.ptr = s
- } else {
- missing = append(missing, v.name)
- }
- }
- if len(missing) > 0 {
- return nil, fmt.Errorf("missing required env vars to use bazel: %s", missing)
- }
-
- targetBuildVariant := "user"
- if c.Eng() {
- targetBuildVariant = "eng"
- } else if c.Debuggable() {
- targetBuildVariant = "userdebug"
- }
- targetProduct := "unknown"
- if c.HasDeviceProduct() {
- targetProduct = c.DeviceProduct()
- }
- dclaMixedBuildsEnabledList := []string{}
- if c.BuildMode == BazelProdMode {
- dclaMixedBuildsEnabledList = allowlists.ProdDclaMixedBuildsEnabledList
- } else if c.BuildMode == BazelStagingMode {
- dclaMixedBuildsEnabledList = append(allowlists.ProdDclaMixedBuildsEnabledList,
- allowlists.StagingDclaMixedBuildsEnabledList...)
- }
- dclaEnabledModules := map[string]bool{}
- AddToStringSet(dclaEnabledModules, dclaMixedBuildsEnabledList)
- return &mixedBuildBazelContext{
- bazelRunner: &builtinBazelRunner{c.UseBazelProxy, absolutePath(c.outDir)},
- paths: &paths,
- bazelEnabledModules: enabledModules,
- bazelDisabledModules: disabledModules,
- bazelDclaEnabledModules: dclaEnabledModules,
- targetProduct: targetProduct,
- targetBuildVariant: targetBuildVariant,
- }, nil
-}
-
-func (p *bazelPaths) BazelMetricsDir() string {
- return p.metricsDir
-}
-
-func (context *mixedBuildBazelContext) IsModuleNameAllowed(moduleName string, withinApex bool) bool {
- if context.bazelDisabledModules[moduleName] {
- return false
- }
- if context.bazelEnabledModules[moduleName] {
- return true
- }
- if withinApex && context.bazelDclaEnabledModules[moduleName] {
- return true
- }
-
- return false
-}
-
-func pwdPrefix() string {
- // Darwin doesn't have /proc
- if runtime.GOOS != "darwin" {
- return "PWD=/proc/self/cwd"
- }
- return ""
-}
-
-type bazelCommand struct {
- command string
- // query or label
- expression string
-}
-
-type builtinBazelRunner struct {
- useBazelProxy bool
- outDir string
-}
-
-// Issues the given bazel command with given build label and additional flags.
-// Returns (stdout, stderr, error). The first and second return values are strings
-// containing the stdout and stderr of the run command, and an error is returned if
-// the invocation returned an error code.
-func (r *builtinBazelRunner) issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (string, string, error) {
- if r.useBazelProxy {
- eventHandler.Begin("client_proxy")
- defer eventHandler.End("client_proxy")
- proxyClient := bazel.NewProxyClient(r.outDir)
- resp, err := proxyClient.IssueCommand(cmdRequest)
-
- if err != nil {
- return "", "", err
- }
- if len(resp.ErrorString) > 0 {
- return "", "", fmt.Errorf(resp.ErrorString)
- }
- return resp.Stdout, resp.Stderr, nil
- } else {
- eventHandler.Begin("bazel command")
- defer eventHandler.End("bazel command")
-
- stdout, stderr, err := bazel.ExecBazel(paths.bazelPath, absolutePath(paths.syntheticWorkspaceDir()), cmdRequest)
- return string(stdout), string(stderr), err
- }
-}
-
-func (context *mixedBuildBazelContext) createBazelCommand(config Config, runName bazel.RunName, command bazelCommand,
- extraFlags ...string) bazel.CmdRequest {
- if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
- panic("Unknown GOOS: " + runtime.GOOS)
- }
- cmdFlags := []string{
- "--output_base=" + absolutePath(context.paths.outputBase),
- command.command,
- command.expression,
- "--profile=" + shared.BazelMetricsFilename(context.paths, runName),
-
- "--host_platform=@soong_injection//product_config_platforms:mixed_builds_product_" + runtime.GOOS + "_x86_64",
- "--//build/bazel/product_config:target_build_variant=" + context.targetBuildVariant,
- // Don't specify --platforms, because on some products/branches (like kernel-build-tools)
- // the main platform for mixed_builds_product-variant doesn't exist because an arch isn't
- // specified in product config. The derivative platforms that config_node transitions into
- // will still work.
-
- // Suppress noise
- "--ui_event_filters=-INFO",
- "--noshow_progress",
- "--norun_validations",
- }
- cmdFlags = append(cmdFlags, extraFlags...)
-
- extraEnv := []string{
- "HOME=" + context.paths.homeDir,
- pwdPrefix(),
- "BUILD_DIR=" + absolutePath(context.paths.soongOutDir),
- // Make OUT_DIR absolute here so build/bazel/bin/bazel uses the correct
- // OUT_DIR at <root>/out, instead of <root>/out/soong/workspace/out.
- "OUT_DIR=" + absolutePath(context.paths.outDir()),
- // Disables local host detection of gcc; toolchain information is defined
- // explicitly in BUILD files.
- "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1",
- }
- capturedEnvVars, err := starlark_import.GetStarlarkValue[[]string]("captured_env_vars")
- if err != nil {
- panic(err)
- }
- for _, envvar := range capturedEnvVars {
- val := config.Getenv(envvar)
- if val == "" {
- continue
- }
- extraEnv = append(extraEnv, fmt.Sprintf("%s=%s", envvar, val))
- }
- envVars := append(os.Environ(), extraEnv...)
-
- return bazel.CmdRequest{cmdFlags, envVars}
-}
-
-func (context *mixedBuildBazelContext) printableCqueryCommand(bazelCmd bazel.CmdRequest) string {
- args := append([]string{context.paths.bazelPath}, bazelCmd.Argv...)
- outputString := strings.Join(bazelCmd.Env, " ") + " \"" + strings.Join(args, "\" \"") + "\""
- return outputString
-}
-
-func (context *mixedBuildBazelContext) mainBzlFileContents() []byte {
- // TODO(cparsons): Define configuration transitions programmatically based
- // on available archs.
- contents := `
-#####################################################
-# This file is generated by soong_build. Do not edit.
-#####################################################
-def _config_node_transition_impl(settings, attr):
- if attr.os == "android" and attr.arch == "target":
- target = "mixed_builds_product"
- else:
- target = "mixed_builds_product_%s_%s" % (attr.os, attr.arch)
- apex_name = ""
- if attr.within_apex:
- # //build/bazel/rules/apex:apex_name has to be set to a non_empty value,
- # otherwise //build/bazel/rules/apex:non_apex will be true and the
- # "-D__ANDROID_APEX__" compiler flag will be missing. Apex_name is used
- # in some validation on bazel side which don't really apply in mixed
- # build because soong will do the work, so we just set it to a fixed
- # value here.
- apex_name = "dcla_apex"
- outputs = {
- "//command_line_option:platforms": "@soong_injection//product_config_platforms:%s" % target,
- "@//build/bazel/rules/apex:within_apex": attr.within_apex,
- "@//build/bazel/rules/apex:min_sdk_version": attr.apex_sdk_version,
- "@//build/bazel/rules/apex:apex_name": apex_name,
- "@//build/bazel/rules/apex:api_domain": attr.api_domain,
- }
-
- return outputs
-
-_config_node_transition = transition(
- implementation = _config_node_transition_impl,
- inputs = [],
- outputs = [
- "//command_line_option:platforms",
- "@//build/bazel/rules/apex:within_apex",
- "@//build/bazel/rules/apex:min_sdk_version",
- "@//build/bazel/rules/apex:apex_name",
- "@//build/bazel/rules/apex:api_domain",
- ],
-)
-
-def _passthrough_rule_impl(ctx):
- return [DefaultInfo(files = depset(ctx.files.deps))]
-
-config_node = rule(
- implementation = _passthrough_rule_impl,
- attrs = {
- "arch" : attr.string(mandatory = True),
- "os" : attr.string(mandatory = True),
- "within_apex" : attr.bool(default = False),
- "apex_sdk_version" : attr.string(mandatory = True),
- "api_domain" : attr.string(mandatory = True),
- "deps" : attr.label_list(cfg = _config_node_transition, allow_files = True),
- "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
- },
-)
-
-
-# Rule representing the root of the build, to depend on all Bazel targets that
-# are required for the build. Building this target will build the entire Bazel
-# build tree.
-mixed_build_root = rule(
- implementation = _passthrough_rule_impl,
- attrs = {
- "deps" : attr.label_list(),
- },
-)
-
-def _phony_root_impl(ctx):
- return []
-
-# Rule to depend on other targets but build nothing.
-# This is useful as follows: building a target of this rule will generate
-# symlink forests for all dependencies of the target, without executing any
-# actions of the build.
-phony_root = rule(
- implementation = _phony_root_impl,
- attrs = {"deps" : attr.label_list()},
-)
-`
-
- return []byte(contents)
-}
-
-func (context *mixedBuildBazelContext) mainBuildFileContents() []byte {
- // TODO(cparsons): Map label to attribute programmatically; don't use hard-coded
- // architecture mapping.
- formatString := `
-# This file is generated by soong_build. Do not edit.
-load(":main.bzl", "config_node", "mixed_build_root", "phony_root")
-
-%s
-
-mixed_build_root(name = "buildroot",
- deps = [%s],
- testonly = True, # Unblocks testonly deps.
-)
-
-phony_root(name = "phonyroot",
- deps = [":buildroot"],
- testonly = True, # Unblocks testonly deps.
-)
-`
- configNodeFormatString := `
-config_node(name = "%s",
- arch = "%s",
- os = "%s",
- within_apex = %s,
- apex_sdk_version = "%s",
- api_domain = "%s",
- deps = [%s],
- testonly = True, # Unblocks testonly deps.
-)
-`
-
- configNodesSection := ""
-
- labelsByConfig := map[string][]string{}
-
- for _, val := range context.requests {
- labelString := fmt.Sprintf("\"@%s\"", val.label)
- configString := getConfigString(val)
- labelsByConfig[configString] = append(labelsByConfig[configString], labelString)
- }
-
- // Configs need to be sorted to maintain determinism of the BUILD file.
- sortedConfigs := make([]string, 0, len(labelsByConfig))
- for val := range labelsByConfig {
- sortedConfigs = append(sortedConfigs, val)
- }
- sort.Slice(sortedConfigs, func(i, j int) bool { return sortedConfigs[i] < sortedConfigs[j] })
-
- allLabels := []string{}
- for _, configString := range sortedConfigs {
- labels := labelsByConfig[configString]
- configTokens := strings.Split(configString, "|")
- if len(configTokens) < 2 {
- panic(fmt.Errorf("Unexpected config string format: %s", configString))
- }
- archString := configTokens[0]
- osString := configTokens[1]
- withinApex := "False"
- apexSdkVerString := ""
- apiDomainString := ""
- if osString == "android" {
- // api domains are meaningful only for device variants
- apiDomainString = "system"
- }
- targetString := fmt.Sprintf("%s_%s", osString, archString)
- if len(configTokens) > 2 {
- targetString += "_" + configTokens[2]
- if configTokens[2] == withinApexToString(true) {
- withinApex = "True"
- }
- }
- if len(configTokens) > 3 {
- targetString += "_" + configTokens[3]
- apexSdkVerString = configTokens[3]
- }
- if len(configTokens) > 4 {
- apiDomainString = configTokens[4]
- targetString += "_" + apiDomainString
- }
- allLabels = append(allLabels, fmt.Sprintf("\":%s\"", targetString))
- labelsString := strings.Join(labels, ",\n ")
- configNodesSection += fmt.Sprintf(configNodeFormatString, targetString, archString, osString, withinApex, apexSdkVerString, apiDomainString,
- labelsString)
- }
-
- return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(allLabels, ",\n ")))
-}
-
-func indent(original string) string {
- result := ""
- for _, line := range strings.Split(original, "\n") {
- result += " " + line + "\n"
- }
- return result
-}
-
-// Returns the file contents of the buildroot.cquery file that should be used for the cquery
-// expression in order to obtain information about buildroot and its dependencies.
-// The contents of this file depend on the mixedBuildBazelContext's requests; requests are enumerated
-// and grouped by their request type. The data retrieved for each label depends on its
-// request type.
-func (context *mixedBuildBazelContext) cqueryStarlarkFileContents() []byte {
- requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
- requestTypes := []cqueryRequest{}
- for _, val := range context.requests {
- cqueryId := getCqueryId(val)
- mapEntryString := fmt.Sprintf("%q : True", cqueryId)
- if _, seenKey := requestTypeToCqueryIdEntries[val.requestType]; !seenKey {
- requestTypes = append(requestTypes, val.requestType)
- }
- requestTypeToCqueryIdEntries[val.requestType] =
- append(requestTypeToCqueryIdEntries[val.requestType], mapEntryString)
- }
- labelRegistrationMapSection := ""
- functionDefSection := ""
- mainSwitchSection := ""
-
- mapDeclarationFormatString := `
-%s = {
- %s
-}
-`
- functionDefFormatString := `
-def %s(target, id_string):
-%s
-`
- mainSwitchSectionFormatString := `
- if id_string in %s:
- return id_string + ">>" + %s(target, id_string)
-`
-
- for _, requestType := range requestTypes {
- labelMapName := requestType.Name() + "_Labels"
- functionName := requestType.Name() + "_Fn"
- labelRegistrationMapSection += fmt.Sprintf(mapDeclarationFormatString,
- labelMapName,
- strings.Join(requestTypeToCqueryIdEntries[requestType], ",\n "))
- functionDefSection += fmt.Sprintf(functionDefFormatString,
- functionName,
- indent(requestType.StarlarkFunctionBody()))
- mainSwitchSection += fmt.Sprintf(mainSwitchSectionFormatString,
- labelMapName, functionName)
- }
-
- formatString := `
-# This file is generated by soong_build. Do not edit.
-
-{LABEL_REGISTRATION_MAP_SECTION}
-
-{FUNCTION_DEF_SECTION}
-
-def get_arch(target):
- # TODO(b/199363072): filegroups and file targets aren't associated with any
- # specific platform architecture in mixed builds. This is consistent with how
- # Soong treats filegroups, but it may not be the case with manually-written
- # filegroup BUILD targets.
- buildoptions = build_options(target)
-
- if buildoptions == None:
- # File targets do not have buildoptions. File targets aren't associated with
- # any specific platform architecture in mixed builds, so use the host.
- return "x86_64|linux"
- platforms = buildoptions["//command_line_option:platforms"]
- if len(platforms) != 1:
- # An individual configured target should have only one platform architecture.
- # Note that it's fine for there to be multiple architectures for the same label,
- # but each is its own configured target.
- fail("expected exactly 1 platform for " + str(target.label) + " but got " + str(platforms))
- platform_name = platforms[0].name
- if platform_name == "host":
- return "HOST"
- if not platform_name.startswith("mixed_builds_product"):
- fail("expected platform name of the form 'mixed_builds_product_android_<arch>' or 'mixed_builds_product_linux_<arch>', but was " + str(platforms))
- platform_name = platform_name.removeprefix("mixed_builds_product").removeprefix("_")
- config_key = ""
- if not platform_name:
- config_key = "target|android"
- elif platform_name.startswith("android_"):
- config_key = platform_name.removeprefix("android_") + "|android"
- elif platform_name.startswith("linux_"):
- config_key = platform_name.removeprefix("linux_") + "|linux"
- else:
- fail("expected platform name of the form 'mixed_builds_product_android_<arch>' or 'mixed_builds_product_linux_<arch>', but was " + str(platforms))
-
- within_apex = buildoptions.get("//build/bazel/rules/apex:within_apex")
- apex_sdk_version = buildoptions.get("//build/bazel/rules/apex:min_sdk_version")
- api_domain = buildoptions.get("//build/bazel/rules/apex:api_domain")
-
- if within_apex:
- config_key += "|within_apex"
- if apex_sdk_version != None and len(apex_sdk_version) > 0:
- config_key += "|" + apex_sdk_version
- if api_domain != None and len(api_domain) > 0:
- config_key += "|" + api_domain
-
- return config_key
-
-def format(target):
- id_string = str(target.label) + "|" + get_arch(target)
-
- # TODO(b/248106697): Remove once Bazel is updated to always normalize labels.
- if id_string.startswith("//"):
- id_string = "@" + id_string
-
- {MAIN_SWITCH_SECTION}
-
- # This target was not requested via cquery, and thus must be a dependency
- # of a requested target.
- return id_string + ">>NONE"
-`
- replacer := strings.NewReplacer(
- "{LABEL_REGISTRATION_MAP_SECTION}", labelRegistrationMapSection,
- "{FUNCTION_DEF_SECTION}", functionDefSection,
- "{MAIN_SWITCH_SECTION}", mainSwitchSection)
-
- return []byte(replacer.Replace(formatString))
-}
-
-// Returns a path containing build-related metadata required for interfacing
-// with Bazel. Example: out/soong/bazel.
-func (p *bazelPaths) intermediatesDir() string {
- return filepath.Join(p.soongOutDir, "bazel")
-}
-
-// Returns the path where the contents of the @soong_injection repository live.
-// It is used by Soong to tell Bazel things it cannot over the command line.
-func (p *bazelPaths) injectedFilesDir() string {
- return filepath.Join(p.soongOutDir, bazel.SoongInjectionDirName)
-}
-
-// Returns the path of the synthetic Bazel workspace that contains a symlink
-// forest composed the whole source tree and BUILD files generated by bp2build.
-func (p *bazelPaths) syntheticWorkspaceDir() string {
- return filepath.Join(p.soongOutDir, "workspace")
-}
-
-// Returns the path to the top level out dir ($OUT_DIR).
-func (p *bazelPaths) outDir() string {
- return filepath.Dir(p.soongOutDir)
-}
-
-const buildrootLabel = "@soong_injection//mixed_builds:buildroot"
-
-var (
- cqueryCmd = bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
- aqueryCmd = bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
- buildCmd = bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
- allBazelCommands = []bazelCommand{aqueryCmd, cqueryCmd, buildCmd}
-)
-
-// This can't be part of bp2build_product_config.go because it would create a circular go package dependency
-func getLabelsForBazelSandwichPartitions(variables *ProductVariables) []string {
- targetProduct := "unknown"
- if variables.DeviceProduct != nil {
- targetProduct = *variables.DeviceProduct
- }
- currentProductFolder := fmt.Sprintf("build/bazel/products/%s", targetProduct)
- if len(variables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory) > 0 {
- currentProductFolder = fmt.Sprintf("%s%s", variables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory, targetProduct)
- }
- var ret []string
- if variables.PartitionVarsForBazelMigrationOnlyDoNotUse.PartitionQualifiedVariables["system"].BuildingImage {
- ret = append(ret, "@//"+currentProductFolder+":system_image")
- ret = append(ret, "@//"+currentProductFolder+":run_system_image_test")
- }
- return ret
-}
-
-func GetBazelSandwichCqueryRequests(config Config) ([]cqueryKey, error) {
- partitionLabels := getLabelsForBazelSandwichPartitions(&config.productVariables)
- result := make([]cqueryKey, 0, len(partitionLabels))
- labelRegex := regexp.MustCompile("^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$")
- // Note that bazel "targets" are different from soong "targets", the bazel targets are
- // synonymous with soong modules, and soong targets are a configuration a module is built in.
- for _, target := range partitionLabels {
- match := labelRegex.FindStringSubmatch(target)
- if match == nil {
- return nil, fmt.Errorf("invalid label, must match `^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$`: %s", target)
- }
-
- // change this to config.BuildOSTarget if we add host targets
- soongTarget := config.AndroidCommonTarget
- if soongTarget.Os.Class != Device {
- // kernel-build-tools seems to set the AndroidCommonTarget to a linux host
- // target for some reason, disable device builds in that case.
- continue
- }
-
- result = append(result, cqueryKey{
- label: target,
- requestType: cquery.GetOutputFiles,
- configKey: configKey{
- arch: soongTarget.Arch.String(),
- osType: soongTarget.Os,
- },
- })
- }
- return result, nil
-}
-
-// QueueBazelSandwichCqueryRequests queues cquery requests for all the bazel labels in
-// bazel_sandwich_targets. These will later be given phony targets so that they can be built on the
-// command line.
-func (context *mixedBuildBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
- requests, err := GetBazelSandwichCqueryRequests(config)
- if err != nil {
- return err
- }
- for _, request := range requests {
- context.QueueBazelRequest(request.label, request.requestType, request.configKey)
- }
-
- return nil
-}
-
-// Issues commands to Bazel to receive results for all cquery requests
-// queued in the BazelContext.
-func (context *mixedBuildBazelContext) InvokeBazel(config Config, ctx invokeBazelContext) error {
- eventHandler := ctx.GetEventHandler()
- eventHandler.Begin("bazel")
- defer eventHandler.End("bazel")
-
- if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
- if err := os.MkdirAll(metricsDir, 0777); err != nil {
- return err
- }
- }
- context.results = make(map[cqueryKey]string)
- if err := context.runCquery(config, ctx); err != nil {
- return err
- }
- if err := context.runAquery(config, ctx); err != nil {
- return err
- }
- if err := context.generateBazelSymlinks(config, ctx); err != nil {
- return err
- }
-
- // Clear requests.
- context.requests = []cqueryKey{}
- return nil
-}
-
-func (context *mixedBuildBazelContext) runCquery(config Config, ctx invokeBazelContext) error {
- eventHandler := ctx.GetEventHandler()
- eventHandler.Begin("cquery")
- defer eventHandler.End("cquery")
- soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
- mixedBuildsPath := filepath.Join(soongInjectionPath, "mixed_builds")
- if _, err := os.Stat(mixedBuildsPath); os.IsNotExist(err) {
- err = os.MkdirAll(mixedBuildsPath, 0777)
- if err != nil {
- return err
- }
- }
- if err := writeFileBytesIfChanged(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
- return err
- }
- if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
- return err
- }
- if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
- return err
- }
- cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
- if err := writeFileBytesIfChanged(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
- return err
- }
-
- extraFlags := []string{"--output=starlark", "--starlark:file=" + absolutePath(cqueryFileRelpath)}
- if Bool(config.productVariables.ClangCoverage) {
- extraFlags = append(extraFlags, "--collect_code_coverage")
- }
-
- cqueryCmdRequest := context.createBazelCommand(config, bazel.CqueryBuildRootRunName, cqueryCmd, extraFlags...)
- cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCmdRequest, context.paths, eventHandler)
- if cqueryErr != nil {
- return cqueryErr
- }
- cqueryCommandPrint := fmt.Sprintf("cquery command line:\n %s \n\n\n", context.printableCqueryCommand(cqueryCmdRequest))
- if err := os.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
- return err
- }
- cqueryResults := map[string]string{}
- for _, outputLine := range strings.Split(cqueryOutput, "\n") {
- if strings.Contains(outputLine, ">>") {
- splitLine := strings.SplitN(outputLine, ">>", 2)
- cqueryResults[splitLine[0]] = splitLine[1]
- }
- }
- for _, val := range context.requests {
- if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
- context.results[val] = cqueryResult
- } else {
- return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
- getCqueryId(val), cqueryOutput, cqueryErrorMessage)
- }
- }
- return nil
-}
-
-func writeFileBytesIfChanged(path string, contents []byte, perm os.FileMode) error {
- oldContents, err := os.ReadFile(path)
- if err != nil || !bytes.Equal(contents, oldContents) {
- err = os.WriteFile(path, contents, perm)
- }
- return nil
-}
-
-func (context *mixedBuildBazelContext) runAquery(config Config, ctx invokeBazelContext) error {
- eventHandler := ctx.GetEventHandler()
- eventHandler.Begin("aquery")
- defer eventHandler.End("aquery")
- // Issue an aquery command to retrieve action information about the bazel build tree.
- //
- // Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
- // proto sources, which would add a number of unnecessary dependencies.
- extraFlags := []string{"--output=proto", "--include_file_write_contents"}
- if Bool(config.productVariables.ClangCoverage) {
- extraFlags = append(extraFlags, "--collect_code_coverage")
- paths := make([]string, 0, 2)
- if p := config.productVariables.NativeCoveragePaths; len(p) > 0 {
- for i := range p {
- // TODO(b/259404593) convert path wildcard to regex values
- if p[i] == "*" {
- p[i] = ".*"
- }
- }
- paths = append(paths, JoinWithPrefixAndSeparator(p, "+", ","))
- }
- if p := config.productVariables.NativeCoverageExcludePaths; len(p) > 0 {
- paths = append(paths, JoinWithPrefixAndSeparator(p, "-", ","))
- }
- if len(paths) > 0 {
- extraFlags = append(extraFlags, "--instrumentation_filter="+strings.Join(paths, ","))
- }
- }
- aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(config, bazel.AqueryBuildRootRunName, aqueryCmd,
- extraFlags...), context.paths, eventHandler)
- if err != nil {
- return err
- }
- context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput), eventHandler)
- return err
-}
-
-func (context *mixedBuildBazelContext) generateBazelSymlinks(config Config, ctx invokeBazelContext) error {
- eventHandler := ctx.GetEventHandler()
- eventHandler.Begin("symlinks")
- defer eventHandler.End("symlinks")
- // Issue a build command of the phony root to generate symlink forests for dependencies of the
- // Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
- // but some of symlinks may be required to resolve source dependencies of the build.
- _, _, err := context.issueBazelCommand(context.createBazelCommand(config, bazel.BazelBuildPhonyRootRunName, buildCmd), context.paths, eventHandler)
- return err
-}
-
-func (context *mixedBuildBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
- return context.buildStatements
-}
-
-func (context *mixedBuildBazelContext) AqueryDepsets() []bazel.AqueryDepset {
- return context.depsets
-}
-
-func (context *mixedBuildBazelContext) OutputBase() string {
- return context.paths.outputBase
-}
-
-// Singleton used for registering BUILD file ninja dependencies (needed
-// for correctness of builds which use Bazel.
-func BazelSingleton() Singleton {
- return &bazelSingleton{}
-}
-
-type bazelSingleton struct{}
-
-func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
- // bazelSingleton is a no-op if mixed-soong-bazel-builds are disabled.
- if !ctx.Config().IsMixedBuildsEnabled() {
- return
- }
-
- // Add ninja file dependencies for files which all bazel invocations require.
- bazelBuildList := absolutePath(filepath.Join(
- filepath.Dir(ctx.Config().moduleListFile), "bazel.list"))
- ctx.AddNinjaFileDeps(bazelBuildList)
-
- data, err := os.ReadFile(bazelBuildList)
- if err != nil {
- ctx.Errorf(err.Error())
- }
- files := strings.Split(strings.TrimSpace(string(data)), "\n")
- for _, file := range files {
- ctx.AddNinjaFileDeps(file)
- }
-
- depsetHashToDepset := map[string]bazel.AqueryDepset{}
-
- for _, depset := range ctx.Config().BazelContext.AqueryDepsets() {
- depsetHashToDepset[depset.ContentHash] = depset
-
- var outputs []Path
- var orderOnlies []Path
- for _, depsetDepHash := range depset.TransitiveDepSetHashes {
- otherDepsetName := bazelDepsetName(depsetDepHash)
- outputs = append(outputs, PathForPhony(ctx, otherDepsetName))
- }
- for _, artifactPath := range depset.DirectArtifacts {
- pathInBazelOut := PathForBazelOut(ctx, artifactPath)
- if artifactPath == "bazel-out/volatile-status.txt" {
- // See https://bazel.build/docs/user-manual#workspace-status
- orderOnlies = append(orderOnlies, pathInBazelOut)
- } else {
- outputs = append(outputs, pathInBazelOut)
- }
- }
- thisDepsetName := bazelDepsetName(depset.ContentHash)
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Outputs: []WritablePath{PathForPhony(ctx, thisDepsetName)},
- Implicits: outputs,
- OrderOnly: orderOnlies,
- })
- }
-
- executionRoot := path.Join(ctx.Config().BazelContext.OutputBase(), "execroot", "__main__")
- bazelOutDir := path.Join(executionRoot, "bazel-out")
- rel, err := filepath.Rel(ctx.Config().OutDir(), executionRoot)
- if err != nil {
- ctx.Errorf("%s", err.Error())
- }
- dotdotsToOutRoot := strings.Repeat("../", strings.Count(rel, "/")+1)
- for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() {
- // nil build statements are a valid case where we do not create an action because it is
- // unnecessary or handled by other processing
- if buildStatement == nil {
- continue
- }
- if len(buildStatement.Command) > 0 {
- rule := NewRuleBuilder(pctx, ctx)
- intermediateDir, intermediateDirHash := intermediatePathForSboxMixedBuildAction(ctx, buildStatement)
- if buildStatement.ShouldRunInSbox {
- // Create a rule to build the output inside a sandbox
- // This will create two changes of working directory
- // 1. From ANDROID_BUILD_TOP to sbox top
- // 2. From sbox top to a a synthetic mixed build execution root relative to it
- // Finally, the outputs will be copied to intermediateDir
- rule.Sbox(intermediateDir,
- PathForOutput(ctx, "mixed_build_sbox_intermediates", intermediateDirHash+".textproto")).
- SandboxInputs().
- // Since we will cd to mixed build execution root, set sbox's out subdir to empty
- // Without this, we will try to copy from $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/...
- SetSboxOutDirDirAsEmpty()
-
- // Create another set of rules to copy files from the intermediate dir to mixed build execution root
- for _, outputPath := range buildStatement.OutputPaths {
- ctx.Build(pctx, BuildParams{
- Rule: CpIfChanged,
- Input: intermediateDir.Join(ctx, executionRoot, outputPath),
- Output: PathForBazelOut(ctx, outputPath),
- })
- }
- }
- createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx, depsetHashToDepset, dotdotsToOutRoot)
-
- desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths)
- rule.Build(fmt.Sprintf("bazel %d", index), desc)
- continue
- }
- // Certain actions returned by aquery (for instance FileWrite) do not contain a command
- // and thus require special treatment. If BuildStatement were an interface implementing
- // buildRule(ctx) function, the code here would just call it.
- // Unfortunately, the BuildStatement is defined in
- // the 'bazel' package, which cannot depend on 'android' package where ctx is defined,
- // because this would cause circular dependency. So, until we move aquery processing
- // to the 'android' package, we need to handle special cases here.
- switch buildStatement.Mnemonic {
- case "RepoMappingManifest":
- // It appears RepoMappingManifest files currently have
- // non-deterministic content. Just emit empty files for
- // now because they're unused.
- out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
- WriteFileRuleVerbatim(ctx, out, "")
- case "FileWrite", "SourceSymlinkManifest":
- out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
- if buildStatement.IsExecutable {
- WriteExecutableFileRuleVerbatim(ctx, out, buildStatement.FileContents)
- } else {
- WriteFileRuleVerbatim(ctx, out, buildStatement.FileContents)
- }
- case "SymlinkTree":
- // build-runfiles arguments are the manifest file and the target directory
- // where it creates the symlink tree according to this manifest (and then
- // writes the MANIFEST file to it).
- outManifest := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
- outManifestPath := outManifest.String()
- if !strings.HasSuffix(outManifestPath, "MANIFEST") {
- panic("the base name of the symlink tree action should be MANIFEST, got " + outManifestPath)
- }
- outDir := filepath.Dir(outManifestPath)
- ctx.Build(pctx, BuildParams{
- Rule: buildRunfilesRule,
- Output: outManifest,
- Inputs: []Path{PathForBazelOut(ctx, buildStatement.InputPaths[0])},
- Description: "symlink tree for " + outDir,
- Args: map[string]string{
- "outDir": outDir,
- },
- })
- default:
- panic(fmt.Sprintf("unhandled build statement: %v", buildStatement))
- }
- }
-
- // Create phony targets for all the bazel sandwich output files
- requests, err := GetBazelSandwichCqueryRequests(ctx.Config())
- if err != nil {
- ctx.Errorf(err.Error())
- }
- for _, request := range requests {
- files, err := ctx.Config().BazelContext.GetOutputFiles(request.label, request.configKey)
- if err != nil {
- ctx.Errorf(err.Error())
- }
- filesAsPaths := make([]Path, 0, len(files))
- for _, file := range files {
- filesAsPaths = append(filesAsPaths, PathForBazelOut(ctx, file))
- }
- ctx.Phony("bazel_sandwich", filesAsPaths...)
- }
- ctx.Phony("checkbuild", PathForPhony(ctx, "bazel_sandwich"))
-}
-
-// Returns a out dir path for a sandboxed mixed build action
-func intermediatePathForSboxMixedBuildAction(ctx PathContext, statement *bazel.BuildStatement) (OutputPath, string) {
- // An artifact can be generated by a single buildstatement.
- // Use the hash of the first artifact to create a unique path
- uniqueDir := sha1.New()
- uniqueDir.Write([]byte(statement.OutputPaths[0]))
- uniqueDirHashString := hex.EncodeToString(uniqueDir.Sum(nil))
- return PathForOutput(ctx, "mixed_build_sbox_intermediates", uniqueDirHashString), uniqueDirHashString
-}
-
-// Register bazel-owned build statements (obtained from the aquery invocation).
-func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx BuilderContext, depsetHashToDepset map[string]bazel.AqueryDepset, dotdotsToOutRoot string) {
- // executionRoot is the action cwd.
- if buildStatement.ShouldRunInSbox {
- // mkdir -p ensures that the directory exists when run via sbox
- cmd.Text(fmt.Sprintf("mkdir -p '%s' && cd '%s' &&", executionRoot, executionRoot))
- } else {
- cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot))
- }
-
- // Remove old outputs, as some actions might not rerun if the outputs are detected.
- if len(buildStatement.OutputPaths) > 0 {
- cmd.Text("rm -rf") // -r because outputs can be Bazel dir/tree artifacts.
- for _, outputPath := range buildStatement.OutputPaths {
- cmd.Text(fmt.Sprintf("'%s'", outputPath))
- }
- cmd.Text("&&")
- }
-
- for _, pair := range buildStatement.Env {
- // Set per-action env variables, if any.
- cmd.Flag(pair.Key + "=" + pair.Value)
- }
-
- command := buildStatement.Command
- command = strings.ReplaceAll(command, "{DOTDOTS_TO_OUTPUT_ROOT}", dotdotsToOutRoot)
-
- // The actual Bazel action.
- if len(command) > 16*1024 {
- commandFile := PathForBazelOut(ctx, buildStatement.OutputPaths[0]+".sh")
- WriteFileRule(ctx, commandFile, command)
-
- cmd.Text("bash").Text(buildStatement.OutputPaths[0] + ".sh").Implicit(commandFile)
- } else {
- cmd.Text(command)
- }
-
- for _, outputPath := range buildStatement.OutputPaths {
- if buildStatement.ShouldRunInSbox {
- // The full path has three components that get joined together
- // 1. intermediate output dir that `sbox` will place the artifacts at
- // 2. mixed build execution root
- // 3. artifact path returned by aquery
- intermediateDir, _ := intermediatePathForSboxMixedBuildAction(ctx, buildStatement)
- cmd.ImplicitOutput(intermediateDir.Join(ctx, executionRoot, outputPath))
- } else {
- cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
- }
- }
- for _, inputPath := range buildStatement.InputPaths {
- cmd.Implicit(PathForBazelOut(ctx, inputPath))
- }
- for _, inputDepsetHash := range buildStatement.InputDepsetHashes {
- if buildStatement.ShouldRunInSbox {
- // Bazel depsets are phony targets that are used to group files.
- // We need to copy the grouped files into the sandbox
- ds, _ := depsetHashToDepset[inputDepsetHash]
- cmd.Implicits(PathsForBazelOut(ctx, ds.DirectArtifacts))
- } else {
- otherDepsetName := bazelDepsetName(inputDepsetHash)
- cmd.Implicit(PathForPhony(ctx, otherDepsetName))
- }
- }
- for _, implicitPath := range buildStatement.ImplicitDeps {
- cmd.Implicit(PathForArbitraryOutput(ctx, implicitPath))
- }
-
- if depfile := buildStatement.Depfile; depfile != nil {
- // The paths in depfile are relative to `executionRoot`.
- // Hence, they need to be corrected by replacing "bazel-out"
- // with the full `bazelOutDir`.
- // Otherwise, implicit outputs and implicit inputs under "bazel-out/"
- // would be deemed missing.
- // (Note: The regexp uses a capture group because the version of sed
- // does not support a look-behind pattern.)
- replacement := fmt.Sprintf(`&& sed -i'' -E 's@(^|\s|")bazel-out/@\1%s/@g' '%s'`,
- bazelOutDir, *depfile)
- cmd.Text(replacement)
- cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile))
- }
-
- for _, symlinkPath := range buildStatement.SymlinkPaths {
- cmd.ImplicitSymlinkOutput(PathForBazelOut(ctx, symlinkPath))
- }
-}
-
-func getCqueryId(key cqueryKey) string {
- return key.label + "|" + getConfigString(key)
-}
-
-func getConfigString(key cqueryKey) string {
- arch := key.configKey.arch
- if len(arch) == 0 || arch == "common" {
- if key.configKey.osType.Class == Device {
- // For the generic Android, the expected result is "target|android", which
- // corresponds to the product_variable_config named "android_target" in
- // build/bazel/platforms/BUILD.bazel.
- arch = "target"
- } else {
- // Use host platform, which is currently hardcoded to be x86_64.
- arch = "x86_64"
- }
- }
- osName := key.configKey.osType.Name
- if len(osName) == 0 || osName == "common_os" || osName == "linux_glibc" || osName == "linux_musl" {
- // Use host OS, which is currently hardcoded to be linux.
- osName = "linux"
- }
- keyString := arch + "|" + osName
- if key.configKey.apexKey.WithinApex {
- keyString += "|" + withinApexToString(key.configKey.apexKey.WithinApex)
- }
-
- if len(key.configKey.apexKey.ApexSdkVersion) > 0 {
- keyString += "|" + key.configKey.apexKey.ApexSdkVersion
- }
-
- if len(key.configKey.apexKey.ApiDomain) > 0 {
- keyString += "|" + key.configKey.apexKey.ApiDomain
- }
-
- return keyString
-}
-
-func GetConfigKey(ctx BaseModuleContext) configKey {
- return configKey{
- // use string because Arch is not a valid key in go
- arch: ctx.Arch().String(),
- osType: ctx.Os(),
- }
-}
-
-func GetConfigKeyApexVariant(ctx BaseModuleContext, apexKey *ApexConfigKey) configKey {
- configKey := GetConfigKey(ctx)
-
- if apexKey != nil {
- configKey.apexKey = ApexConfigKey{
- WithinApex: apexKey.WithinApex,
- ApexSdkVersion: apexKey.ApexSdkVersion,
- ApiDomain: apexKey.ApiDomain,
- }
- }
-
- return configKey
-}
-
-func bazelDepsetName(contentHash string) string {
- return fmt.Sprintf("bazel_depset_%s", contentHash)
-}
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
deleted file mode 100644
index 9a3c8fc..0000000
--- a/android/bazel_handler_test.go
+++ /dev/null
@@ -1,426 +0,0 @@
-package android
-
-import (
- "encoding/json"
- "os"
- "path/filepath"
- "reflect"
- "strings"
- "testing"
-
- "android/soong/bazel"
- "android/soong/bazel/cquery"
- analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
-
- "github.com/google/blueprint/metrics"
- "google.golang.org/protobuf/proto"
-)
-
-var testConfig = TestConfig("out", nil, "", nil)
-
-type testInvokeBazelContext struct{}
-
-type mockBazelRunner struct {
- testHelper *testing.T
- // Stores mock behavior. If an issueBazelCommand request is made for command
- // k, and {k:v} is present in this map, then the mock will return v.
- bazelCommandResults map[bazelCommand]string
- // Requests actually made of the mockBazelRunner with issueBazelCommand,
- // keyed by the command they represent.
- bazelCommandRequests map[bazelCommand]bazel.CmdRequest
-}
-
-func (r *mockBazelRunner) bazelCommandForRequest(cmdRequest bazel.CmdRequest) bazelCommand {
- for _, arg := range cmdRequest.Argv {
- for _, cmdType := range allBazelCommands {
- if arg == cmdType.command {
- return cmdType
- }
- }
- }
- r.testHelper.Fatalf("Unrecognized bazel request: %s", cmdRequest)
- return cqueryCmd
-}
-
-func (r *mockBazelRunner) issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (string, string, error) {
- command := r.bazelCommandForRequest(cmdRequest)
- r.bazelCommandRequests[command] = cmdRequest
- return r.bazelCommandResults[command], "", nil
-}
-
-func (t *testInvokeBazelContext) GetEventHandler() *metrics.EventHandler {
- return &metrics.EventHandler{}
-}
-
-func TestRequestResultsAfterInvokeBazel(t *testing.T) {
- label_foo := "@//foo:foo"
- label_bar := "@//foo:bar"
- apexKey := ApexConfigKey{
- WithinApex: true,
- ApexSdkVersion: "29",
- ApiDomain: "myapex",
- }
- cfg_foo := configKey{"arm64_armv8-a", Android, apexKey}
- cfg_bar := configKey{arch: "arm64_armv8-a", osType: Android}
- cmd_results := []string{
- `@//foo:foo|arm64_armv8-a|android|within_apex|29|myapex>>out/foo/foo.txt`,
- `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
- }
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{cqueryCmd: strings.Join(cmd_results, "\n")})
-
- bazelContext.QueueBazelRequest(label_foo, cquery.GetOutputFiles, cfg_foo)
- bazelContext.QueueBazelRequest(label_bar, cquery.GetOutputFiles, cfg_bar)
- err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
- }
- verifyCqueryResult(t, bazelContext, label_foo, cfg_foo, "out/foo/foo.txt")
- verifyCqueryResult(t, bazelContext, label_bar, cfg_bar, "out/foo/bar.txt")
-}
-
-func verifyCqueryResult(t *testing.T, ctx *mixedBuildBazelContext, label string, cfg configKey, result string) {
- g, err := ctx.GetOutputFiles(label, cfg)
- if err != nil {
- t.Errorf("Expected cquery results after running InvokeBazel(), but got err %v", err)
- } else if w := []string{result}; !reflect.DeepEqual(w, g) {
- t.Errorf("Expected output %s, got %s", w, g)
- }
-}
-
-func TestInvokeBazelWritesBazelFiles(t *testing.T) {
- bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
- err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
- }
- if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "main.bzl")); os.IsNotExist(err) {
- t.Errorf("Expected main.bzl to exist, but it does not")
- } else if err != nil {
- t.Errorf("Unexpected error stating main.bzl %s", err)
- }
-
- if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "BUILD.bazel")); os.IsNotExist(err) {
- t.Errorf("Expected BUILD.bazel to exist, but it does not")
- } else if err != nil {
- t.Errorf("Unexpected error stating BUILD.bazel %s", err)
- }
-
- if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "WORKSPACE.bazel")); os.IsNotExist(err) {
- t.Errorf("Expected WORKSPACE.bazel to exist, but it does not")
- } else if err != nil {
- t.Errorf("Unexpected error stating WORKSPACE.bazel %s", err)
- }
-}
-
-func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
- type testCase struct {
- input string
- command string
- }
-
- var testCases = []testCase{
- {`
-{
- "artifacts": [
- { "id": 1, "path_fragment_id": 1 },
- { "id": 2, "path_fragment_id": 2 }],
- "actions": [{
- "target_Id": 1,
- "action_Key": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "input_dep_set_ids": [1],
- "output_Ids": [1],
- "primary_output_id": 1
- }],
- "dep_set_of_files": [
- { "id": 1, "direct_artifact_ids": [1, 2] }],
- "path_fragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
-}`,
- "cd 'test/exec_root' && rm -rf 'one' && touch foo",
- }, {`
-{
- "artifacts": [
- { "id": 1, "path_fragment_id": 10 },
- { "id": 2, "path_fragment_id": 20 }],
- "actions": [{
- "target_Id": 100,
- "action_Key": "x",
- "mnemonic": "x",
- "arguments": ["bogus", "command"],
- "output_Ids": [1, 2],
- "primary_output_id": 1
- }],
- "path_fragments": [
- { "id": 10, "label": "one", "parent_id": 30 },
- { "id": 20, "label": "one.d", "parent_id": 30 },
- { "id": 30, "label": "parent" }]
-}`,
- `cd 'test/exec_root' && rm -rf 'parent/one' && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1test/bazel_out/@g' 'parent/one.d'`,
- },
- }
-
- for i, testCase := range testCases {
- data, err := JsonToActionGraphContainer(testCase.input)
- if err != nil {
- t.Error(err)
- }
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)})
-
- err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
- }
-
- got := bazelContext.BuildStatementsToRegister()
- if want := 1; len(got) != want {
- t.Fatalf("expected %d registered build statements, but got %#v", want, got)
- }
-
- cmd := RuleBuilderCommand{}
- ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
- createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{}, "")
- if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
- t.Errorf("expected: [%s], actual: [%s]", expected, actual)
- }
- }
-}
-
-func TestMixedBuildSandboxedAction(t *testing.T) {
- input := `{
- "artifacts": [
- { "id": 1, "path_fragment_id": 1 },
- { "id": 2, "path_fragment_id": 2 }],
- "actions": [{
- "target_Id": 1,
- "action_Key": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "input_dep_set_ids": [1],
- "output_Ids": [1],
- "primary_output_id": 1
- }],
- "dep_set_of_files": [
- { "id": 1, "direct_artifact_ids": [1, 2] }],
- "path_fragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
-}`
- data, err := JsonToActionGraphContainer(input)
- if err != nil {
- t.Error(err)
- }
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)})
-
- err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("TestMixedBuildSandboxedAction did not expect error invoking Bazel, but got %s", err)
- }
-
- statement := bazelContext.BuildStatementsToRegister()[0]
- statement.ShouldRunInSbox = true
-
- cmd := RuleBuilderCommand{}
- ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
- createCommand(&cmd, statement, "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{}, "")
- // Assert that the output is generated in an intermediate directory
- // fe05bcdcdc4928012781a5f1a2a77cbb5398e106 is the sha1 checksum of "one"
- if actual, expected := cmd.outputs[0].String(), "out/soong/mixed_build_sbox_intermediates/fe05bcdcdc4928012781a5f1a2a77cbb5398e106/test/exec_root/one"; expected != actual {
- t.Errorf("expected: [%s], actual: [%s]", expected, actual)
- }
-
- // Assert the actual command remains unchanged inside the sandbox
- if actual, expected := cmd.buf.String(), "mkdir -p 'test/exec_root' && cd 'test/exec_root' && rm -rf 'one' && touch foo"; expected != actual {
- t.Errorf("expected: [%s], actual: [%s]", expected, actual)
- }
-}
-
-func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
- testConfig.productVariables.ClangCoverage = boolPtr(true)
-
- testConfig.productVariables.NativeCoveragePaths = []string{"foo1", "foo2"}
- testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1", "bar2"}
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1,+foo2,-bar1,-bar2")
-
- testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
- testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1,-bar1")
-
- testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
- testConfig.productVariables.NativeCoverageExcludePaths = nil
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1")
-
- testConfig.productVariables.NativeCoveragePaths = nil
- testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=-bar1")
-
- testConfig.productVariables.NativeCoveragePaths = []string{"*"}
- testConfig.productVariables.NativeCoverageExcludePaths = nil
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+.*")
-
- testConfig.productVariables.ClangCoverage = boolPtr(false)
- verifyAqueryDoesNotContainSubstrings(t, testConfig, "collect_code_coverage", "instrumentation_filter")
-}
-
-func TestBazelRequestsSorted(t *testing.T) {
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
-
- cfgKeyArm64Android := configKey{arch: "arm64_armv8-a", osType: Android}
- cfgKeyArm64Linux := configKey{arch: "arm64_armv8-a", osType: Linux}
- cfgKeyOtherAndroid := configKey{arch: "otherarch", osType: Android}
-
- bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, cfgKeyArm64Linux)
- bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, cfgKeyOtherAndroid)
- bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, cfgKeyOtherAndroid)
-
- if len(bazelContext.requests) != 7 {
- t.Error("Expected 7 request elements, but got", len(bazelContext.requests))
- }
-
- lastString := ""
- for _, val := range bazelContext.requests {
- thisString := val.String()
- if thisString <= lastString {
- t.Errorf("Requests are not ordered correctly. '%s' came before '%s'", lastString, thisString)
- }
- lastString = thisString
- }
-}
-
-func TestIsModuleNameAllowed(t *testing.T) {
- libDisabled := "lib_disabled"
- libEnabled := "lib_enabled"
- libDclaWithinApex := "lib_dcla_within_apex"
- libDclaNonApex := "lib_dcla_non_apex"
- libNotConverted := "lib_not_converted"
-
- disabledModules := map[string]bool{
- libDisabled: true,
- }
- enabledModules := map[string]bool{
- libEnabled: true,
- }
- dclaEnabledModules := map[string]bool{
- libDclaWithinApex: true,
- libDclaNonApex: true,
- }
-
- bazelContext := &mixedBuildBazelContext{
- bazelEnabledModules: enabledModules,
- bazelDisabledModules: disabledModules,
- bazelDclaEnabledModules: dclaEnabledModules,
- }
-
- if bazelContext.IsModuleNameAllowed(libDisabled, true) {
- t.Fatalf("%s shouldn't be allowed for mixed build", libDisabled)
- }
-
- if !bazelContext.IsModuleNameAllowed(libEnabled, true) {
- t.Fatalf("%s should be allowed for mixed build", libEnabled)
- }
-
- if !bazelContext.IsModuleNameAllowed(libDclaWithinApex, true) {
- t.Fatalf("%s should be allowed for mixed build", libDclaWithinApex)
- }
-
- if bazelContext.IsModuleNameAllowed(libDclaNonApex, false) {
- t.Fatalf("%s shouldn't be allowed for mixed build", libDclaNonApex)
- }
-
- if bazelContext.IsModuleNameAllowed(libNotConverted, true) {
- t.Fatalf("%s shouldn't be allowed for mixed build", libNotConverted)
- }
-}
-
-func verifyAqueryContainsFlags(t *testing.T, config Config, expected ...string) {
- t.Helper()
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
-
- err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
- }
-
- sliceContains := func(slice []string, x string) bool {
- for _, s := range slice {
- if s == x {
- return true
- }
- }
- return false
- }
-
- aqueryArgv := bazelContext.bazelRunner.(*mockBazelRunner).bazelCommandRequests[aqueryCmd].Argv
-
- for _, expectedFlag := range expected {
- if !sliceContains(aqueryArgv, expectedFlag) {
- t.Errorf("aquery does not contain expected flag %#v. Argv was: %#v", expectedFlag, aqueryArgv)
- }
- }
-}
-
-func verifyAqueryDoesNotContainSubstrings(t *testing.T, config Config, substrings ...string) {
- t.Helper()
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
-
- err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
- }
-
- sliceContainsSubstring := func(slice []string, substring string) bool {
- for _, s := range slice {
- if strings.Contains(s, substring) {
- return true
- }
- }
- return false
- }
-
- aqueryArgv := bazelContext.bazelRunner.(*mockBazelRunner).bazelCommandRequests[aqueryCmd].Argv
-
- for _, substring := range substrings {
- if sliceContainsSubstring(aqueryArgv, substring) {
- t.Errorf("aquery contains unexpected substring %#v. Argv was: %#v", substring, aqueryArgv)
- }
- }
-}
-
-func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) (*mixedBuildBazelContext, string) {
- t.Helper()
- p := bazelPaths{
- soongOutDir: t.TempDir(),
- outputBase: "outputbase",
- workspaceDir: "workspace_dir",
- }
- if _, exists := bazelCommandResults[aqueryCmd]; !exists {
- bazelCommandResults[aqueryCmd] = ""
- }
- runner := &mockBazelRunner{
- testHelper: t,
- bazelCommandResults: bazelCommandResults,
- bazelCommandRequests: map[bazelCommand]bazel.CmdRequest{},
- }
- return &mixedBuildBazelContext{
- bazelRunner: runner,
- paths: &p,
- }, p.soongOutDir
-}
-
-// Transform the json format to ActionGraphContainer
-func JsonToActionGraphContainer(inputString string) ([]byte, error) {
- var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
- err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
- if err != nil {
- return []byte(""), err
- }
- data, _ := proto.Marshal(&aqueryProtoResult)
- return data, err
-}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
deleted file mode 100644
index f25803c..0000000
--- a/android/bazel_paths.go
+++ /dev/null
@@ -1,675 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "android/soong/bazel"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/pathtools"
-)
-
-// bazel_paths contains methods to:
-// * resolve Soong path and module references into bazel.LabelList
-// * resolve Bazel path references into Soong-compatible paths
-//
-// There is often a similar method for Bazel as there is for Soong path handling and should be used
-// in similar circumstances
-//
-// Bazel Soong
-// ==============================================================
-// BazelLabelForModuleSrc PathForModuleSrc
-// BazelLabelForModuleSrcExcludes PathForModuleSrcExcludes
-// BazelLabelForModuleDeps n/a
-// tbd PathForSource
-// tbd ExistentPathsForSources
-// PathForBazelOut PathForModuleOut
-//
-// Use cases:
-// * Module contains a property (often tagged `android:"path"`) that expects paths *relative to the
-// module directory*:
-// * BazelLabelForModuleSrcExcludes, if the module also contains an excludes_<propname> property
-// * BazelLabelForModuleSrc, otherwise
-// * Converting references to other modules to Bazel Labels:
-// BazelLabelForModuleDeps
-// * Converting a path obtained from bazel_handler cquery results:
-// PathForBazelOut
-//
-// NOTE: all Soong globs are expanded within Soong rather than being converted to a Bazel glob
-// syntax. This occurs because Soong does not have a concept of crossing package boundaries,
-// so the glob as computed by Soong may contain paths that cross package-boundaries. These
-// would be unknowingly omitted if the glob were handled by Bazel. By expanding globs within
-// Soong, we support identification and detection (within Bazel) use of paths that cross
-// package boundaries.
-//
-// Path resolution:
-// * filepath/globs: resolves as itself or is converted to an absolute Bazel label (e.g.
-// //path/to/dir:<filepath>) if path exists in a separate package or subpackage.
-// * references to other modules (using the ":name{.tag}" syntax). These resolve as a Bazel label
-// for a target. If the Bazel target is in the local module directory, it will be returned
-// relative to the current package (e.g. ":<target>"). Otherwise, it will be returned as an
-// absolute Bazel label (e.g. "//path/to/dir:<target>"). If the reference to another module
-// cannot be resolved,the function will panic. This is often due to the dependency not being added
-// via an AddDependency* method.
-
-// BazelConversionContext is a minimal context interface to check if a module should be converted by bp2build,
-// with functions containing information to match against allowlists and denylists.
-// If a module is deemed to be convertible by bp2build, then it should rely on a
-// BazelConversionPathContext for more functions for dep/path features.
-type BazelConversionContext interface {
- Config() Config
-
- Module() Module
- OtherModuleType(m blueprint.Module) string
- OtherModuleName(m blueprint.Module) string
- OtherModuleDir(m blueprint.Module) string
- ModuleErrorf(format string, args ...interface{})
-}
-
-// A subset of the ModuleContext methods which are sufficient to resolve references to paths/deps in
-// order to form a Bazel-compatible label for conversion.
-type BazelConversionPathContext interface {
- EarlyModulePathContext
- BazelConversionContext
-
- ModuleName() string
- ModuleType() string
- ModuleErrorf(fmt string, args ...interface{})
- PropertyErrorf(property, fmt string, args ...interface{})
- GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
- ModuleFromName(name string) (blueprint.Module, bool)
- AddUnconvertedBp2buildDep(string)
- AddMissingBp2buildDep(dep string)
-}
-
-// BazelLabelForModuleDeps expects a list of reference to other modules, ("<module>"
-// or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
-// module within the given ctx.
-func BazelLabelForModuleDeps(ctx Bp2buildMutatorContext, modules []string) bazel.LabelList {
- return BazelLabelForModuleDepsWithFn(ctx, modules, BazelModuleLabel, true)
-}
-
-// BazelLabelForModuleWholeDepsExcludes expects two lists: modules (containing modules to include in
-// the list), and excludes (modules to exclude from the list). Both of these should contain
-// references to other modules, ("<module>" or ":<module>"). It returns a Bazel-compatible label
-// list which corresponds to dependencies on the module within the given ctx, and the excluded
-// dependencies. Prebuilt dependencies will be appended with _alwayslink so they can be handled as
-// whole static libraries.
-func BazelLabelForModuleDepsExcludes(ctx Bp2buildMutatorContext, modules, excludes []string) bazel.LabelList {
- return BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, BazelModuleLabel)
-}
-
-// BazelLabelForModuleDepsWithFn expects a list of reference to other modules, ("<module>"
-// or ":<module>") and applies moduleToLabelFn to determine and return a Bazel-compatible label
-// which corresponds to dependencies on the module within the given ctx.
-func BazelLabelForModuleDepsWithFn(ctx Bp2buildMutatorContext, modules []string,
- moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string,
- markAsDeps bool) bazel.LabelList {
- var labels bazel.LabelList
- // In some cases, a nil string list is different than an explicitly empty list.
- if len(modules) == 0 && modules != nil {
- labels.Includes = []bazel.Label{}
- return labels
- }
- modules = FirstUniqueStrings(modules)
- for _, module := range modules {
- bpText := module
- if m := SrcIsModule(module); m == "" {
- module = ":" + module
- }
- if m, t := SrcIsModuleWithTag(module); m != "" {
- l := getOtherModuleLabel(ctx, m, t, moduleToLabelFn, markAsDeps)
- if l != nil {
- l.OriginalModuleName = bpText
- labels.Includes = append(labels.Includes, *l)
- }
- } else {
- ctx.ModuleErrorf("%q, is not a module reference", module)
- }
- }
- return labels
-}
-
-// BazelLabelForModuleDepsExcludesWithFn expects two lists: modules (containing modules to include in the
-// list), and excludes (modules to exclude from the list). Both of these should contain references
-// to other modules, ("<module>" or ":<module>"). It applies moduleToLabelFn to determine and return a
-// Bazel-compatible label list which corresponds to dependencies on the module within the given ctx, and
-// the excluded dependencies.
-func BazelLabelForModuleDepsExcludesWithFn(ctx Bp2buildMutatorContext, modules, excludes []string,
- moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string) bazel.LabelList {
- moduleLabels := BazelLabelForModuleDepsWithFn(ctx, RemoveListFromList(modules, excludes), moduleToLabelFn, true)
- if len(excludes) == 0 {
- return moduleLabels
- }
- excludeLabels := BazelLabelForModuleDepsWithFn(ctx, excludes, moduleToLabelFn, false)
- return bazel.LabelList{
- Includes: moduleLabels.Includes,
- Excludes: excludeLabels.Includes,
- }
-}
-
-func BazelLabelForModuleSrcSingle(ctx Bp2buildMutatorContext, path string) bazel.Label {
- if srcs := BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes; len(srcs) > 0 {
- return srcs[0]
- }
- return bazel.Label{}
-}
-
-func BazelLabelForModuleDepSingle(ctx Bp2buildMutatorContext, path string) bazel.Label {
- if srcs := BazelLabelForModuleDepsExcludes(ctx, []string{path}, []string(nil)).Includes; len(srcs) > 0 {
- return srcs[0]
- }
- return bazel.Label{}
-}
-
-// BazelLabelForModuleSrc expects a list of path (relative to local module directory) and module
-// references (":<module>") and returns a bazel.LabelList{} containing the resolved references in
-// paths, relative to the local module, or Bazel-labels (absolute if in a different package or
-// relative if within the same package).
-// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
-// will have already been handled by the pathdeps mutator.
-func BazelLabelForModuleSrc(ctx Bp2buildMutatorContext, paths []string) bazel.LabelList {
- return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
-}
-
-// BazelLabelForModuleSrc expects lists of path and excludes (relative to local module directory)
-// and module references (":<module>") and returns a bazel.LabelList{} containing the resolved
-// references in paths, minus those in excludes, relative to the local module, or Bazel-labels
-// (absolute if in a different package or relative if within the same package).
-// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
-// will have already been handled by the pathdeps mutator.
-func BazelLabelForModuleSrcExcludes(ctx Bp2buildMutatorContext, paths, excludes []string) bazel.LabelList {
- excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil), false)
- excluded := make([]string, 0, len(excludeLabels.Includes))
- for _, e := range excludeLabels.Includes {
- excluded = append(excluded, e.Label)
- }
- labels := expandSrcsForBazel(ctx, paths, excluded, true)
- labels.Excludes = excludeLabels.Includes
- labels = TransformSubpackagePaths(ctx.Config(), ctx.ModuleDir(), labels)
- return labels
-}
-
-func BazelLabelForSrcPatternExcludes(ctx BazelConversionPathContext, dir, pattern string, excludes []string) bazel.LabelList {
- topRelPaths, err := ctx.GlobWithDeps(filepath.Join(dir, pattern), excludes)
- if err != nil {
- ctx.ModuleErrorf("Could not search dir: %s for pattern %s due to %v\n", dir, pattern, err)
- }
- // An intermediate list of labels relative to `dir` that assumes that there no subpacakges beneath `dir`
- dirRelLabels := []bazel.Label{}
- for _, topRelPath := range topRelPaths {
- dirRelPath := Rel(ctx, dir, topRelPath)
- dirRelLabels = append(dirRelLabels, bazel.Label{Label: "./" + dirRelPath})
- }
- // Return the package boudary resolved labels
- return TransformSubpackagePaths(ctx.Config(), dir, bazel.MakeLabelList(dirRelLabels))
-}
-
-// Returns true if a prefix + components[:i] is a package boundary.
-//
-// A package boundary is determined by a BUILD file in the directory. This can happen in 2 cases:
-//
-// 1. An Android.bp exists, which bp2build will always convert to a sibling BUILD file.
-// 2. An Android.bp doesn't exist, but a checked-in BUILD/BUILD.bazel file exists, and that file
-// is allowlisted by the bp2build configuration to be merged into the symlink forest workspace.
-func isPackageBoundary(config Config, prefix string, components []string, componentIndex int) bool {
- isSymlink := func(c Config, path string) bool {
- f, err := c.fs.Lstat(path)
- if err != nil {
- // The file does not exist
- return false
- }
- return f.Mode()&os.ModeSymlink == os.ModeSymlink
- }
- prefix = filepath.Join(prefix, filepath.Join(components[:componentIndex+1]...))
- if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "Android.bp")); exists {
- return true
- } else if config.Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(prefix) || isSymlink(config, prefix) {
- if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "BUILD")); exists {
- return true
- } else if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "BUILD.bazel")); exists {
- return true
- }
- }
-
- return false
-}
-
-// Transform a path (if necessary) to acknowledge package boundaries
-//
-// e.g. something like
-//
-// async_safe/include/async_safe/CHECK.h
-//
-// might become
-//
-// //bionic/libc/async_safe:include/async_safe/CHECK.h
-//
-// if the "async_safe" directory is actually a package and not just a directory.
-//
-// In particular, paths that extend into packages are transformed into absolute labels beginning with //.
-func transformSubpackagePath(cfg Config, dir string, path bazel.Label) bazel.Label {
- var newPath bazel.Label
-
- // Don't transform OriginalModuleName
- newPath.OriginalModuleName = path.OriginalModuleName
- // if it wasn't a module, store the original path. We may need the original path to replace
- // references if it is actually in another package
- if path.OriginalModuleName == "" {
- newPath.OriginalModuleName = path.Label
- }
-
- if strings.HasPrefix(path.Label, "//") {
- // Assume absolute labels are already correct (e.g. //path/to/some/package:foo.h)
- newPath.Label = path.Label
- return newPath
- }
- if strings.HasPrefix(path.Label, "./") {
- // Drop "./" for consistent handling of paths.
- // Specifically, to not let "." be considered a package boundary.
- // Say `inputPath` is `x/Android.bp` and that file has some module
- // with `srcs=["y/a.c", "z/b.c"]`.
- // And say the directory tree is:
- // x
- // ├── Android.bp
- // ├── y
- // │ ├── a.c
- // │ └── Android.bp
- // └── z
- // └── b.c
- // Then bazel equivalent labels in srcs should be:
- // //x/y:a.c, x/z/b.c
- // The above should still be the case if `x/Android.bp` had
- // srcs=["./y/a.c", "./z/b.c"]
- // However, if we didn't strip "./", we'd get
- // //x/./y:a.c, //x/.:z/b.c
- path.Label = strings.TrimPrefix(path.Label, "./")
- }
- pathComponents := strings.Split(path.Label, "/")
- newLabel := ""
- foundPackageBoundary := false
- // Check the deepest subdirectory first and work upwards
- for i := len(pathComponents) - 1; i >= 0; i-- {
- pathComponent := pathComponents[i]
- var sep string
- if !foundPackageBoundary && isPackageBoundary(cfg, dir, pathComponents, i) {
- sep = ":"
- foundPackageBoundary = true
- } else {
- sep = "/"
- }
- if newLabel == "" {
- newLabel = pathComponent
- } else {
- newLabel = pathComponent + sep + newLabel
- }
- }
- if foundPackageBoundary {
- // Ensure paths end up looking like //bionic/... instead of //./bionic/...
- moduleDir := dir
- if strings.HasPrefix(moduleDir, ".") {
- moduleDir = moduleDir[1:]
- }
- // Make the path into an absolute label (e.g. //bionic/libc/foo:bar.h instead of just foo:bar.h)
- if moduleDir == "" {
- newLabel = "//" + newLabel
- } else {
- newLabel = "//" + moduleDir + "/" + newLabel
- }
- }
- newPath.Label = newLabel
-
- return newPath
-}
-
-// Transform paths to acknowledge package boundaries
-// See transformSubpackagePath() for more information
-func TransformSubpackagePaths(cfg Config, dir string, paths bazel.LabelList) bazel.LabelList {
- var newPaths bazel.LabelList
- for _, include := range paths.Includes {
- newPaths.Includes = append(newPaths.Includes, transformSubpackagePath(cfg, dir, include))
- }
- for _, exclude := range paths.Excludes {
- newPaths.Excludes = append(newPaths.Excludes, transformSubpackagePath(cfg, dir, exclude))
- }
- return newPaths
-}
-
-// Converts root-relative Paths to a list of bazel.Label relative to the module in ctx.
-func RootToModuleRelativePaths(ctx BazelConversionPathContext, paths Paths) []bazel.Label {
- var newPaths []bazel.Label
- for _, path := range PathsWithModuleSrcSubDir(ctx, paths, "") {
- s := path.Rel()
- newPaths = append(newPaths, bazel.Label{Label: s})
- }
- return newPaths
-}
-
-var Bp2buildDepTag bp2buildDepTag
-
-type bp2buildDepTag struct {
- blueprint.BaseDependencyTag
-}
-
-// expandSrcsForBazel returns bazel.LabelList with paths rooted from the module's local source
-// directory and Bazel target labels, excluding those included in the excludes argument (which
-// should already be expanded to resolve references to Soong-modules). Valid elements of paths
-// include:
-// - filepath, relative to local module directory, resolves as a filepath relative to the local
-// source directory
-// - glob, relative to the local module directory, resolves as filepath(s), relative to the local
-// module directory. Because Soong does not have a concept of crossing package boundaries, the
-// glob as computed by Soong may contain paths that cross package-boundaries that would be
-// unknowingly omitted if the glob were handled by Bazel. To allow identification and detect
-// (within Bazel) use of paths that cross package boundaries, we expand globs within Soong rather
-// than converting Soong glob syntax to Bazel glob syntax. **Invalid for excludes.**
-// - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer
-// or OutputFileProducer. These resolve as a Bazel label for a target. If the Bazel target is in
-// the local module directory, it will be returned relative to the current package (e.g.
-// ":<target>"). Otherwise, it will be returned as an absolute Bazel label (e.g.
-// "//path/to/dir:<target>"). If the reference to another module cannot be resolved,the function
-// will panic.
-//
-// Properties passed as the paths or excludes argument must have been annotated with struct tag
-// `android:"path"` so that dependencies on other modules will have already been handled by the
-// pathdeps mutator.
-func expandSrcsForBazel(ctx Bp2buildMutatorContext, paths, expandedExcludes []string, markAsDeps bool) bazel.LabelList {
- if paths == nil {
- return bazel.LabelList{}
- }
- labels := bazel.LabelList{
- Includes: []bazel.Label{},
- }
-
- // expandedExcludes contain module-dir relative paths, but root-relative paths
- // are needed for GlobFiles later.
- var rootRelativeExpandedExcludes []string
- for _, e := range expandedExcludes {
- rootRelativeExpandedExcludes = append(rootRelativeExpandedExcludes, filepath.Join(ctx.ModuleDir(), e))
- }
-
- for _, p := range paths {
- if m, tag := SrcIsModuleWithTag(p); m != "" {
- l := getOtherModuleLabel(ctx, m, tag, BazelModuleLabel, markAsDeps)
- if l != nil && !InList(l.Label, expandedExcludes) {
- if strings.HasPrefix(m, "//") {
- // this is a module in a soong namespace
- // It appears as //<namespace>:<module_name> in srcs, and not ://<namespace>:<module_name>
- l.OriginalModuleName = m
- } else {
- l.OriginalModuleName = fmt.Sprintf(":%s", m)
- }
- labels.Includes = append(labels.Includes, *l)
- }
- } else {
- var expandedPaths []bazel.Label
- if pathtools.IsGlob(p) {
- // e.g. turn "math/*.c" in
- // external/arm-optimized-routines to external/arm-optimized-routines/math/*.c
- rootRelativeGlobPath := pathForModuleSrc(ctx, p).String()
- expandedPaths = RootToModuleRelativePaths(ctx, GlobFiles(ctx, rootRelativeGlobPath, rootRelativeExpandedExcludes))
- } else {
- if !InList(p, expandedExcludes) {
- expandedPaths = append(expandedPaths, bazel.Label{Label: p})
- }
- }
- labels.Includes = append(labels.Includes, expandedPaths...)
- }
- }
- return labels
-}
-
-// getOtherModuleLabel returns a bazel.Label for the given dependency/tag combination for the
-// module. The label will be relative to the current directory if appropriate. The dependency must
-// already be resolved by either deps mutator or path deps mutator.
-func getOtherModuleLabel(ctx Bp2buildMutatorContext, dep, tag string,
- labelFromModule func(BazelConversionPathContext, blueprint.Module) string,
- markAsDep bool) *bazel.Label {
- m, _ := ctx.ModuleFromName(dep)
- // The module was not found in an Android.bp file, this is often due to:
- // * a limited manifest
- // * a required module not being converted from Android.mk
- if m == nil {
- ctx.AddMissingBp2buildDep(dep)
- return &bazel.Label{
- Label: ":" + dep + "__BP2BUILD__MISSING__DEP",
- }
- }
- // Returns true if a dependency from the current module to the target module
- // should be skipped; doing so is a hack to circumvent certain problematic
- // scenarios that will be addressed in the future.
- shouldSkipDep := func(dep string) bool {
- // Don't count dependencies of "libc". This is a hack to circumvent the
- // fact that, in a variantless build graph, "libc" has a dependency on itself.
- if ctx.ModuleName() == "libc" {
- return true
- }
-
- // TODO: b/303307672: Dependencies on this module happen to "work" because
- // there is a source file with the same name as this module in the
- // same directory. We should remove this hack and enforce the underlying
- // module of this name is the actual one used.
- if dep == "mke2fs.conf" {
- return true
- }
-
- // TODO: b/303310285: Remove this special-casing once all dependencies of
- // crtbegin_dynamic are convertible
- if ctx.ModuleName() == "crtbegin_dynamic" {
- return true
- }
-
- return false
- }
- if markAsDep && !shouldSkipDep(dep) {
- ctx.AddDependency(ctx.Module(), Bp2buildDepTag, dep)
- }
- if !convertedToBazel(ctx, m) {
- ctx.AddUnconvertedBp2buildDep(dep)
- }
- label := BazelModuleLabel(ctx, ctx.Module())
- otherLabel := labelFromModule(ctx, m)
-
- // TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
- if (tag != "" && m.Name() == "framework-res") ||
- (tag == ".generated_srcjars" && ctx.OtherModuleType(m) == "java_aconfig_library") {
- otherLabel += tag
- }
-
- if samePackage(label, otherLabel) {
- otherLabel = bazelShortLabel(otherLabel)
- }
-
- return &bazel.Label{
- Label: otherLabel,
- }
-}
-
-func BazelModuleLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
- // TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
- if !convertedToBazel(ctx, module) || isGoModule(module) {
- return bp2buildModuleLabel(ctx, module)
- }
- b, _ := module.(Bazelable)
- return b.GetBazelLabel(ctx, module)
-}
-
-func bazelShortLabel(label string) string {
- i := strings.Index(label, ":")
- if i == -1 {
- panic(fmt.Errorf("Could not find the ':' character in '%s', expected a fully qualified label.", label))
- }
- return label[i:]
-}
-
-func bazelPackage(label string) string {
- i := strings.Index(label, ":")
- if i == -1 {
- panic(fmt.Errorf("Could not find the ':' character in '%s', expected a fully qualified label.", label))
- }
- return label[0:i]
-}
-
-func samePackage(label1, label2 string) bool {
- return bazelPackage(label1) == bazelPackage(label2)
-}
-
-func bp2buildModuleLabel(ctx BazelConversionContext, module blueprint.Module) string {
- moduleName := moduleNameWithPossibleOverride(ctx, module, ctx.OtherModuleName(module))
- moduleDir := moduleDirWithPossibleOverride(ctx, module, ctx.OtherModuleDir(module))
- if moduleDir == Bp2BuildTopLevel {
- moduleDir = ""
- }
- if a, ok := module.(Module); ok && IsModulePrebuilt(a) {
- moduleName = RemoveOptionalPrebuiltPrefix(moduleName)
- }
- return fmt.Sprintf("//%s:%s", moduleDir, moduleName)
-}
-
-// BazelOutPath is a Bazel output path compatible to be used for mixed builds within Soong/Ninja.
-type BazelOutPath struct {
- OutputPath
-}
-
-// ensure BazelOutPath implements Path
-var _ Path = BazelOutPath{}
-
-// ensure BazelOutPath implements genPathProvider
-var _ genPathProvider = BazelOutPath{}
-
-// ensure BazelOutPath implements objPathProvider
-var _ objPathProvider = BazelOutPath{}
-
-func (p BazelOutPath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath {
- return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
-}
-
-func (p BazelOutPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
- return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
-}
-
-// PathForBazelOutRelative returns a BazelOutPath representing the path under an output directory dedicated to
-// bazel-owned outputs. Calling .Rel() on the result will give the input path as relative to the given
-// relativeRoot.
-func PathForBazelOutRelative(ctx PathContext, relativeRoot string, path string) BazelOutPath {
- validatedPath, err := validatePath(filepath.Join("execroot", "__main__", path))
- if err != nil {
- reportPathError(ctx, err)
- }
- var relativeRootPath string
- if pathComponents := strings.SplitN(path, "/", 4); len(pathComponents) >= 3 &&
- pathComponents[0] == "bazel-out" && pathComponents[2] == "bin" {
- // If the path starts with something like: bazel-out/linux_x86_64-fastbuild-ST-b4ef1c4402f9/bin/
- // make it relative to that folder. bazel-out/volatile-status.txt is an example
- // of something that starts with bazel-out but is not relative to the bin folder
- relativeRootPath = filepath.Join("execroot", "__main__", pathComponents[0], pathComponents[1], pathComponents[2], relativeRoot)
- } else {
- relativeRootPath = filepath.Join("execroot", "__main__", relativeRoot)
- }
-
- var relPath string
- if relPath, err = filepath.Rel(relativeRootPath, validatedPath); err != nil || strings.HasPrefix(relPath, "../") {
- // We failed to make this path relative to execroot/__main__, fall back to a non-relative path
- // One case where this happens is when path is ../bazel_tools/something
- relativeRootPath = ""
- relPath = validatedPath
- }
-
- outputPath := OutputPath{
- basePath{"", ""},
- ctx.Config().soongOutDir,
- ctx.Config().BazelContext.OutputBase(),
- }
-
- return BazelOutPath{
- // .withRel() appends its argument onto the current path, and only the most
- // recently appended part is returned by outputPath.rel().
- // So outputPath.rel() will return relPath.
- OutputPath: outputPath.withRel(relativeRootPath).withRel(relPath),
- }
-}
-
-// PathForBazelOut returns a BazelOutPath representing the path under an output directory dedicated to
-// bazel-owned outputs.
-func PathForBazelOut(ctx PathContext, path string) BazelOutPath {
- return PathForBazelOutRelative(ctx, "", path)
-}
-
-// PathsForBazelOut returns a list of paths representing the paths under an output directory
-// dedicated to Bazel-owned outputs.
-func PathsForBazelOut(ctx PathContext, paths []string) Paths {
- outs := make(Paths, 0, len(paths))
- for _, p := range paths {
- outs = append(outs, PathForBazelOut(ctx, p))
- }
- return outs
-}
-
-// BazelStringOrLabelFromProp splits a Soong module property that can be
-// either a string literal, path (with android:path tag) or a module reference
-// into separate bazel string or label attributes. Bazel treats string and label
-// attributes as distinct types, so this function categorizes a string property
-// into either one of them.
-//
-// e.g. apex.private_key = "foo.pem" can either refer to:
-//
-// 1. "foo.pem" in the current directory -> file target
-// 2. "foo.pem" module -> rule target
-// 3. "foo.pem" file in a different directory, prefixed by a product variable handled
-// in a bazel macro. -> string literal
-//
-// For the first two cases, they are defined using the label attribute. For the third case,
-// it's defined with the string attribute.
-func BazelStringOrLabelFromProp(
- ctx Bp2buildMutatorContext,
- propToDistinguish *string) (bazel.LabelAttribute, bazel.StringAttribute) {
-
- var labelAttr bazel.LabelAttribute
- var strAttr bazel.StringAttribute
-
- if propToDistinguish == nil {
- // nil pointer
- return labelAttr, strAttr
- }
-
- prop := String(propToDistinguish)
- if SrcIsModule(prop) != "" {
- // If it's a module (SrcIsModule will return the module name), set the
- // resolved label to the label attribute.
- labelAttr.SetValue(BazelLabelForModuleDepSingle(ctx, prop))
- } else {
- // Not a module name. This could be a string literal or a file target in
- // the current dir. Check if the path exists:
- path := ExistentPathForSource(ctx, ctx.ModuleDir(), prop)
-
- if path.Valid() && parentDir(path.String()) == ctx.ModuleDir() {
- // If it exists and the path is relative to the current dir, resolve the bazel label
- // for the _file target_ and set it to the label attribute.
- //
- // Resolution is necessary because this could be a file in a subpackage.
- labelAttr.SetValue(BazelLabelForModuleSrcSingle(ctx, prop))
- } else {
- // Otherwise, treat it as a string literal and assign to the string attribute.
- strAttr.Value = propToDistinguish
- }
- }
-
- return labelAttr, strAttr
-}
diff --git a/android/bazel_paths_test.go b/android/bazel_paths_test.go
deleted file mode 100644
index bed719c..0000000
--- a/android/bazel_paths_test.go
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright 2022 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android
-
-import (
- "fmt"
- "path/filepath"
- "testing"
-
- "android/soong/bazel"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/pathtools"
-)
-
-type TestBazelPathContext struct{}
-
-func (*TestBazelPathContext) Config() Config {
- cfg := NullConfig("out", "out/soong")
- cfg.BazelContext = MockBazelContext{
- OutputBaseDir: "out/bazel",
- }
- return cfg
-}
-
-func (*TestBazelPathContext) AddNinjaFileDeps(...string) {
- panic("Unimplemented")
-}
-
-func TestPathForBazelOut(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOut(ctx, "foo/bar/baz/boq.txt")
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/__main__/foo/bar/baz/boq.txt")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "foo/bar/baz/boq.txt"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-func TestPathForBazelOutRelative(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOutRelative(ctx, "foo/bar", "foo/bar/baz/boq.txt")
-
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/__main__/foo/bar/baz/boq.txt")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "baz/boq.txt"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-func TestPathForBazelOutRelativeUnderBinFolder(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOutRelative(ctx, "foo/bar", "bazel-out/linux_x86_64-fastbuild-ST-b4ef1c4402f9/bin/foo/bar/baz/boq.txt")
-
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/__main__/bazel-out/linux_x86_64-fastbuild-ST-b4ef1c4402f9/bin/foo/bar/baz/boq.txt")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "baz/boq.txt"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-func TestPathForBazelOutOutsideOfExecroot(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOut(ctx, "../bazel_tools/linux_x86_64-fastbuild/bin/tools/android/java_base_extras.jar")
-
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/bazel_tools/linux_x86_64-fastbuild/bin/tools/android/java_base_extras.jar")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "execroot/bazel_tools/linux_x86_64-fastbuild/bin/tools/android/java_base_extras.jar"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-func TestPathForBazelOutRelativeWithParentDirectoryRoot(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOutRelative(ctx, "../bazel_tools", "../bazel_tools/foo/bar/baz.sh")
-
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/bazel_tools/foo/bar/baz.sh")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "foo/bar/baz.sh"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-type TestBazelConversionPathContext struct {
- TestBazelConversionContext
- moduleDir string
- cfg Config
- mockGlobResults *[]string
-}
-
-func (ctx *TestBazelConversionPathContext) AddNinjaFileDeps(...string) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) GlobWithDeps(string, []string) ([]string, error) {
- if ctx.mockGlobResults == nil {
- return []string{}, fmt.Errorf("Set mock glob results first")
- }
- return *ctx.mockGlobResults, nil
-}
-
-func (ctx *TestBazelConversionPathContext) PropertyErrorf(string, string, ...interface{}) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) GetDirectDep(string) (blueprint.Module, blueprint.DependencyTag) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) ModuleFromName(string) (blueprint.Module, bool) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) AddUnconvertedBp2buildDep(string) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) AddMissingBp2buildDep(string) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) Module() Module {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) Config() Config {
- return ctx.cfg
-}
-
-func (ctx *TestBazelConversionPathContext) ModuleDir() string {
- return ctx.moduleDir
-}
-
-func (ctx *TestBazelConversionPathContext) ModuleName() string {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) ModuleType() string {
- panic("Unimplemented")
-}
-
-func TestTransformSubpackagePath(t *testing.T) {
- cfg := NullConfig("out", "out/soong")
- cfg.fs = pathtools.MockFs(map[string][]byte{
- "x/Android.bp": nil,
- "x/y/Android.bp": nil,
- })
-
- var ctx BazelConversionPathContext = &TestBazelConversionPathContext{
- moduleDir: "x",
- cfg: cfg,
- }
- pairs := map[string]string{
- "y/a.c": "//x/y:a.c",
- "./y/a.c": "//x/y:a.c",
- "z/b.c": "z/b.c",
- "./z/b.c": "z/b.c",
- }
- for in, out := range pairs {
- actual := transformSubpackagePath(ctx.Config(), ctx.ModuleDir(), bazel.Label{Label: in}).Label
- if actual != out {
- t.Errorf("expected:\n%v\nactual:\n%v", out, actual)
- }
- }
-}
-
-// Check that the files in a specific directory are returned with labels that respect package boundaries
-// Since the test uses a mock for GlobWithDeps, the params passed to BazelLabelForSrcPatternExcludes are no-ops
-func TestBazelLabelForSrcPatternExcludes(t *testing.T) {
- cfg := NullConfig("out", "out/soong")
- cfg.fs = pathtools.MockFs(map[string][]byte{
- "x/Android.bp": nil,
- "x/y/Android.bp": nil,
- // .proto files
- "foo.proto": nil,
- "x/bar.proto": nil,
- "x/baz.proto": nil,
- "x/y/qux.proto": nil,
- })
-
- var ctx BazelConversionPathContext = &TestBazelConversionPathContext{
- cfg: cfg,
- }
-
- // Root dir
- ctx.(*TestBazelConversionPathContext).mockGlobResults = &[]string{"foo.proto", "x/bar.proto", "x/baz.proto", "x/y/qux.proto"}
- actualLabelsFromRoot := BazelLabelForSrcPatternExcludes(ctx, ".", "**/*.proto", []string{})
- expectedLabelsAsString := []string{"foo.proto", "//x:bar.proto", "//x:baz.proto", "//x/y:qux.proto"}
- for i, actual := range actualLabelsFromRoot.Includes {
- AssertStringEquals(t, "Error in finding src labels relative to root directory", expectedLabelsAsString[i], actual.Label)
- }
-
- // x dir
- ctx.(*TestBazelConversionPathContext).mockGlobResults = &[]string{"x/bar.proto", "x/baz.proto", "x/y/qux.proto"}
- actualLabelsFromRoot = BazelLabelForSrcPatternExcludes(ctx, "x", "**/*.proto", []string{})
- expectedLabelsAsString = []string{"bar.proto", "baz.proto", "//x/y:qux.proto"}
- for i, actual := range actualLabelsFromRoot.Includes {
- AssertStringEquals(t, "Error in finding src labels relative to x directory", expectedLabelsAsString[i], actual.Label)
- }
-
- // y dir
- ctx.(*TestBazelConversionPathContext).mockGlobResults = &[]string{"x/y/qux.proto"}
- actualLabelsFromRoot = BazelLabelForSrcPatternExcludes(ctx, "x/y", "**/*.proto", []string{})
- expectedLabelsAsString = []string{"qux.proto"}
- for i, actual := range actualLabelsFromRoot.Includes {
- AssertStringEquals(t, "Error in finding src labels relative to x/y directory", expectedLabelsAsString[i], actual.Label)
- }
-}
diff --git a/android/bazel_test.go b/android/bazel_test.go
deleted file mode 100644
index e0145b5..0000000
--- a/android/bazel_test.go
+++ /dev/null
@@ -1,592 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package android
-
-import (
- "fmt"
- "testing"
-
- "android/soong/android/allowlists"
- "android/soong/bazel"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
-)
-
-func TestConvertAllModulesInPackage(t *testing.T) {
- testCases := []struct {
- prefixes allowlists.Bp2BuildConfig
- packageDir string
- }{
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalse,
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b/c": allowlists.Bp2BuildDefaultFalse,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b": allowlists.Bp2BuildDefaultFalse,
- "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalseRecursively,
- "a/b": allowlists.Bp2BuildDefaultTrue,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalseRecursively,
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b/c",
- },
- }
-
- for _, test := range testCases {
- if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); !ok {
- t.Errorf("Expected to convert all modules in %s based on %v, but failed.", test.packageDir, test.prefixes)
- }
- }
-}
-
-func TestModuleOptIn(t *testing.T) {
- testCases := []struct {
- prefixes allowlists.Bp2BuildConfig
- packageDir string
- }{
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b": allowlists.Bp2BuildDefaultFalse,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalse,
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a", // opt-in by default
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "foo/bar",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b": allowlists.Bp2BuildDefaultFalse,
- "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalse,
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b/c": allowlists.Bp2BuildDefaultFalse,
- },
- packageDir: "a",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalseRecursively,
- "a/b": allowlists.Bp2BuildDefaultTrue,
- },
- packageDir: "a/b/c",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b": allowlists.Bp2BuildDefaultFalseRecursively,
- },
- packageDir: "a/b/c",
- },
- }
-
- for _, test := range testCases {
- if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); ok {
- t.Errorf("Expected to allow module opt-in in %s based on %v, but failed.", test.packageDir, test.prefixes)
- }
- }
-}
-
-type TestBazelModule struct {
- bazel.TestModuleInfo
- BazelModuleBase
-}
-
-var _ blueprint.Module = TestBazelModule{}
-
-func (m TestBazelModule) Name() string {
- return m.TestModuleInfo.ModuleName
-}
-
-func (m TestBazelModule) GenerateBuildActions(blueprint.ModuleContext) {
-}
-
-type TestBazelConversionContext struct {
- omc bazel.OtherModuleTestContext
- allowlist Bp2BuildConversionAllowlist
- errors []string
-}
-
-var _ bazelOtherModuleContext = &TestBazelConversionContext{}
-
-func (bcc *TestBazelConversionContext) OtherModuleType(m blueprint.Module) string {
- return bcc.omc.OtherModuleType(m)
-}
-
-func (bcc *TestBazelConversionContext) OtherModuleName(m blueprint.Module) string {
- return bcc.omc.OtherModuleName(m)
-}
-
-func (bcc *TestBazelConversionContext) OtherModuleDir(m blueprint.Module) string {
- return bcc.omc.OtherModuleDir(m)
-}
-
-func (bcc *TestBazelConversionContext) ModuleErrorf(format string, args ...interface{}) {
- bcc.errors = append(bcc.errors, fmt.Sprintf(format, args...))
-}
-
-func (bcc *TestBazelConversionContext) Config() Config {
- return Config{
- &config{
- Bp2buildPackageConfig: bcc.allowlist,
- },
- }
-}
-
-var bazelableBazelModuleBase = BazelModuleBase{
- bazelProperties: properties{
- Bazel_module: BazelModuleProperties{
- CanConvertToBazel: true,
- },
- },
-}
-
-func TestBp2BuildAllowlist(t *testing.T) {
- testCases := []struct {
- description string
- shouldConvert bool
- expectedErrors []string
- module TestBazelModule
- allowlist Bp2BuildConversionAllowlist
- }{
- {
- description: "allowlist enables module",
- shouldConvert: true,
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "dir1",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- },
- },
- {
- description: "module in name allowlist and type allowlist fails",
- shouldConvert: false,
- expectedErrors: []string{"A module \"foo\" of type \"rule1\" cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert"},
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "dir1",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- moduleTypeAlwaysConvert: map[string]bool{
- "rule1": true,
- },
- },
- },
- {
- description: "module in allowlist and denylist fails",
- shouldConvert: false,
- expectedErrors: []string{"a module \"foo\" cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert"},
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "dir1",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- moduleDoNotConvert: map[string]bool{
- "foo": true,
- },
- },
- },
- {
- description: "module allowlist and enabled directory",
- shouldConvert: false,
- expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "existing/build/dir",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- defaultConfig: allowlists.Bp2BuildConfig{
- "existing/build/dir": allowlists.Bp2BuildDefaultTrue,
- },
- },
- },
- {
- description: "module allowlist and enabled subdirectory",
- shouldConvert: false,
- expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "existing/build/dir/subdir",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- defaultConfig: allowlists.Bp2BuildConfig{
- "existing/build/dir": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- },
- },
- {
- description: "module enabled in unit test short-circuits other allowlists",
- shouldConvert: true,
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: ".",
- },
- BazelModuleBase: BazelModuleBase{
- bazelProperties: properties{
- Bazel_module: BazelModuleProperties{
- CanConvertToBazel: true,
- Bp2build_available: proptools.BoolPtr(true),
- },
- },
- },
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- moduleDoNotConvert: map[string]bool{
- "foo": true,
- },
- },
- },
- }
-
- for _, test := range testCases {
- t.Run(test.description, func(t *testing.T) {
- bcc := &TestBazelConversionContext{
- omc: bazel.OtherModuleTestContext{
- Modules: []bazel.TestModuleInfo{
- test.module.TestModuleInfo,
- },
- },
- allowlist: test.allowlist,
- }
-
- shouldConvert := test.module.shouldConvertWithBp2build(bcc,
- shouldConvertParams{
- module: test.module.TestModuleInfo,
- moduleDir: test.module.TestModuleInfo.Dir,
- moduleType: test.module.TestModuleInfo.Typ,
- moduleName: test.module.TestModuleInfo.ModuleName,
- },
- )
- if test.shouldConvert != shouldConvert {
- t.Errorf("Module shouldConvert expected to be: %v, but was: %v", test.shouldConvert, shouldConvert)
- }
-
- errorsMatch := true
- if len(test.expectedErrors) != len(bcc.errors) {
- errorsMatch = false
- } else {
- for i, err := range test.expectedErrors {
- if err != bcc.errors[i] {
- errorsMatch = false
- }
- }
- }
- if !errorsMatch {
- t.Errorf("Expected errors to be: %v, but were: %v", test.expectedErrors, bcc.errors)
- }
- })
- }
-}
-
-func TestBp2buildAllowList(t *testing.T) {
- 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])
- }
- }
- for k, v := range allowlists.Bp2buildKeepExistingBuildFile {
- if allowlist.keepExistingBuildFile[k] != v {
- t.Errorf("bp2build keep existing build file of %s: expected: %v, got: %v", k, v, allowlist.keepExistingBuildFile[k])
- }
- }
- for _, k := range allowlists.Bp2buildModuleTypeAlwaysConvertList {
- if !allowlist.moduleTypeAlwaysConvert[k] {
- t.Errorf("bp2build module type always convert of %s: expected: true, got: %v", k, allowlist.moduleTypeAlwaysConvert[k])
- }
- }
- for _, k := range allowlists.Bp2buildModuleDoNotConvertList {
- if !allowlist.moduleDoNotConvert[k] {
- t.Errorf("bp2build module do not convert of %s: expected: true, got: %v", k, allowlist.moduleDoNotConvert[k])
- }
- }
-}
-
-func TestShouldKeepExistingBuildFileForDir(t *testing.T) {
- allowlist := NewBp2BuildAllowlist()
- // entry "a/b2/c2" is moot because of its parent "a/b2"
- allowlist.SetKeepExistingBuildFile(map[string]bool{"a": false, "a/b1": false, "a/b2": true, "a/b1/c1": true, "a/b2/c2": false})
- truths := []string{"a", "a/b1", "a/b2", "a/b1/c1", "a/b2/c", "a/b2/c2", "a/b2/c2/d"}
- falsities := []string{"a1", "a/b", "a/b1/c"}
- for _, dir := range truths {
- if !allowlist.ShouldKeepExistingBuildFileForDir(dir) {
- t.Errorf("%s expected TRUE but was FALSE", dir)
- }
- }
- for _, dir := range falsities {
- if allowlist.ShouldKeepExistingBuildFileForDir(dir) {
- t.Errorf("%s expected FALSE but was TRUE", dir)
- }
- }
-}
-
-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 Bp2buildMutatorContext) {
-}
-
-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)
- }
- })
- }
-}
diff --git a/android/config.go b/android/config.go
index 9293505..0fec792 100644
--- a/android/config.go
+++ b/android/config.go
@@ -84,21 +84,13 @@
SoongOutDir string
SoongVariables string
- SymlinkForestMarker string
- Bp2buildMarker string
- BazelQueryViewDir string
- ModuleGraphFile string
- ModuleActionsFile string
- DocFile string
+ BazelQueryViewDir string
+ ModuleGraphFile string
+ ModuleActionsFile string
+ DocFile string
MultitreeBuild bool
- BazelMode bool
- BazelModeStaging bool
- BazelForceEnabledModules string
-
- UseBazelProxy bool
-
BuildFromSourceStub bool
EnsureAllowlistIntegrity bool
@@ -109,12 +101,6 @@
// Don't use bazel at all during module analysis.
AnalysisNoBazel SoongBuildMode = iota
- // Symlink fores mode: merge two directory trees into a symlink forest
- SymlinkForest
-
- // 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.
@@ -125,15 +111,6 @@
// Generate a documentation file for module type definitions and exit.
GenerateDocFile
-
- // Use bazel during analysis of a few allowlisted build modules. The allowlist
- // is considered "staging, as these are modules being prepared to be released
- // into prod mode shortly after.
- BazelStagingMode
-
- // Use bazel during analysis of build modules from an allowlist carefully
- // curated by the build team to be proven stable.
- BazelProdMode
)
// SoongOutDir returns the build output directory for the configuration.
@@ -265,10 +242,6 @@
// Only available on configs created by TestConfig
TestProductVariables *ProductVariables
- // A specialized context object for Bazel/Soong mixed builds and migration
- // purposes.
- BazelContext BazelContext
-
ProductVariablesFileName string
// BuildOS stores the OsType for the OS that the build is running on.
@@ -310,9 +283,7 @@
fs pathtools.FileSystem
mockBpList string
- BuildMode SoongBuildMode
- Bp2buildPackageConfig Bp2BuildConversionAllowlist
- Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions
+ BuildMode SoongBuildMode
// If MultitreeBuild is true then this is one inner tree of a multitree
// build directed by the multitree orchestrator.
@@ -328,29 +299,6 @@
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{}
-
- // These are modules to be built with Bazel beyond the allowlisted/build-mode
- // specified modules. They are passed via the command-line flag
- // "--bazel-force-enabled-modules"
- bazelForceEnabledModules map[string]struct{}
-
- // Names of Bazel targets as defined by BUILD files in the source tree,
- // keyed by the directory in which they are defined.
- bazelTargetsByDir map[string][]string
-
- // If true, for any requests to Bazel, communicate with a Bazel proxy using
- // unix sockets, instead of spawning Bazel as a subprocess.
- UseBazelProxy bool
-
// If buildFromSourceStub is true then the Java API stubs are
// built from the source Java files, not the signature text files.
buildFromSourceStub bool
@@ -561,14 +509,10 @@
runGoTests: cmdArgs.RunGoTests,
multilibConflicts: make(map[ArchType]bool),
- moduleListFile: cmdArgs.ModuleListFile,
- fs: pathtools.NewOsFs(absSrcDir),
- mixedBuildDisabledModules: make(map[string]struct{}),
- mixedBuildEnabledModules: make(map[string]struct{}),
- bazelForceEnabledModules: make(map[string]struct{}),
+ moduleListFile: cmdArgs.ModuleListFile,
+ fs: pathtools.NewOsFs(absSrcDir),
MultitreeBuild: cmdArgs.MultitreeBuild,
- UseBazelProxy: cmdArgs.UseBazelProxy,
buildFromSourceStub: cmdArgs.BuildFromSourceStub,
}
@@ -661,28 +605,9 @@
config.BuildMode = mode
}
}
- setBazelMode := func(arg bool, argName string, mode SoongBuildMode) {
- if arg {
- if config.BuildMode != AnalysisNoBazel {
- fmt.Fprintf(os.Stderr, "buildMode is already set, illegal argument: %s", argName)
- os.Exit(1)
- }
- config.BuildMode = mode
- }
- }
- setBuildMode(cmdArgs.SymlinkForestMarker, SymlinkForest)
- setBuildMode(cmdArgs.Bp2buildMarker, Bp2build)
setBuildMode(cmdArgs.BazelQueryViewDir, GenerateQueryView)
setBuildMode(cmdArgs.ModuleGraphFile, GenerateModuleGraph)
setBuildMode(cmdArgs.DocFile, GenerateDocFile)
- setBazelMode(cmdArgs.BazelMode, "--bazel-mode", BazelProdMode)
- setBazelMode(cmdArgs.BazelModeStaging, "--bazel-mode-staging", BazelStagingMode)
-
- for _, module := range getForceEnabledModulesFromFlag(cmdArgs.BazelForceEnabledModules) {
- config.bazelForceEnabledModules[module] = struct{}{}
- }
- config.BazelContext, err = NewBazelContext(config)
- config.Bp2buildPackageConfig = GetBp2BuildAllowList()
// TODO(b/276958307): Replace the hardcoded list to a sdk_library local prop.
config.apiLibraries = map[string]struct{}{
@@ -719,13 +644,6 @@
return Config{config}, err
}
-func getForceEnabledModulesFromFlag(forceEnabledFlag string) []string {
- if forceEnabledFlag == "" {
- return []string{}
- }
- return strings.Split(forceEnabledFlag, ",")
-}
-
// mockFileSystem replaces all reads with accesses to the provided map of
// filenames to contents stored as a byte slice.
func (c *config) mockFileSystem(bp string, fs map[string][]byte) {
@@ -756,41 +674,6 @@
c.mockBpList = blueprint.MockModuleListFile
}
-// TODO(b/265062549): Add a field to our collected (and uploaded) metrics which
-// describes a reason that we fell back to non-mixed builds.
-// Returns true if "Bazel builds" is enabled. In this mode, part of build
-// analysis is handled by Bazel.
-func (c *config) IsMixedBuildsEnabled() bool {
- globalMixedBuildsSupport := c.Once(OnceKey{"globalMixedBuildsSupport"}, func() interface{} {
- if c.productVariables.DeviceArch != nil && *c.productVariables.DeviceArch == "riscv64" {
- return false
- }
- // Disable Bazel when Kythe is running
- if c.EmitXrefRules() {
- return false
- }
- if c.IsEnvTrue("GLOBAL_THINLTO") {
- return false
- }
- if len(c.productVariables.SanitizeHost) > 0 {
- return false
- }
- if len(c.productVariables.SanitizeDevice) > 0 {
- return false
- }
- if len(c.productVariables.SanitizeDeviceDiag) > 0 {
- return false
- }
- if len(c.productVariables.SanitizeDeviceArch) > 0 {
- return false
- }
- return true
- }).(bool)
-
- bazelModeEnabled := c.BuildMode == BazelProdMode || c.BuildMode == BazelStagingMode
- return globalMixedBuildsSupport && bazelModeEnabled
-}
-
func (c *config) SetAllowMissingDependencies() {
c.productVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
}
@@ -1066,8 +949,6 @@
// DefaultAppTargetSdk returns the API level that platform apps are targeting.
// This converts a codename to the exact ApiLevel it represents.
func (c *config) DefaultAppTargetSdk(ctx EarlyModuleContext) ApiLevel {
- // This logic is replicated in starlark, if changing logic here update starlark code too
- // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/common/api.bzl;l=72;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
if Bool(c.productVariables.Platform_sdk_final) {
return c.PlatformSdkVersion()
}
@@ -1425,10 +1306,6 @@
return String(c.productVariables.PrebuiltHiddenApiDir)
}
-func (c *config) BazelModulesForceEnabledByFlag() map[string]struct{} {
- return c.bazelForceEnabledModules
-}
-
func (c *config) IsVndkDeprecated() bool {
return !Bool(c.productVariables.KeepVndk)
}
@@ -2041,38 +1918,6 @@
return Bool(c.productVariables.HostMusl)
}
-func (c *config) GetMixedBuildsEnabledModules() map[string]struct{} {
- return c.mixedBuildEnabledModules
-}
-
-func (c *config) GetMixedBuildsDisabledModules() map[string]struct{} {
- return c.mixedBuildDisabledModules
-}
-
-func (c *config) LogMixedBuild(ctx BaseModuleContext, useBazel bool) {
- moduleName := ctx.Module().Name()
- c.mixedBuildsLock.Lock()
- defer c.mixedBuildsLock.Unlock()
- if useBazel {
- c.mixedBuildEnabledModules[moduleName] = struct{}{}
- } else {
- c.mixedBuildDisabledModules[moduleName] = struct{}{}
- }
-}
-
-func (c *config) HasBazelBuildTargetInSource(dir string, target string) bool {
- for _, existingTarget := range c.bazelTargetsByDir[dir] {
- if target == existingTarget {
- return true
- }
- }
- return false
-}
-
-func (c *config) SetBazelBuildFileTargets(bazelTargetsByDir map[string][]string) {
- c.bazelTargetsByDir = bazelTargetsByDir
-}
-
// ApiSurfaces directory returns the source path inside the api_surfaces repo
// (relative to workspace root).
func (c *config) ApiSurfacesDir(s ApiSurface, version string) string {
@@ -2106,12 +1951,6 @@
c.productVariables.Build_from_text_stub = boolPtr(b)
}
-func (c *config) AddForceEnabledModules(forceEnabled []string) {
- for _, forceEnabledModule := range forceEnabled {
- c.bazelForceEnabledModules[forceEnabledModule] = struct{}{}
- }
-}
-
func (c *config) SetApiLibraries(libs []string) {
c.apiLibraries = make(map[string]struct{})
for _, lib := range libs {
@@ -2123,11 +1962,6 @@
return c.apiLibraries
}
-// Bp2buildMode indicates whether the config is for bp2build mode of Soong
-func (c *config) Bp2buildMode() bool {
- return c.BuildMode == Bp2build
-}
-
func (c *deviceConfig) CheckVendorSeappViolations() bool {
return Bool(c.config.productVariables.CheckVendorSeappViolations)
}
diff --git a/android/metrics.go b/android/metrics.go
index 3571272..6834b1b 100644
--- a/android/metrics.go
+++ b/android/metrics.go
@@ -19,7 +19,6 @@
"io/ioutil"
"os"
"runtime"
- "sort"
"strconv"
"time"
@@ -93,23 +92,6 @@
}
metrics.Events = append(metrics.Events, &perfInfo)
}
- mixedBuildsInfo := soong_metrics_proto.MixedBuildsInfo{}
- mixedBuildEnabledModules := make([]string, 0, len(config.mixedBuildEnabledModules))
- for module, _ := range config.mixedBuildEnabledModules {
- mixedBuildEnabledModules = append(mixedBuildEnabledModules, module)
- }
-
- mixedBuildDisabledModules := make([]string, 0, len(config.mixedBuildDisabledModules))
- for module, _ := range config.mixedBuildDisabledModules {
- mixedBuildDisabledModules = append(mixedBuildDisabledModules, module)
- }
- // Sorted for deterministic output.
- sort.Strings(mixedBuildEnabledModules)
- sort.Strings(mixedBuildDisabledModules)
-
- mixedBuildsInfo.MixedBuildEnabledModules = mixedBuildEnabledModules
- mixedBuildsInfo.MixedBuildDisabledModules = mixedBuildDisabledModules
- metrics.MixedBuildsInfo = &mixedBuildsInfo
return metrics
}
diff --git a/android/module.go b/android/module.go
index 9d74642..f571157 100644
--- a/android/module.go
+++ b/android/module.go
@@ -16,7 +16,6 @@
import (
"android/soong/bazel"
- "android/soong/ui/metrics/bp2build_metrics_proto"
"crypto/md5"
"encoding/hex"
"encoding/json"
@@ -96,16 +95,6 @@
AddProperties(props ...interface{})
GetProperties() []interface{}
- // If this module should not have bazel BUILD definitions generated by bp2build,
- // GetUnconvertedReason returns a reason this is the case.
- GetUnconvertedReason() *UnconvertedReason
-
- // Bp2buildTargets returns the target(s) generated for Bazel via bp2build for this module
- Bp2buildTargets() []bp2buildInfo
- GetUnconvertedBp2buildDeps() []string
- GetMissingBp2buildDeps() []string
- GetPartitionForBp2build() string
-
BuildParamsForTests() []BuildParams
RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
VariablesForTests() map[string]string
@@ -520,9 +509,6 @@
// constants in image.go, but can also be set to a custom value by individual module types.
ImageVariation string `blueprint:"mutated"`
- // Bazel conversion status
- BazelConversionStatus BazelConversionStatus `blueprint:"mutated"`
-
// SoongConfigTrace records accesses to VendorVars (soong_config). The trace will be hashed
// and used as a subdir of PathForModuleOut. Note that we mainly focus on incremental
// builds among similar products (e.g. aosp_cf_x86_64_phone and aosp_cf_x86_64_foldable),
@@ -532,41 +518,6 @@
SoongConfigTraceHash string `blueprint:"mutated"`
}
-// CommonAttributes represents the common Bazel attributes from which properties
-// in `commonProperties` are translated/mapped; such properties are annotated in
-// a list their corresponding attribute. It is embedded within `bp2buildInfo`.
-type CommonAttributes struct {
- // Soong nameProperties -> Bazel name
- Name string
-
- // Data mapped from: Required
- Data bazel.LabelListAttribute
-
- // SkipData is neither a Soong nor Bazel target attribute
- // If true, this will not fill the data attribute automatically
- // This is useful for Soong modules that have 1:many Bazel targets
- // Some of the generated Bazel targets might not have a data attribute
- SkipData *bool
-
- Tags bazel.StringListAttribute
-
- Applicable_licenses bazel.LabelListAttribute
-
- Testonly *bool
-
- // Dir is neither a Soong nor Bazel target attribute
- // If set, the bazel target will be created in this directory
- // If unset, the bazel target will default to be created in the directory of the visited soong module
- Dir *string
-}
-
-// constraintAttributes represents Bazel attributes pertaining to build constraints,
-// which make restrict building a Bazel target for some set of platforms.
-type constraintAttributes struct {
- // Constraint values this target can be built for.
- Target_compatible_with bazel.LabelListAttribute
-}
-
type distProperties struct {
// configuration to distribute output files from this module to the distribution
// directory (default: $OUT/dist, configurable with $DIST_DIR)
@@ -804,234 +755,6 @@
m.base().commonProperties.CreateCommonOSVariant = true
}
-func (attrs *CommonAttributes) getRequiredWithoutCycles(ctx *bottomUpMutatorContext, props *commonProperties) []string {
- // Treat `required` as if it's empty if data should be skipped for this target,
- // as `required` is only used for the `data` attribute at this time, and we want
- // to avoid lookups of labels that won't actually be dependencies of this target.
- // TODO: b/202299295 - Refactor this to use `required` dependencies, once they
- // are handled other than passing to `data`.
- if proptools.Bool(attrs.SkipData) {
- return []string{}
- }
- // The required property can contain the module itself. This causes a cycle
- // when generated as the 'data' label list attribute in Bazel. Remove it if
- // it exists. See b/247985196.
- _, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), props.Required)
- return FirstUniqueStrings(requiredWithoutCycles)
-}
-
-func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *bottomUpMutatorContext,
- enabledPropertyOverrides bazel.BoolAttribute) constraintAttributes {
-
- mod := ctx.Module().base()
- // Assert passed-in attributes include Name
- if len(attrs.Name) == 0 {
- if ctx.ModuleType() != "package" {
- ctx.ModuleErrorf("CommonAttributes in fillCommonBp2BuildModuleAttrs expects a `.Name`!")
- }
- }
-
- depsToLabelList := func(deps []string) bazel.LabelListAttribute {
- return bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, deps))
- }
-
- var enabledProperty bazel.BoolAttribute
-
- onlyAndroid := false
- neitherHostNorDevice := false
-
- osSupport := map[string]bool{}
-
- // if the target is enabled and supports arch variance, determine the defaults based on the module
- // type's host or device property and host_supported/device_supported properties
- if mod.commonProperties.ArchSpecific {
- moduleSupportsDevice := mod.DeviceSupported()
- moduleSupportsHost := mod.HostSupported()
- if moduleSupportsHost && !moduleSupportsDevice {
- // for host only, we specify as unsupported on android rather than listing all host osSupport
- // TODO(b/220874839): consider replacing this with a constraint that covers all host osSupport
- // instead
- enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, Android.Name, proptools.BoolPtr(false))
- } else if moduleSupportsDevice && !moduleSupportsHost {
- enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, Android.Name, proptools.BoolPtr(true))
- // specify as a positive to ensure any target-specific enabled can be resolved
- // also save that a target is only android, as if there is only the positive restriction on
- // android, it'll be dropped, so we may need to add it back later
- onlyAndroid = true
- } else if !moduleSupportsHost && !moduleSupportsDevice {
- neitherHostNorDevice = true
- }
-
- for _, osType := range OsTypeList() {
- if osType.Class == Host {
- osSupport[osType.Name] = moduleSupportsHost
- } else if osType.Class == Device {
- osSupport[osType.Name] = moduleSupportsDevice
- }
- }
- }
-
- if neitherHostNorDevice {
- // we can't build this, disable
- enabledProperty.Value = proptools.BoolPtr(false)
- } else if mod.commonProperties.Enabled != nil {
- enabledProperty.SetValue(mod.commonProperties.Enabled)
- if !*mod.commonProperties.Enabled {
- for oss, enabled := range osSupport {
- if val := enabledProperty.SelectValue(bazel.OsConfigurationAxis, oss); enabled && val != nil && *val {
- // if this should be disabled by default, clear out any enabling we've done
- enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, oss, nil)
- }
- }
- }
- }
-
- attrs.Applicable_licenses = bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, mod.commonProperties.Licenses))
-
- requiredWithoutCycles := attrs.getRequiredWithoutCycles(ctx, &mod.commonProperties)
- required := depsToLabelList(requiredWithoutCycles)
- archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{})
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*commonProperties); ok {
- requiredWithoutCycles := attrs.getRequiredWithoutCycles(ctx, archProps)
- required.SetSelectValue(axis, config, depsToLabelList(requiredWithoutCycles).Value)
- if !neitherHostNorDevice {
- if archProps.Enabled != nil {
- if axis != bazel.OsConfigurationAxis || osSupport[config] {
- enabledProperty.SetSelectValue(axis, config, archProps.Enabled)
- }
- }
- }
- }
- }
- }
-
- if !neitherHostNorDevice {
- if enabledPropertyOverrides.Value != nil {
- enabledProperty.Value = enabledPropertyOverrides.Value
- }
- for _, axis := range enabledPropertyOverrides.SortedConfigurationAxes() {
- configToBools := enabledPropertyOverrides.ConfigurableValues[axis]
- for cfg, val := range configToBools {
- if axis != bazel.OsConfigurationAxis || osSupport[cfg] || val /*If enabled is explicitly requested via overrides */ {
- enabledProperty.SetSelectValue(axis, cfg, &val)
- }
- }
- }
- }
-
- productConfigEnabledAttribute := bazel.LabelListAttribute{}
- // TODO(b/234497586): Soong config variables and product variables have different overriding behavior, we
- // should handle it correctly
- if !proptools.BoolDefault(enabledProperty.Value, true) && !neitherHostNorDevice {
- // If the module is not enabled by default, then we can check if a
- // product variable enables it
- productConfigEnabledAttribute = productVariableConfigEnableAttribute(ctx)
-
- if len(productConfigEnabledAttribute.ConfigurableValues) > 0 {
- // In this case, an existing product variable configuration overrides any
- // module-level `enable: false` definition
- newValue := true
- enabledProperty.Value = &newValue
- }
- }
-
- platformEnabledAttribute, err := enabledProperty.ToLabelListAttribute(
- bazel.LabelList{[]bazel.Label{{Label: "@platforms//:incompatible"}}, nil},
- bazel.LabelList{[]bazel.Label{}, nil})
- if err != nil {
- ctx.ModuleErrorf("Error processing platform enabled attribute: %s", err)
- }
-
- // if android is the only arch/os enabled, then add a restriction to only be compatible with android
- if platformEnabledAttribute.IsNil() && onlyAndroid {
- l := bazel.LabelAttribute{}
- l.SetValue(bazel.Label{Label: bazel.OsConfigurationAxis.SelectKey(Android.Name)})
- platformEnabledAttribute.Add(&l)
- }
-
- attrs.Data.Append(required)
-
- // SkipData is not an attribute of any Bazel target
- // Set this to nil so that it does not appear in the generated build file
- attrs.SkipData = nil
-
- moduleEnableConstraints := bazel.LabelListAttribute{}
- moduleEnableConstraints.Append(platformEnabledAttribute)
- moduleEnableConstraints.Append(productConfigEnabledAttribute)
- addCompatibilityConstraintForCompileMultilib(ctx, &moduleEnableConstraints)
-
- return constraintAttributes{Target_compatible_with: moduleEnableConstraints}
-}
-
-var (
- incompatible = bazel.LabelList{[]bazel.Label{{Label: "@platforms//:incompatible"}}, nil}
-)
-
-// If compile_mulitilib is set to
-// 1. 32: Add an incompatibility constraint for non-32 arches
-// 1. 64: Add an incompatibility constraint for non-64 arches
-func addCompatibilityConstraintForCompileMultilib(ctx *bottomUpMutatorContext, enabled *bazel.LabelListAttribute) {
- mod := ctx.Module().base()
- multilib, _ := decodeMultilib(mod, mod.commonProperties.CompileOS, ctx.Config().IgnorePrefer32OnDevice())
-
- switch multilib {
- case "32":
- // Add an incompatibility constraint for all known 64-bit arches
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "arm64", incompatible)
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "x86_64", incompatible)
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "riscv64", incompatible)
- case "64":
- // Add an incompatibility constraint for all known 32-bit arches
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "arm", incompatible)
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "x86", incompatible)
- case "both":
- // Do nothing: "both" is trivially compatible with 32-bit and 64-bit
- // The top level rule (e.g. apex/partition) will be responsible for building this module in both variants via an
- // outgoing_transition.
- default: // e.g. first, common
- // TODO - b/299135307: Add bp2build support for these properties.
- }
-
-}
-
-// Check product variables for `enabled: true` flag override.
-// Returns a list of the constraint_value targets who enable this override.
-func productVariableConfigEnableAttribute(ctx *bottomUpMutatorContext) bazel.LabelListAttribute {
- result := bazel.LabelListAttribute{}
- productVariableProps, errs := ProductVariableProperties(ctx, ctx.Module())
- for _, err := range errs {
- ctx.ModuleErrorf("ProductVariableProperties error: %s", err)
- }
- if productConfigProps, exists := productVariableProps["Enabled"]; exists {
- for productConfigProp, prop := range productConfigProps {
- flag, ok := prop.(*bool)
- if !ok {
- ctx.ModuleErrorf("Could not convert product variable enabled property")
- }
-
- if flag == nil {
- // soong config var is not used to set `enabled`. nothing to do.
- continue
- } else if *flag {
- axis := productConfigProp.ConfigurationAxis()
- result.SetSelectValue(axis, bazel.ConditionsDefaultConfigKey, bazel.MakeLabelList([]bazel.Label{{Label: "@platforms//:incompatible"}}))
- result.SetSelectValue(axis, productConfigProp.SelectKey(), bazel.LabelList{Includes: []bazel.Label{}})
- } else if scp, isSoongConfigProperty := productConfigProp.(SoongConfigProperty); isSoongConfigProperty && scp.value == bazel.ConditionsDefaultConfigKey {
- // productVariableConfigEnableAttribute runs only if `enabled: false` is set at the top-level outside soong_config_variables
- // conditions_default { enabled: false} is a no-op in this case
- continue
- } else {
- // TODO(b/210546943): handle negative case where `enabled: false`
- ctx.ModuleErrorf("`enabled: false` is not currently supported for configuration variables. See b/210546943")
- }
- }
- }
-
- return result
-}
-
// A ModuleBase object contains the properties that are common to all Android
// modules. It should be included as an anonymous field in every module
// struct definition. InitAndroidModule should then be called from the module's
@@ -1146,81 +869,6 @@
licenseMetadataFile WritablePath
}
-// A struct containing all relevant information about a Bazel target converted via bp2build.
-type bp2buildInfo struct {
- Dir string
- BazelProps bazel.BazelTargetModuleProperties
- CommonAttrs CommonAttributes
- ConstraintAttrs constraintAttributes
- Attrs interface{}
-}
-
-// TargetName returns the Bazel target name of a bp2build converted target.
-func (b bp2buildInfo) TargetName() string {
- return b.CommonAttrs.Name
-}
-
-// TargetPackage returns the Bazel package of a bp2build converted target.
-func (b bp2buildInfo) TargetPackage() string {
- return b.Dir
-}
-
-// BazelRuleClass returns the Bazel rule class of a bp2build converted target.
-func (b bp2buildInfo) BazelRuleClass() string {
- return b.BazelProps.Rule_class
-}
-
-// BazelRuleLoadLocation returns the location of the Bazel rule of a bp2build converted target.
-// This may be empty as native Bazel rules do not need to be loaded.
-func (b bp2buildInfo) BazelRuleLoadLocation() string {
- return b.BazelProps.Bzl_load_location
-}
-
-// BazelAttributes returns the Bazel attributes of a bp2build converted target.
-func (b bp2buildInfo) BazelAttributes() []interface{} {
- return []interface{}{&b.CommonAttrs, &b.ConstraintAttrs, b.Attrs}
-}
-
-func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {
- m.commonProperties.BazelConversionStatus.Bp2buildInfo = append(m.commonProperties.BazelConversionStatus.Bp2buildInfo, info)
-}
-
-func (m *ModuleBase) setPartitionForBp2build(partition string) {
- m.commonProperties.BazelConversionStatus.Partition = partition
-}
-
-func (m *ModuleBase) setBp2buildUnconvertible(reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) {
- m.commonProperties.BazelConversionStatus.UnconvertedReason = &UnconvertedReason{
- ReasonType: int(reasonType),
- Detail: detail,
- }
-}
-
-func (m *ModuleBase) GetUnconvertedReason() *UnconvertedReason {
- return m.commonProperties.BazelConversionStatus.UnconvertedReason
-}
-
-// Bp2buildTargets returns the Bazel targets bp2build generated for this module.
-func (m *ModuleBase) Bp2buildTargets() []bp2buildInfo {
- return m.commonProperties.BazelConversionStatus.Bp2buildInfo
-}
-
-// Bp2buildTargets returns the Bazel targets bp2build generated for this module.
-func (m *ModuleBase) GetPartitionForBp2build() string {
- return m.commonProperties.BazelConversionStatus.Partition
-}
-
-// GetUnconvertedBp2buildDeps returns the list of module names of this module's direct dependencies that
-// were not converted to Bazel.
-func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
- return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.UnconvertedDeps)
-}
-
-// GetMissingBp2buildDeps returns the list of module names that were not found in Android.bp files.
-func (m *ModuleBase) GetMissingBp2buildDeps() []string {
- return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.MissingDeps)
-}
-
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
(*d)["Android"] = map[string]interface{}{
// Properties set in Blueprint or in blueprint of a defaults modules
@@ -2031,11 +1679,7 @@
return
}
- if mixedBuildMod, handled := m.isHandledByBazel(ctx); handled {
- mixedBuildMod.ProcessBazelQueryResponse(ctx)
- } else {
- m.module.GenerateAndroidBuildActions(ctx)
- }
+ m.module.GenerateAndroidBuildActions(ctx)
if ctx.Failed() {
return
}
@@ -2092,15 +1736,6 @@
m.variables = ctx.variables
}
-func (m *ModuleBase) isHandledByBazel(ctx ModuleContext) (MixedBuildBuildable, bool) {
- if mixedBuildMod, ok := m.module.(MixedBuildBuildable); ok {
- if mixedBuildMod.IsMixedBuildSupported(ctx) && (MixedBuildsEnabled(ctx) == MixedBuildEnabled) {
- return mixedBuildMod, true
- }
- }
- return nil, false
-}
-
// Check the supplied dist structure to make sure that it is valid.
//
// property - the base property, e.g. dist or dists[1], which is combined with the
@@ -2193,6 +1828,18 @@
return proptools.Bool(m.commonProperties.Native_bridge_supported)
}
+// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
+// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
+// or if this variant is not overridden.
+func ModuleNameWithPossibleOverride(ctx BaseModuleContext) string {
+ if overridable, ok := ctx.Module().(OverridableModule); ok {
+ if o := overridable.GetOverriddenBy(); o != "" {
+ return o
+ }
+ }
+ return ctx.ModuleName()
+}
+
// SrcIsModule decodes module references in the format ":unqualified-name" or "//namespace:name"
// into the module name, or empty string if the input was not a module reference.
func SrcIsModule(s string) (module string) {
@@ -2615,36 +2262,3 @@
WriteFileRule(ctx, outFile, string(j))
ctx.Phony("soong_config_trace", outFile)
}
-
-// Interface implemented by xsd_config which has 1:many mappings in bp2build workspace
-// This interface exists because we want to
-// 1. Determine the name of the additional targets generated by the primary soong module
-// 2. Enable distinguishing an xsd_config module from other Soong modules using type assertion
-type XsdConfigBp2buildTargets interface {
- CppBp2buildTargetName() string
- JavaBp2buildTargetName() string
-}
-
-// XsdModuleToTargetName is a function that takes an XsdConfigBp2buildTarget
-type XsdModuleToTargetName func(xsd XsdConfigBp2buildTargets) string
-
-// XsdLabelMapper returns a bazel.LabelMapper for partitioning XSD sources/headers given an
-// XsdModuleToTargetName function.
-func XsdLabelMapper(targetName XsdModuleToTargetName) bazel.LabelMapper {
- return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
- mod, exists := ctx.ModuleFromName(label.OriginalModuleName)
- if !exists {
- return label.Label, false
- }
- xsdMod, isXsd := mod.(XsdConfigBp2buildTargets)
- if !isXsd {
- return label.Label, false
- }
-
- // Remove the base module name
- ret := strings.TrimSuffix(label.Label, mod.Name())
- // Append the language specific target name
- ret += targetName(xsdMod)
- return ret, true
- }
-}
diff --git a/android/mutator.go b/android/mutator.go
index 3ff9e61..0d391a4 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,11 +15,6 @@
package android
import (
- "path/filepath"
-
- "android/soong/bazel"
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
"github.com/google/blueprint"
)
@@ -32,40 +27,9 @@
// run FinalDeps mutators (CreateVariations disallowed in this phase)
// continue on to GenerateAndroidBuildActions
-// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
- bp2buildMutators := append(preArchMutators, registerBp2buildConversionMutator)
- registerMutatorsForBazelConversion(ctx, bp2buildMutators)
-}
-
-func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []RegisterMutatorFunc) {
- mctx := ®isterMutatorsContext{
- bazelConversionMode: true,
- }
-
- allMutators := append([]RegisterMutatorFunc{
- RegisterNamespaceMutator,
- RegisterDefaultsPreArchMutators,
- // TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
- // evaluate the impact on conversion.
- RegisterPrebuiltsPreArchMutators,
- RegisterPrebuiltsPostDepsMutators,
- },
- bp2buildMutators...)
-
- // Register bp2build mutators
- for _, f := range allMutators {
- f(mctx)
- }
-
- mctx.mutators.registerAll(ctx)
-}
-
// 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)
}
@@ -94,9 +58,8 @@
}
type registerMutatorsContext struct {
- mutators sortableComponents
- finalPhase bool
- bazelConversionMode bool
+ mutators sortableComponents
+ finalPhase bool
}
type RegisterMutatorsContext interface {
@@ -219,58 +182,6 @@
finalDeps = append(finalDeps, f)
}
-var bp2buildPreArchMutators = []RegisterMutatorFunc{}
-
-// A minimal context for Bp2build conversion
-type Bp2buildMutatorContext interface {
- BazelConversionPathContext
- BaseMutatorContext
-
- // AddDependency adds a dependency to the given module. It returns a slice of modules for each
- // dependency (some entries may be nil).
- //
- // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
- // new dependencies have had the current mutator called on them. If the mutator is not
- // parallel this method does not affect the ordering of the current mutator pass, but will
- // be ordered correctly for all future mutator passes.
- AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module
-
- // CreateBazelTargetModule creates a BazelTargetModule by calling the
- // factory method, just like in CreateModule, but also requires
- // BazelTargetModuleProperties containing additional metadata for the
- // bp2build codegenerator.
- CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})
-
- // CreateBazelTargetModuleWithRestrictions creates a BazelTargetModule by calling the
- // factory method, just like in CreateModule, but also requires
- // BazelTargetModuleProperties containing additional metadata for the
- // bp2build codegenerator. The generated target is restricted to only be buildable for certain
- // platforms, as dictated by a given bool attribute: the target will not be buildable in
- // any platform for which this bool attribute is false.
- CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
-
- // MarkBp2buildUnconvertible registers the current module as "unconvertible to bp2build" for the
- // given reason.
- MarkBp2buildUnconvertible(reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string)
-
- // CreateBazelTargetAliasInDir creates an alias definition in `dir` directory.
- // This function can be used to create alias definitions in a directory that is different
- // from the directory of the visited Soong module.
- CreateBazelTargetAliasInDir(dir string, name string, actual bazel.Label)
-
- // CreateBazelConfigSetting creates a config_setting in <dir>/BUILD.bazel
- // build/bazel has several static config_setting(s) that are used in Bazel builds.
- // This function can be used to createa additional config_setting(s) based on the build graph
- // (e.g. a config_setting specific to an apex variant)
- CreateBazelConfigSetting(csa bazel.ConfigSettingAttributes, ca CommonAttributes, dir string)
-}
-
-// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
-// into Bazel BUILD targets that should run prior to deps and conversion.
-func PreArchBp2BuildMutators(f RegisterMutatorFunc) {
- bp2buildPreArchMutators = append(bp2buildPreArchMutators, f)
-}
-
type BaseMutatorContext interface {
BaseModuleContext
@@ -301,7 +212,15 @@
type BottomUpMutatorContext interface {
BaseMutatorContext
- Bp2buildMutatorContext
+
+ // AddDependency adds a dependency to the given module. It returns a slice of modules for each
+ // dependency (some entries may be nil).
+ //
+ // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
+ // new dependencies have had the current mutator called on them. If the mutator is not
+ // parallel this method does not affect the ordering of the current mutator pass, but will
+ // be ordered correctly for all future mutator passes.
+ AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module
// AddReverseDependency adds a dependency from the destination to the given module.
// Does not affect the ordering of the current mutator pass, but will be ordered
@@ -416,10 +335,9 @@
}
func bottomUpMutatorContextFactory(ctx blueprint.BottomUpMutatorContext, a Module,
- finalPhase, bazelConversionMode bool) BottomUpMutatorContext {
+ finalPhase bool) BottomUpMutatorContext {
moduleContext := a.base().baseModuleContextFactory(ctx)
- moduleContext.bazelConversionMode = bazelConversionMode
return &bottomUpMutatorContext{
bp: ctx,
@@ -430,10 +348,9 @@
func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle {
finalPhase := x.finalPhase
- bazelConversionMode := x.bazelConversionMode
f := func(ctx blueprint.BottomUpMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
- m(bottomUpMutatorContextFactory(ctx, a, finalPhase, bazelConversionMode))
+ m(bottomUpMutatorContextFactory(ctx, a, finalPhase))
}
}
mutator := &mutator{name: x.mutatorName(name), bottomUpMutator: f}
@@ -550,15 +467,13 @@
}
type androidTransitionMutator struct {
- finalPhase bool
- bazelConversionMode bool
- mutator TransitionMutator
+ finalPhase bool
+ mutator TransitionMutator
}
func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string {
if m, ok := ctx.Module().(Module); ok {
moduleContext := m.base().baseModuleContextFactory(ctx)
- moduleContext.bazelConversionMode = a.bazelConversionMode
return a.mutator.Split(&moduleContext)
} else {
return []string{""}
@@ -607,15 +522,14 @@
func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) {
if am, ok := ctx.Module().(Module); ok {
- a.mutator.Mutate(bottomUpMutatorContextFactory(ctx, am, a.finalPhase, a.bazelConversionMode), variation)
+ a.mutator.Mutate(bottomUpMutatorContextFactory(ctx, am, a.finalPhase), variation)
}
}
func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) {
atm := &androidTransitionMutator{
- finalPhase: x.finalPhase,
- bazelConversionMode: x.bazelConversionMode,
- mutator: m,
+ finalPhase: x.finalPhase,
+ mutator: m,
}
mutator := &mutator{
name: name,
@@ -624,9 +538,6 @@
}
func (x *registerMutatorsContext) mutatorName(name string) string {
- if x.bazelConversionMode {
- return name + "_bp2build"
- }
return name
}
@@ -634,7 +545,6 @@
f := func(ctx blueprint.TopDownMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
moduleContext := a.base().baseModuleContextFactory(ctx)
- moduleContext.bazelConversionMode = x.bazelConversionMode
actx := &topDownMutatorContext{
bp: ctx,
baseModuleContext: moduleContext,
@@ -698,179 +608,6 @@
ctx.BottomUp("deps", depsMutator).Parallel()
}
-func (t *bottomUpMutatorContext) CreateBazelTargetModule(
- bazelProps bazel.BazelTargetModuleProperties,
- commonAttrs CommonAttributes,
- attrs interface{}) {
- t.createBazelTargetModule(bazelProps, commonAttrs, attrs, bazel.BoolAttribute{})
-}
-
-func (t *bottomUpMutatorContext) CreateBazelTargetModuleWithRestrictions(
- bazelProps bazel.BazelTargetModuleProperties,
- commonAttrs CommonAttributes,
- attrs interface{},
- enabledProperty bazel.BoolAttribute) {
- t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
-}
-
-func (t *bottomUpMutatorContext) MarkBp2buildUnconvertible(
- reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) {
- mod := t.Module()
- mod.base().setBp2buildUnconvertible(reasonType, detail)
-}
-
-var (
- bazelAliasModuleProperties = bazel.BazelTargetModuleProperties{
- Rule_class: "alias",
- }
-)
-
-type bazelAliasAttributes struct {
- Actual *bazel.LabelAttribute
-}
-
-func (t *bottomUpMutatorContext) CreateBazelTargetAliasInDir(
- dir string,
- name string,
- actual bazel.Label) {
- mod := t.Module()
- attrs := &bazelAliasAttributes{
- Actual: bazel.MakeLabelAttribute(actual.Label),
- }
- info := bp2buildInfo{
- Dir: dir,
- BazelProps: bazelAliasModuleProperties,
- CommonAttrs: CommonAttributes{Name: name},
- ConstraintAttrs: constraintAttributes{},
- Attrs: attrs,
- }
- mod.base().addBp2buildInfo(info)
-}
-
-// Returns the directory in which the bazel target will be generated
-// If ca.Dir is not nil, use that
-// Otherwise default to the directory of the soong module
-func dirForBazelTargetGeneration(t *bottomUpMutatorContext, ca *CommonAttributes) string {
- dir := t.OtherModuleDir(t.Module())
- if ca.Dir != nil {
- dir = *ca.Dir
- // Restrict its use to dirs that contain an Android.bp file.
- // There are several places in bp2build where we use the existence of Android.bp/BUILD on the filesystem
- // to curate a compatible label for src files (e.g. headers for cc).
- // If we arbritrarily create BUILD files, then it might render those curated labels incompatible.
- if exists, _, _ := t.Config().fs.Exists(filepath.Join(dir, "Android.bp")); !exists {
- t.ModuleErrorf("Cannot use ca.Dir to create a BazelTarget in dir: %v since it does not contain an Android.bp file", dir)
- }
-
- // Set ca.Dir to nil so that it does not get emitted to the BUILD files
- ca.Dir = nil
- }
- return dir
-}
-
-func (t *bottomUpMutatorContext) CreateBazelConfigSetting(
- csa bazel.ConfigSettingAttributes,
- ca CommonAttributes,
- dir string) {
- mod := t.Module()
- info := bp2buildInfo{
- Dir: dir,
- BazelProps: bazel.BazelTargetModuleProperties{
- Rule_class: "config_setting",
- },
- CommonAttrs: ca,
- ConstraintAttrs: constraintAttributes{},
- Attrs: &csa,
- }
- mod.base().addBp2buildInfo(info)
-}
-
-// ApexAvailableTags converts the apex_available property value of an ApexModule
-// module and returns it as a list of keyed tags.
-func ApexAvailableTags(mod Module) bazel.StringListAttribute {
- attr := bazel.StringListAttribute{}
- // Transform specific attributes into tags.
- if am, ok := mod.(ApexModule); ok {
- // TODO(b/218841706): hidl_interface has the apex_available prop, but it's
- // defined directly as a prop and not via ApexModule, so this doesn't
- // pick those props up.
- apexAvailable := am.apexModuleBase().ApexAvailable()
- // If a user does not specify apex_available in Android.bp, then soong provides a default.
- // To avoid verbosity of BUILD files, remove this default from user-facing BUILD files.
- if len(am.apexModuleBase().ApexProperties.Apex_available) == 0 {
- apexAvailable = []string{}
- }
- attr.Value = ConvertApexAvailableToTags(apexAvailable)
- }
- return attr
-}
-
-func ApexAvailableTagsWithoutTestApexes(ctx BaseModuleContext, mod Module) bazel.StringListAttribute {
- attr := bazel.StringListAttribute{}
- if am, ok := mod.(ApexModule); ok {
- apexAvailableWithoutTestApexes := removeTestApexes(ctx, am.apexModuleBase().ApexAvailable())
- // If a user does not specify apex_available in Android.bp, then soong provides a default.
- // To avoid verbosity of BUILD files, remove this default from user-facing BUILD files.
- if len(am.apexModuleBase().ApexProperties.Apex_available) == 0 {
- apexAvailableWithoutTestApexes = []string{}
- }
- attr.Value = ConvertApexAvailableToTags(apexAvailableWithoutTestApexes)
- }
- return attr
-}
-
-func removeTestApexes(ctx BaseModuleContext, apex_available []string) []string {
- testApexes := []string{}
- for _, aa := range apex_available {
- // ignore the wildcards
- if InList(aa, AvailableToRecognziedWildcards) {
- continue
- }
- mod, _ := ctx.ModuleFromName(aa)
- if apex, ok := mod.(ApexTestInterface); ok && apex.IsTestApex() {
- testApexes = append(testApexes, aa)
- }
- }
- return RemoveListFromList(CopyOf(apex_available), testApexes)
-}
-
-func ConvertApexAvailableToTags(apexAvailable []string) []string {
- if len(apexAvailable) == 0 {
- // We need nil specifically to make bp2build not add the tags property at all,
- // instead of adding it with an empty list
- return nil
- }
- result := make([]string, 0, len(apexAvailable))
- for _, a := range apexAvailable {
- result = append(result, "apex_available="+a)
- }
- return result
-}
-
-// ConvertApexAvailableToTagsWithoutTestApexes converts a list of apex names to a list of bazel tags
-// This function drops any test apexes from the input.
-func ConvertApexAvailableToTagsWithoutTestApexes(ctx BaseModuleContext, apexAvailable []string) []string {
- noTestApexes := removeTestApexes(ctx, apexAvailable)
- return ConvertApexAvailableToTags(noTestApexes)
-}
-
-func (t *bottomUpMutatorContext) createBazelTargetModule(
- bazelProps bazel.BazelTargetModuleProperties,
- commonAttrs CommonAttributes,
- attrs interface{},
- enabledProperty bazel.BoolAttribute) {
- constraintAttributes := commonAttrs.fillCommonBp2BuildModuleAttrs(t, enabledProperty)
- mod := t.Module()
- info := bp2buildInfo{
- Dir: dirForBazelTargetGeneration(t, &commonAttrs),
- BazelProps: bazelProps,
- CommonAttrs: commonAttrs,
- ConstraintAttrs: constraintAttributes,
- Attrs: attrs,
- }
- mod.base().addBp2buildInfo(info)
-}
-
// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid
// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every
diff --git a/android/mutator_test.go b/android/mutator_test.go
index dbdfa33..21eebd2 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "reflect"
"strings"
"testing"
@@ -268,22 +267,3 @@
FixtureWithRootAndroidBp(`test {name: "foo"}`),
).RunTest(t)
}
-
-func TestConvertApexAvailableToTags(t *testing.T) {
- input := []string{
- "com.android.adbd",
- "//apex_available:platform",
- }
- actual := ConvertApexAvailableToTags(input)
- expected := []string{
- "apex_available=com.android.adbd",
- "apex_available=//apex_available:platform",
- }
- if !reflect.DeepEqual(actual, expected) {
- t.Errorf("Expected: %v, actual: %v", expected, actual)
- }
-
- if ConvertApexAvailableToTags(nil) != nil {
- t.Errorf("Expected providing nil to return nil")
- }
-}
diff --git a/android/override_module.go b/android/override_module.go
index 9e0de6f..1341f53 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -214,17 +214,6 @@
}
b.overridableModuleProperties.OverriddenBy = o.Name()
b.overridableModuleProperties.OverriddenByModuleDir = o.ModuleDir()
-
- if oBazelable, ok := o.base().module.(Bazelable); ok {
- if bBazelable, ok := m.(Bazelable); ok {
- oProps := oBazelable.bazelProps()
- bProps := bBazelable.bazelProps()
- bProps.Bazel_module.Bp2build_available = oProps.Bazel_module.Bp2build_available
- bProps.Bazel_module.Label = oProps.Bazel_module.Label
- } else {
- ctx.ModuleErrorf("Override type cannot be Bazelable if original module type is not Bazelable %v %v.", o.Name(), m.Name())
- }
- }
}
// GetOverriddenBy returns the name of the override module that has overridden this module.
@@ -348,31 +337,3 @@
}
}
}
-
-// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
-// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
-// or if this variant is not overridden.
-func ModuleNameWithPossibleOverride(ctx BazelConversionContext) string {
- return moduleNameWithPossibleOverride(ctx, ctx.Module(), ctx.OtherModuleName(ctx.Module()))
-}
-
-func moduleNameWithPossibleOverride(ctx shouldConvertModuleContext, module blueprint.Module, name string) string {
- if overridable, ok := module.(OverridableModule); ok {
- if o := overridable.GetOverriddenBy(); o != "" {
- return o
- }
- }
- return name
-}
-
-// moduleDirWithPossibleOverride returns the dir of the OverrideModule that overrides the current
-// variant of the given OverridableModule, or ctx.OtherModuleName() if the module is not an
-// OverridableModule or if the variant is not overridden.
-func moduleDirWithPossibleOverride(ctx shouldConvertModuleContext, module blueprint.Module, dir string) string {
- if overridable, ok := module.(OverridableModule); ok {
- if o := overridable.GetOverriddenByModuleDir(); o != "" {
- return o
- }
- }
- return dir
-}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 91c0aa1..a32a37d 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -461,10 +461,6 @@
// Propagate the provider received from `all_apex_contributions`
// to the source module
ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) {
- if ctx.Config().Bp2buildMode() {
- // This provider key is not applicable in bp2build
- return
- }
psi := ctx.OtherModuleProvider(am, PrebuiltSelectionInfoProvider).(PrebuiltSelectionInfoMap)
ctx.SetProvider(PrebuiltSelectionInfoProvider, psi)
})
@@ -570,55 +566,20 @@
// fall back to the existing source vs prebuilt selection.
// TODO: Drop the fallback mechanisms
- if !ctx.Config().Bp2buildMode() {
- if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
- return false
- }
+ if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
+ return false
+ }
- // Skip prebuilt modules under unexported namespaces so that we won't
- // end up shadowing non-prebuilt module when prebuilt module under same
- // name happens to have a `Prefer` property set to true.
- if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() {
- return false
- }
+ // Skip prebuilt modules under unexported namespaces so that we won't
+ // end up shadowing non-prebuilt module when prebuilt module under same
+ // name happens to have a `Prefer` property set to true.
+ if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() {
+ return false
}
// If source is not available or is disabled then always use the prebuilt.
if source == nil || !source.Enabled() {
- // If in bp2build mode, we need to check product variables & Soong config variables, which may
- // have overridden the "enabled" property but have not been merged into the property value as
- // they would in a non-bp2build mode invocation
- if ctx.Config().Bp2buildMode() && source != nil {
- productVariableProps, errs := ProductVariableProperties(ctx, source)
- if productConfigProps, exists := productVariableProps["Enabled"]; len(errs) == 0 && exists && len(productConfigProps) == 1 {
- var prop ProductConfigOrSoongConfigProperty
- var value bool
- for p, v := range productConfigProps {
- prop = p
- actual, ok := v.(*bool)
- if ok {
- value = proptools.Bool(actual)
- }
- }
- if scv, ok := prop.(SoongConfigProperty); ok {
- // If the product config var is enabled but the value of enabled is false still, the
- // prebuilt is preferred. Otherwise, check if the prebulit is explicitly preferred
- if ctx.Config().VendorConfig(scv.namespace).Bool(strings.ToLower(scv.name)) && !value {
- return true
- }
- } else {
- // TODO: b/300998219 - handle product vars
- // We don't handle product variables yet, so return based on the non-product specific
- // value of enabled
- return true
- }
- } else {
- // No "enabled" property override, return true since this module isn't enabled
- return true
- }
- } else {
- return true
- }
+ return true
}
// If the use_source_config_var property is set then it overrides the prefer property setting.
diff --git a/android/register.go b/android/register.go
index de31353..cd968cd 100644
--- a/android/register.go
+++ b/android/register.go
@@ -15,15 +15,9 @@
package android
import (
- "bufio"
"fmt"
- "path/filepath"
- "reflect"
- "regexp"
-
- "android/soong/shared"
-
"github.com/google/blueprint"
+ "reflect"
)
// A sortable component is one whose registration order affects the order in which it is executed
@@ -166,75 +160,6 @@
return ctx
}
-// Helper function to register the module types used in bp2build.
-func registerModuleTypes(ctx *Context) {
- for _, t := range moduleTypes {
- t.register(ctx)
- }
- // Required for SingletonModule types, even though we are not using them.
- for _, t := range singletons {
- t.register(ctx)
- }
-}
-
-// RegisterForBazelConversion registers an alternate shadow pipeline of
-// singletons, module types and mutators to register for converting Blueprint
-// files to semantically equivalent BUILD files.
-func (ctx *Context) RegisterForBazelConversion() {
- registerModuleTypes(ctx)
- RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators)
-}
-
-// RegisterExistingBazelTargets reads Bazel BUILD.bazel and BUILD files under
-// the workspace, and returns a map containing names of Bazel targets defined in
-// these BUILD files.
-// For example, maps "//foo/bar" to ["baz", "qux"] if `//foo/bar:{baz,qux}` exist.
-func (c *Context) RegisterExistingBazelTargets(topDir string, existingBazelFiles []string) error {
- result := map[string][]string{}
-
- // Search for instances of `name = "$NAME"` (with arbitrary spacing).
- targetNameRegex := regexp.MustCompile(`(?m)^\s*name\s*=\s*\"([^\"]+)\"`)
-
- parseBuildFile := func(path string) error {
- fullPath := shared.JoinPath(topDir, path)
- sourceDir := filepath.Dir(path)
-
- fileInfo, err := c.Config().fs.Stat(fullPath)
- if err != nil {
- return fmt.Errorf("Error accessing Bazel file '%s': %s", path, err)
- }
- if !fileInfo.IsDir() &&
- (fileInfo.Name() == "BUILD" || fileInfo.Name() == "BUILD.bazel") {
- f, err := c.Config().fs.Open(fullPath)
- if err != nil {
- return fmt.Errorf("Error reading Bazel file '%s': %s", path, err)
- }
- defer f.Close()
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Text()
- matches := targetNameRegex.FindAllStringSubmatch(line, -1)
- for _, match := range matches {
- result[sourceDir] = append(result[sourceDir], match[1])
- }
- }
- }
- return nil
- }
-
- for _, path := range existingBazelFiles {
- if !c.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) {
- continue
- }
- err := parseBuildFile(path)
- if err != nil {
- return err
- }
- }
- c.Config().SetBazelBuildFileTargets(result)
- return nil
-}
-
// Register the pipeline of singletons, module types, and mutators for
// generating build.ninja and other files for Kati, from Android.bp files.
func (ctx *Context) Register() {
@@ -260,8 +185,6 @@
func collateGloballyRegisteredSingletons() sortableComponents {
allSingletons := append(sortableComponents(nil), singletons...)
allSingletons = append(allSingletons,
- singleton{parallel: true, name: "bazeldeps", factory: BazelSingleton},
-
// Register phony just before makevars so it can write out its phony rules as Make rules
singleton{parallel: false, name: "phony", factory: phonySingletonFactory},
diff --git a/android/test_config.go b/android/test_config.go
index 2a59d92..9e1ac70 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -61,11 +61,7 @@
// passed to PathForSource or PathForModuleSrc.
TestAllowNonExistentPaths: true,
- BazelContext: noopBazelContext{},
- BuildMode: BazelProdMode,
- mixedBuildDisabledModules: make(map[string]struct{}),
- mixedBuildEnabledModules: make(map[string]struct{}),
- bazelForceEnabledModules: make(map[string]struct{}),
+ BuildMode: AnalysisNoBazel,
}
config.deviceConfig = &deviceConfig{
config: config,
diff --git a/android/testing.go b/android/testing.go
index c596468..fa4dffd 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -219,10 +219,6 @@
ctx.finalDeps = append(ctx.finalDeps, f)
}
-func (ctx *TestContext) RegisterBp2BuildConfig(config Bp2BuildConversionAllowlist) {
- ctx.config.Bp2buildPackageConfig = config
-}
-
// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
// into Bazel BUILD targets that should run prior to deps and conversion.
func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
@@ -449,12 +445,6 @@
ctx.singletonOrder = componentsToNames(singletons)
}
-// RegisterForBazelConversion prepares a test context for bp2build conversion.
-func (ctx *TestContext) RegisterForBazelConversion() {
- ctx.config.BuildMode = Bp2build
- RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch)
-}
-
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
// This function adapts the old style ParseFileList calls that are spread throughout the tests
// to the new style that takes a config.
diff --git a/android/util.go b/android/util.go
index f687bca..ae1c657 100644
--- a/android/util.go
+++ b/android/util.go
@@ -591,3 +591,9 @@
}
return "", false
}
+
+func AddToStringSet(set map[string]bool, items []string) {
+ for _, item := range items {
+ set[item] = true
+ }
+}
diff --git a/android/variable.go b/android/variable.go
index aecad3b..fa4cfc1 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -20,7 +20,6 @@
"runtime"
"strings"
- "android/soong/android/soongconfig"
"android/soong/bazel"
"github.com/google/blueprint/proptools"
@@ -746,44 +745,6 @@
// property, like ["-DDEFINES"] for cflags.
type ProductConfigProperties map[string]map[ProductConfigOrSoongConfigProperty]interface{}
-// ProductVariableProperties returns a ProductConfigProperties containing only the properties which
-// have been set for the given module.
-func ProductVariableProperties(ctx ArchVariantContext, module Module) (ProductConfigProperties, []error) {
- var errs []error
- moduleBase := module.base()
-
- productConfigProperties := ProductConfigProperties{}
-
- if moduleBase.variableProperties != nil {
- productVariablesProperty := proptools.FieldNameForProperty("product_variables")
- if moduleBase.ArchSpecific() {
- for /* axis */ _, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
- for config, props := range configToProps {
- variableValues := reflect.ValueOf(props).Elem().FieldByName(productVariablesProperty)
- productConfigProperties.AddProductConfigProperties(variableValues, config)
- }
- }
- } else {
- variableValues := reflect.ValueOf(moduleBase.variableProperties).Elem().FieldByName(productVariablesProperty)
- productConfigProperties.AddProductConfigProperties(variableValues, "")
- }
- }
-
- if m, ok := module.(Bazelable); ok && m.namespacedVariableProps() != nil {
- for namespace, namespacedVariableProps := range m.namespacedVariableProps() {
- for _, namespacedVariableProp := range namespacedVariableProps {
- variableValues := reflect.ValueOf(namespacedVariableProp).Elem().FieldByName(soongconfig.SoongConfigProperty)
- err := productConfigProperties.AddSoongConfigProperties(namespace, variableValues)
- if err != nil {
- errs = append(errs, err)
- }
- }
- }
- }
-
- return productConfigProperties, errs
-}
-
func (p *ProductConfigProperties) AddProductConfigProperty(
propertyName, productVariableName, arch string, propertyValue interface{}) {
@@ -833,10 +794,6 @@
}
}
-var (
- conditionsDefaultField string = proptools.FieldNameForProperty(bazel.ConditionsDefaultConfigKey)
-)
-
// maybeExtractConfigVarProp attempts to read this value as a config var struct
// wrapped by interfaces and ptrs. If it's not the right type, the second return
// value is false.