summaryrefslogtreecommitdiff
path: root/android/bazel.go
diff options
context:
space:
mode:
Diffstat (limited to 'android/bazel.go')
-rw-r--r--android/bazel.go545
1 files changed, 0 insertions, 545 deletions
diff --git a/android/bazel.go b/android/bazel.go
deleted file mode 100644
index 164688396..000000000
--- a/android/bazel.go
+++ /dev/null
@@ -1,545 +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"
- "strings"
-
- "github.com/google/blueprint"
- "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 = "."
-)
-
-// 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"`
-}
-
-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 BazelConversionContext) bool
- shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool
- ConvertWithBp2build(ctx TopDownMutatorContext)
-
- // 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
-}
-
-// 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)
- }
- return "" // no label for unconverted module
-}
-
-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 true if 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) bool {
- module := ctx.Module()
- apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo)
- withinApex := !apexInfo.IsForPlatform()
- mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() &&
- ctx.Os() != Windows && // Windows toolchains are not currently supported.
- ctx.Os() != LinuxBionic && // Linux Bionic toolchains are not currently supported.
- ctx.Os() != LinuxMusl && // Linux musl toolchains are not currently supported (b/259266326).
- ctx.Arch().ArchType != Riscv64 && // TODO(b/262192655) Riscv64 toolchains are not currently supported.
- module.Enabled() &&
- convertedToBazel(ctx, module) &&
- ctx.Config().BazelContext.IsModuleNameAllowed(module.Name(), withinApex)
- ctx.Config().LogMixedBuild(ctx, mixedBuildEnabled)
- return mixedBuildEnabled
-}
-
-// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
-func convertedToBazel(ctx BazelConversionContext, module blueprint.Module) bool {
- b, ok := module.(Bazelable)
- if !ok {
- return false
- }
- return b.shouldConvertWithBp2build(ctx, module) || b.HasHandcraftedLabel()
-}
-
-// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build
-func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx BazelConversionContext) bool {
- return b.shouldConvertWithBp2build(ctx, ctx.Module())
-}
-
-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 (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool {
- if !b.bazelProps().Bazel_module.CanConvertToBazel {
- return false
- }
-
- // In api_bp2build mode, all soong modules that can provide API contributions should be converted
- // This is irrespective of its presence/absence in bp2build allowlists
- if ctx.Config().BuildMode == ApiBp2build {
- _, providesApis := module.(ApiProvider)
- return providesApis
- }
-
- propValue := b.bazelProperties.Bazel_module.Bp2build_available
- packagePath := ctx.OtherModuleDir(module)
-
- // 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 := module.Name()
- allowlist := ctx.Config().Bp2buildPackageConfig
- moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName]
- moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[ctx.OtherModuleType(module)]
- allowlistConvert := moduleNameAllowed || moduleTypeAllowed
- if moduleNameAllowed && moduleTypeAllowed {
- ctx.ModuleErrorf("A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert")
- return false
- }
-
- if allowlist.moduleDoNotConvert[moduleName] {
- if moduleNameAllowed {
- ctx.ModuleErrorf("a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert")
- }
- 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.TopDown("bp2build_conversion", convertWithBp2build).Parallel()
-}
-
-func convertWithBp2build(ctx TopDownMutatorContext) {
- bModule, ok := ctx.Module().(Bazelable)
- if !ok || !bModule.shouldConvertWithBp2build(ctx, ctx.Module()) {
- return
- }
-
- bModule.ConvertWithBp2build(ctx)
-}
-
-func registerApiBp2buildConversionMutator(ctx RegisterMutatorsContext) {
- ctx.TopDown("apiBp2build_conversion", convertWithApiBp2build).Parallel()
-}
-
-// Generate API contribution targets if the Soong module provides APIs
-func convertWithApiBp2build(ctx TopDownMutatorContext) {
- if m, ok := ctx.Module().(ApiProvider); ok {
- m.ConvertWithApiBp2build(ctx)
- }
-}
-
-// 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
-}