Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5f86249 authored by Liz Kammer's avatar Liz Kammer Committed by Gerrit Code Review
Browse files

Merge changes from topic "mixed-bp2build"

* changes:
  Support autoconverted modules in mixed builds
  Use handcrafted build targets in bp2build
parents 9f315dea bdc60997
Loading
Loading
Loading
Loading
+81 −7
Original line number Diff line number Diff line
@@ -14,19 +14,49 @@

package android

import "android/soong/bazel"
import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"

	"github.com/google/blueprint"
	"github.com/google/blueprint/proptools"
)

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.
	Bp2build_available bool
}

// Properties contains common module properties for Bazel migration purposes.
type properties struct {
	// In USE_BAZEL_ANALYSIS=1 mode, this represents the Bazel target replacing
	// this Soong module.
	Bazel_module bazelModuleProperties
}

// BazelModuleBase contains the property structs with metadata for modules which can be converted to
// Bazel.
type BazelModuleBase struct {
	bazelProperties bazel.Properties
	bazelProperties properties
}

// Bazelable is specifies the interface for modules that can be converted to Bazel.
type Bazelable interface {
	bazelProps() *bazel.Properties
	GetBazelLabel() string
	bazelProps() *properties
	HasHandcraftedLabel() bool
	HandcraftedLabel() string
	GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
	ConvertWithBp2build() bool
	GetBazelBuildFileContents(c Config, path, name string) (string, error)
	ConvertedToBazel() bool
}

// BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules.
@@ -42,16 +72,60 @@ func InitBazelModule(module BazelModule) {
}

// bazelProps returns the Bazel properties for the given BazelModuleBase.
func (b *BazelModuleBase) bazelProps() *bazel.Properties {
func (b *BazelModuleBase) bazelProps() *properties {
	return &b.bazelProperties
}

// 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() string {
	return b.bazelProperties.Bazel_module.Label
func (b *BazelModuleBase) GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
	if b.HasHandcraftedLabel() {
		return b.HandcraftedLabel()
	}
	if b.ConvertWithBp2build() {
		return bp2buildModuleLabel(ctx, module)
	}
	return "" // no label for unconverted module
}

// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
func (b *BazelModuleBase) ConvertWithBp2build() bool {
	return b.bazelProperties.Bazel_module.Bp2build_available
}

// GetBazelBuildFileContents returns the file contents of a hand-crafted BUILD file if available or
// an error if there are errors reading the file.
// TODO(b/181575318): currently we append the whole BUILD file, let's change that to do
// something more targeted based on the rule type and target.
func (b *BazelModuleBase) GetBazelBuildFileContents(c Config, path, name string) (string, error) {
	if !strings.Contains(b.HandcraftedLabel(), path) {
		return "", fmt.Errorf("%q not found in bazel_module.label %q", path, b.HandcraftedLabel())
	}
	name = filepath.Join(path, name)
	f, err := c.fs.Open(name)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data, err := ioutil.ReadAll(f)
	if err != nil {
		return "", err
	}
	return string(data[:]), nil
}

// ConvertedToBazel returns whether this module has been converted to Bazel, whether automatically
// or manually
func (b *BazelModuleBase) ConvertedToBazel() bool {
	return b.ConvertWithBp2build() || b.HasHandcraftedLabel()
}
+38 −7
Original line number Diff line number Diff line
@@ -339,6 +339,7 @@ type BazelConversionPathContext interface {
	EarlyModulePathContext

	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
	Module() Module
	OtherModuleName(m blueprint.Module) string
	OtherModuleDir(m blueprint.Module) string
}
@@ -434,15 +435,45 @@ func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes
// already be resolved by either deps mutator or path deps mutator.
func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string) bazel.Label {
	m, _ := ctx.GetDirectDep(dep)
	otherLabel := bazelModuleLabel(ctx, m, tag)
	label := bazelModuleLabel(ctx, ctx.Module(), "")
	if samePackage(label, otherLabel) {
		otherLabel = bazelShortLabel(otherLabel)
	}

	return bazel.Label{
		Label: otherLabel,
	}
}

func bazelModuleLabel(ctx BazelConversionPathContext, module blueprint.Module, tag string) string {
	// TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
	otherModuleName := ctx.OtherModuleName(m)
	var label bazel.Label
	if otherDir, dir := ctx.OtherModuleDir(m), ctx.ModuleDir(); otherDir != dir {
		label.Label = fmt.Sprintf("//%s:%s", otherDir, otherModuleName)
	} else {
		label.Label = fmt.Sprintf(":%s", otherModuleName)
	b, ok := module.(Bazelable)
	// TODO(b/181155349): perhaps return an error here if the module can't be/isn't being converted
	if !ok || !b.ConvertedToBazel() {
		return bp2buildModuleLabel(ctx, module)
	}
	return b.GetBazelLabel(ctx, module)
}
	return label

func bazelShortLabel(label string) string {
	i := strings.Index(label, ":")
	return label[i:]
}

func bazelPackage(label string) string {
	i := strings.Index(label, ":")
	return label[0:i]
}

func samePackage(label1, label2 string) bool {
	return bazelPackage(label1) == bazelPackage(label2)
}

func bp2buildModuleLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
	moduleName := ctx.OtherModuleName(module)
	moduleDir := ctx.OtherModuleDir(module)
	return fmt.Sprintf("//%s:%s", moduleDir, moduleName)
}

// OutputPaths is a slice of OutputPath objects, with helpers to operate on the collection.
+0 −15
Original line number Diff line number Diff line
@@ -19,21 +19,6 @@ import (
	"sort"
)

type bazelModuleProperties struct {
	// The label of the Bazel target replacing this Soong module.
	Label string

	// If true, bp2build will generate the converted Bazel target for this module.
	Bp2build_available bool
}

// Properties contains common module properties for Bazel migration purposes.
type Properties struct {
	// In USE_BAZEL_ANALYSIS=1 mode, this represents the Bazel target replacing
	// this Soong module.
	Bazel_module bazelModuleProperties
}

// BazelTargetModuleProperties contain properties and metadata used for
// Blueprint to BUILD file conversion.
type BazelTargetModuleProperties struct {
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ bootstrap_go_package {
        "build_conversion.go",
        "bzl_conversion.go",
        "configurability.go",
        "constants.go",
        "conversion.go",
        "metrics.go",
    ],
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ import (

// The Bazel bp2build code generator is responsible for writing .bzl files that are equivalent to
// Android.bp files that are capable of being built with Bazel.
func Codegen(ctx CodegenContext) CodegenMetrics {
func Codegen(ctx *CodegenContext) CodegenMetrics {
	outputDir := android.PathForOutput(ctx, "bp2build")
	android.RemoveAllOutputDir(outputDir)

Loading