123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628 |
- // 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/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 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 BazelConversionContext) bool
- shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) 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 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)
- }
- panic(fmt.Errorf("requested non-existent label for module ", 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
- }
- // 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 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.
- }
- 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 := moduleDirWithPossibleOverride(ctx, 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 := moduleNameWithPossibleOverride(ctx, module)
- 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", bp2buildConversionMutator).Parallel()
- }
- func bp2buildConversionMutator(ctx TopDownMutatorContext) {
- if ctx.Config().HasBazelBuildTargetInSource(ctx) {
- // 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
- }
- bModule, ok := ctx.Module().(Bazelable)
- if !ok {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
- return
- }
- // TODO: b/285631638 - Differentiate between denylisted modules and missing bp2build capabilities.
- if !bModule.shouldConvertWithBp2build(ctx, ctx.Module()) {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "")
- return
- }
- bModule.ConvertWithBp2build(ctx)
- if !ctx.Module().base().IsConvertedByBp2build() && ctx.Module().base().GetUnconvertedReason() == nil {
- panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName()))
- }
- }
- 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
- }
|