Create a new mode in soong_ui to generate API only BUILD files
The generated Bazel workspace will only contain api specific targets. This is feasible since these targets do not have any cross dependencies with the targets in the bp2build workspace The advantages of a new mode are 1. Does not pollute bp2build workspace with api targets 2. Does not block api targets with the current allowlist conversion mechansims in bp2build (In the future we might want to combine these two workspaces) A Soong module type will generate a Bazel target if it implements ApiProvider interface Test: m apigen Test: m nothing Change-Id: I69c57ca6539f932e0ad554ce84a87fb7936fdba0
This commit is contained in:
@@ -134,6 +134,11 @@ type Bazelable interface {
|
||||
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 {
|
||||
@@ -415,6 +420,13 @@ func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext,
|
||||
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)
|
||||
|
||||
@@ -510,6 +522,17 @@ func convertWithBp2build(ctx TopDownMutatorContext) {
|
||||
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.
|
||||
|
@@ -83,6 +83,9 @@ const (
|
||||
// express build semantics.
|
||||
GenerateQueryView
|
||||
|
||||
// Generate BUILD files for API contributions to API surfaces
|
||||
ApiBp2build
|
||||
|
||||
// Create a JSON representation of the module graph and exit.
|
||||
GenerateModuleGraph
|
||||
|
||||
|
@@ -31,22 +31,33 @@ import (
|
||||
|
||||
// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
|
||||
func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
|
||||
bp2buildMutators := append(preArchMutators, registerBp2buildConversionMutator)
|
||||
registerMutatorsForBazelConversion(ctx, bp2buildMutators)
|
||||
}
|
||||
|
||||
// RegisterMutatorsForApiBazelConversion is an alternate registration pipeline for api_bp2build
|
||||
// This pipeline restricts generation of Bazel targets to Soong modules that contribute APIs
|
||||
func RegisterMutatorsForApiBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
|
||||
bp2buildMutators := append(preArchMutators, registerApiBp2buildConversionMutator)
|
||||
registerMutatorsForBazelConversion(ctx, bp2buildMutators)
|
||||
}
|
||||
|
||||
func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []RegisterMutatorFunc) {
|
||||
mctx := ®isterMutatorsContext{
|
||||
bazelConversionMode: true,
|
||||
}
|
||||
|
||||
bp2buildMutators := append([]RegisterMutatorFunc{
|
||||
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,
|
||||
},
|
||||
preArchMutators...)
|
||||
bp2buildMutators = append(bp2buildMutators, registerBp2buildConversionMutator)
|
||||
bp2buildMutators...)
|
||||
|
||||
// Register bp2build mutators
|
||||
for _, f := range bp2buildMutators {
|
||||
for _, f := range allMutators {
|
||||
f(mctx)
|
||||
}
|
||||
|
||||
|
@@ -180,6 +180,16 @@ func (ctx *Context) RegisterForBazelConversion() {
|
||||
RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators)
|
||||
}
|
||||
|
||||
// RegisterForApiBazelConversion is similar to RegisterForBazelConversion except that
|
||||
// it only generates API targets in the generated workspace
|
||||
func (ctx *Context) RegisterForApiBazelConversion() {
|
||||
for _, t := range moduleTypes {
|
||||
t.register(ctx)
|
||||
}
|
||||
|
||||
RegisterMutatorsForApiBazelConversion(ctx, bp2buildPreArchMutators)
|
||||
}
|
||||
|
||||
// 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() {
|
||||
|
@@ -461,6 +461,12 @@ func (ctx *TestContext) RegisterForBazelConversion() {
|
||||
RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch)
|
||||
}
|
||||
|
||||
// RegisterForApiBazelConversion prepares a test context for API bp2build conversion.
|
||||
func (ctx *TestContext) RegisterForApiBazelConversion() {
|
||||
ctx.config.BuildMode = ApiBp2build
|
||||
RegisterMutatorsForApiBazelConversion(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.
|
||||
|
@@ -163,6 +163,9 @@ const (
|
||||
// This mode is used for discovering and introspecting the existing Soong
|
||||
// module graph.
|
||||
QueryView
|
||||
|
||||
// ApiBp2build - generate BUILD files for API contribution targets
|
||||
ApiBp2build
|
||||
)
|
||||
|
||||
type unconvertedDepsMode int
|
||||
@@ -181,6 +184,8 @@ func (mode CodegenMode) String() string {
|
||||
return "Bp2Build"
|
||||
case QueryView:
|
||||
return "QueryView"
|
||||
case ApiBp2build:
|
||||
return "ApiBp2build"
|
||||
default:
|
||||
return fmt.Sprintf("%d", mode)
|
||||
}
|
||||
@@ -327,6 +332,10 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers
|
||||
errs = append(errs, err)
|
||||
}
|
||||
targets = append(targets, t)
|
||||
case ApiBp2build:
|
||||
if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
|
||||
targets, errs = generateBazelTargets(bpCtx, aModule)
|
||||
}
|
||||
default:
|
||||
errs = append(errs, fmt.Errorf("Unknown code-generation mode: %s", ctx.Mode()))
|
||||
return
|
||||
|
@@ -1848,3 +1848,27 @@ filegroup {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenerateApiBazelTargets(t *testing.T) {
|
||||
bp := `
|
||||
custom {
|
||||
name: "foo",
|
||||
api: "foo.txt",
|
||||
}
|
||||
`
|
||||
expectedBazelTarget := MakeBazelTarget(
|
||||
"custom_api_contribution",
|
||||
"foo",
|
||||
AttrNameToString{
|
||||
"api": `"foo.txt"`,
|
||||
},
|
||||
)
|
||||
registerCustomModule := func(ctx android.RegistrationContext) {
|
||||
ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
|
||||
}
|
||||
RunApiBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
|
||||
Blueprint: bp,
|
||||
ExpectedBazelTargets: []string{expectedBazelTarget},
|
||||
Description: "Generating API contribution Bazel targets for custom module",
|
||||
})
|
||||
}
|
||||
|
@@ -85,6 +85,7 @@ custom = rule(
|
||||
"soong_module_name": attr.string(mandatory = True),
|
||||
"soong_module_variant": attr.string(),
|
||||
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
||||
"api": attr.string(),
|
||||
"arch_paths": attr.string_list(),
|
||||
"arch_paths_exclude": attr.string_list(),
|
||||
# bazel_module start
|
||||
@@ -119,6 +120,7 @@ custom_defaults = rule(
|
||||
"soong_module_name": attr.string(mandatory = True),
|
||||
"soong_module_variant": attr.string(),
|
||||
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
||||
"api": attr.string(),
|
||||
"arch_paths": attr.string_list(),
|
||||
"arch_paths_exclude": attr.string_list(),
|
||||
"bool_prop": attr.bool(),
|
||||
@@ -149,6 +151,7 @@ custom_test_ = rule(
|
||||
"soong_module_name": attr.string(mandatory = True),
|
||||
"soong_module_variant": attr.string(),
|
||||
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
|
||||
"api": attr.string(),
|
||||
"arch_paths": attr.string_list(),
|
||||
"arch_paths_exclude": attr.string_list(),
|
||||
"bool_prop": attr.bool(),
|
||||
|
@@ -97,7 +97,7 @@ func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode)
|
||||
targets.sort()
|
||||
|
||||
var content string
|
||||
if mode == Bp2Build {
|
||||
if mode == Bp2Build || mode == ApiBp2build {
|
||||
content = `# READ THIS FIRST:
|
||||
# This file was automatically generated by bp2build for the Bazel migration project.
|
||||
# Feel free to edit or test it, but do *not* check it into your version control system.
|
||||
|
@@ -24,6 +24,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/android/allowlists"
|
||||
"android/soong/bazel"
|
||||
@@ -88,6 +90,22 @@ type Bp2buildTestCase struct {
|
||||
}
|
||||
|
||||
func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
|
||||
bp2buildSetup := func(ctx *android.TestContext) {
|
||||
registerModuleTypes(ctx)
|
||||
ctx.RegisterForBazelConversion()
|
||||
}
|
||||
runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
|
||||
}
|
||||
|
||||
func RunApiBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
|
||||
apiBp2BuildSetup := func(ctx *android.TestContext) {
|
||||
registerModuleTypes(ctx)
|
||||
ctx.RegisterForApiBazelConversion()
|
||||
}
|
||||
runBp2BuildTestCaseWithSetup(t, apiBp2BuildSetup, tc)
|
||||
}
|
||||
|
||||
func runBp2BuildTestCaseWithSetup(t *testing.T, setup func(ctx *android.TestContext), tc Bp2buildTestCase) {
|
||||
t.Helper()
|
||||
dir := "."
|
||||
filesystem := make(map[string][]byte)
|
||||
@@ -103,7 +121,7 @@ func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.Regi
|
||||
config := android.TestConfig(buildDir, nil, tc.Blueprint, filesystem)
|
||||
ctx := android.NewTestContext(config)
|
||||
|
||||
registerModuleTypes(ctx)
|
||||
setup(ctx)
|
||||
ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory)
|
||||
|
||||
// A default configuration for tests to not have to specify bp2build_available on top level targets.
|
||||
@@ -118,7 +136,6 @@ func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.Regi
|
||||
})
|
||||
}
|
||||
ctx.RegisterBp2BuildConfig(bp2buildConfig)
|
||||
ctx.RegisterForBazelConversion()
|
||||
|
||||
_, parseErrs := ctx.ParseFileList(dir, toParse)
|
||||
if errored(t, tc, parseErrs) {
|
||||
@@ -198,6 +215,8 @@ type customProps struct {
|
||||
|
||||
// Prop used to indicate this conversion should be 1 module -> multiple targets
|
||||
One_to_many_prop *bool
|
||||
|
||||
Api *string // File describing the APIs of this module
|
||||
}
|
||||
|
||||
type customModule struct {
|
||||
@@ -320,6 +339,7 @@ type customBazelModuleAttributes struct {
|
||||
String_ptr_prop *string
|
||||
String_list_prop []string
|
||||
Arch_paths bazel.LabelListAttribute
|
||||
Api bazel.LabelAttribute
|
||||
}
|
||||
|
||||
func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
|
||||
@@ -364,6 +384,23 @@ func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
|
||||
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
|
||||
}
|
||||
|
||||
var _ android.ApiProvider = (*customModule)(nil)
|
||||
|
||||
func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
|
||||
props := bazel.BazelTargetModuleProperties{
|
||||
Rule_class: "custom_api_contribution",
|
||||
}
|
||||
apiAttribute := bazel.MakeLabelAttribute(
|
||||
android.BazelLabelForModuleSrcSingle(ctx, proptools.String(c.props.Api)).Label,
|
||||
)
|
||||
attrs := &customBazelModuleAttributes{
|
||||
Api: *apiAttribute,
|
||||
}
|
||||
ctx.CreateBazelTargetModule(props,
|
||||
android.CommonAttributes{Name: c.Name()},
|
||||
attrs)
|
||||
}
|
||||
|
||||
// A bp2build mutator that uses load statements and creates a 1:M mapping from
|
||||
// module to target.
|
||||
func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
|
||||
|
@@ -24,6 +24,7 @@ import (
|
||||
"time"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/bazel"
|
||||
"android/soong/bp2build"
|
||||
"android/soong/shared"
|
||||
"android/soong/ui/metrics/bp2build_metrics_proto"
|
||||
@@ -48,11 +49,12 @@ var (
|
||||
delveListen string
|
||||
delvePath string
|
||||
|
||||
moduleGraphFile string
|
||||
moduleActionsFile string
|
||||
docFile string
|
||||
bazelQueryViewDir string
|
||||
bp2buildMarker string
|
||||
moduleGraphFile string
|
||||
moduleActionsFile string
|
||||
docFile string
|
||||
bazelQueryViewDir string
|
||||
bazelApiBp2buildDir string
|
||||
bp2buildMarker string
|
||||
|
||||
cmdlineArgs bootstrap.Args
|
||||
)
|
||||
@@ -81,6 +83,7 @@ func init() {
|
||||
flag.StringVar(&moduleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
|
||||
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
|
||||
flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
|
||||
flag.StringVar(&bazelApiBp2buildDir, "bazel_api_bp2build_dir", "", "path to the bazel api_bp2build directory relative to --top")
|
||||
flag.StringVar(&bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
|
||||
flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
|
||||
flag.BoolVar(&cmdlineArgs.EmptyNinjaFile, "empty-ninja-file", false, "write out a 0-byte ninja file")
|
||||
@@ -129,6 +132,8 @@ func newConfig(availableEnv map[string]string) android.Config {
|
||||
buildMode = android.Bp2build
|
||||
} else if bazelQueryViewDir != "" {
|
||||
buildMode = android.GenerateQueryView
|
||||
} else if bazelApiBp2buildDir != "" {
|
||||
buildMode = android.ApiBp2build
|
||||
} else if moduleGraphFile != "" {
|
||||
buildMode = android.GenerateModuleGraph
|
||||
} else if docFile != "" {
|
||||
@@ -178,7 +183,7 @@ func runQueryView(queryviewDir, queryviewMarker string, configuration android.Co
|
||||
defer ctx.EventHandler.End("queryview")
|
||||
codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
|
||||
absoluteQueryViewDir := shared.JoinPath(topDir, queryviewDir)
|
||||
if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
|
||||
if err := createBazelWorkspace(codegenContext, absoluteQueryViewDir); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -186,6 +191,96 @@ func runQueryView(queryviewDir, queryviewMarker string, configuration android.Co
|
||||
touch(shared.JoinPath(topDir, queryviewMarker))
|
||||
}
|
||||
|
||||
// Run the code-generation phase to convert API contributions to BUILD files.
|
||||
// Return marker file for the new synthetic workspace
|
||||
func runApiBp2build(configuration android.Config, extraNinjaDeps []string) string {
|
||||
// Create a new context and register mutators that are only meaningful to API export
|
||||
ctx := android.NewContext(configuration)
|
||||
ctx.EventHandler.Begin("api_bp2build")
|
||||
defer ctx.EventHandler.End("api_bp2build")
|
||||
ctx.SetNameInterface(newNameResolver(configuration))
|
||||
ctx.RegisterForApiBazelConversion()
|
||||
|
||||
// Register the Android.bp files in the tree
|
||||
// Add them to the workspace's .d file
|
||||
ctx.SetModuleListFile(cmdlineArgs.ModuleListFile)
|
||||
if paths, err := ctx.ListModulePaths("."); err == nil {
|
||||
extraNinjaDeps = append(extraNinjaDeps, paths...)
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Run the loading and analysis phase
|
||||
ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs,
|
||||
bootstrap.StopBeforePrepareBuildActions,
|
||||
ctx.Context,
|
||||
configuration)
|
||||
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
|
||||
|
||||
// Add the globbed dependencies
|
||||
globs := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
|
||||
ninjaDeps = append(ninjaDeps, globs...)
|
||||
|
||||
// Run codegen to generate BUILD files
|
||||
codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.ApiBp2build)
|
||||
absoluteApiBp2buildDir := shared.JoinPath(topDir, bazelApiBp2buildDir)
|
||||
if err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
|
||||
|
||||
// Create soong_injection repository
|
||||
soongInjectionFiles := bp2build.CreateSoongInjectionFiles(configuration, bp2build.CodegenMetrics{})
|
||||
absoluteSoongInjectionDir := shared.JoinPath(topDir, configuration.SoongOutDir(), bazel.SoongInjectionDirName)
|
||||
for _, file := range soongInjectionFiles {
|
||||
writeReadOnlyFile(absoluteSoongInjectionDir, file)
|
||||
}
|
||||
|
||||
workspace := shared.JoinPath(configuration.SoongOutDir(), "api_bp2build")
|
||||
|
||||
excludes := bazelArtifacts()
|
||||
// Exclude all src BUILD files
|
||||
excludes = append(excludes, apiBuildFileExcludes()...)
|
||||
|
||||
// Create the symlink forest
|
||||
symlinkDeps := bp2build.PlantSymlinkForest(
|
||||
configuration,
|
||||
topDir,
|
||||
workspace,
|
||||
bazelApiBp2buildDir,
|
||||
".",
|
||||
excludes)
|
||||
ninjaDeps = append(ninjaDeps, symlinkDeps...)
|
||||
|
||||
workspaceMarkerFile := workspace + ".marker"
|
||||
writeDepFile(workspaceMarkerFile, *ctx.EventHandler, ninjaDeps)
|
||||
touch(shared.JoinPath(topDir, workspaceMarkerFile))
|
||||
return workspaceMarkerFile
|
||||
}
|
||||
|
||||
// With some exceptions, api_bp2build does not have any dependencies on the checked-in BUILD files
|
||||
// Exclude them from the generated workspace to prevent unrelated errors during the loading phase
|
||||
func apiBuildFileExcludes() []string {
|
||||
ret := make([]string, 0)
|
||||
|
||||
srcs, err := getExistingBazelRelatedFiles(topDir)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
for _, src := range srcs {
|
||||
if src != "WORKSPACE" &&
|
||||
src != "BUILD" &&
|
||||
src != "BUILD.bazel" &&
|
||||
!strings.HasPrefix(src, "build/bazel") &&
|
||||
!strings.HasPrefix(src, "prebuilts/clang") {
|
||||
ret = append(ret, src)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func writeMetrics(configuration android.Config, eventHandler metrics.EventHandler, metricsDir string) {
|
||||
if len(metricsDir) < 1 {
|
||||
fmt.Fprintf(os.Stderr, "\nMissing required env var for generating soong metrics: LOG_DIR\n")
|
||||
@@ -248,6 +343,8 @@ func doChosenActivity(ctx *android.Context, configuration android.Config, extraN
|
||||
return bp2buildMarker
|
||||
} else if configuration.IsMixedBuildsEnabled() {
|
||||
runMixedModeBuild(configuration, ctx, extraNinjaDeps)
|
||||
} else if configuration.BuildMode == android.ApiBp2build {
|
||||
return runApiBp2build(configuration, extraNinjaDeps)
|
||||
} else {
|
||||
var stopBefore bootstrap.StopBefore
|
||||
if configuration.BuildMode == android.GenerateModuleGraph {
|
||||
@@ -476,6 +573,16 @@ func getExistingBazelRelatedFiles(topDir string) ([]string, error) {
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func bazelArtifacts() []string {
|
||||
return []string{
|
||||
"bazel-bin",
|
||||
"bazel-genfiles",
|
||||
"bazel-out",
|
||||
"bazel-testlogs",
|
||||
"bazel-" + filepath.Base(topDir),
|
||||
}
|
||||
}
|
||||
|
||||
// Run Soong in the bp2build mode. This creates a standalone context that registers
|
||||
// an alternate pipeline of mutators and singletons specifically for generating
|
||||
// Bazel BUILD files instead of Ninja files.
|
||||
@@ -524,13 +631,7 @@ func runBp2Build(configuration android.Config, extraNinjaDeps []string) {
|
||||
generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
|
||||
workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
|
||||
|
||||
excludes := []string{
|
||||
"bazel-bin",
|
||||
"bazel-genfiles",
|
||||
"bazel-out",
|
||||
"bazel-testlogs",
|
||||
"bazel-" + filepath.Base(topDir),
|
||||
}
|
||||
excludes := bazelArtifacts()
|
||||
|
||||
if outDir[0] != '/' {
|
||||
excludes = append(excludes, outDir)
|
||||
|
@@ -23,8 +23,9 @@ import (
|
||||
"android/soong/bp2build"
|
||||
)
|
||||
|
||||
func createBazelQueryView(ctx *bp2build.CodegenContext, bazelQueryViewDir string) error {
|
||||
os.RemoveAll(bazelQueryViewDir)
|
||||
// A helper function to generate a Read-only Bazel workspace in outDir
|
||||
func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string) error {
|
||||
os.RemoveAll(outDir)
|
||||
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
|
||||
|
||||
res, err := bp2build.GenerateBazelTargets(ctx, true)
|
||||
@@ -33,9 +34,9 @@ func createBazelQueryView(ctx *bp2build.CodegenContext, bazelQueryViewDir string
|
||||
}
|
||||
|
||||
filesToWrite := bp2build.CreateBazelFiles(ctx.Config(), ruleShims, res.BuildDirToTargets(),
|
||||
bp2build.QueryView)
|
||||
ctx.Mode())
|
||||
for _, f := range filesToWrite {
|
||||
if err := writeReadOnlyFile(bazelQueryViewDir, f); err != nil {
|
||||
if err := writeReadOnlyFile(outDir, f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@@ -71,6 +71,7 @@ type configImpl struct {
|
||||
checkbuild bool
|
||||
dist bool
|
||||
jsonModuleGraph bool
|
||||
apiBp2build bool // Generate BUILD files for Soong modules that contribute APIs
|
||||
bp2build bool
|
||||
queryview bool
|
||||
reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
|
||||
@@ -756,6 +757,8 @@ func (c *configImpl) parseArgs(ctx Context, args []string) {
|
||||
c.jsonModuleGraph = true
|
||||
} else if arg == "bp2build" {
|
||||
c.bp2build = true
|
||||
} else if arg == "api_bp2build" {
|
||||
c.apiBp2build = true
|
||||
} else if arg == "queryview" {
|
||||
c.queryview = true
|
||||
} else if arg == "soong_docs" {
|
||||
@@ -833,7 +836,7 @@ func (c *configImpl) SoongBuildInvocationNeeded() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() {
|
||||
if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
|
||||
// Command line was empty, the default Ninja target is built
|
||||
return true
|
||||
}
|
||||
@@ -916,6 +919,10 @@ func (c *configImpl) QueryviewMarkerFile() string {
|
||||
return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
|
||||
}
|
||||
|
||||
func (c *configImpl) ApiBp2buildMarkerFile() string {
|
||||
return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
|
||||
}
|
||||
|
||||
func (c *configImpl) ModuleGraphFile() string {
|
||||
return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
|
||||
}
|
||||
@@ -957,6 +964,10 @@ func (c *configImpl) Bp2Build() bool {
|
||||
return c.bp2build
|
||||
}
|
||||
|
||||
func (c *configImpl) ApiBp2build() bool {
|
||||
return c.apiBp2build
|
||||
}
|
||||
|
||||
func (c *configImpl) Queryview() bool {
|
||||
return c.queryview
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@ const (
|
||||
bp2buildTag = "bp2build"
|
||||
jsonModuleGraphTag = "modulegraph"
|
||||
queryviewTag = "queryview"
|
||||
apiBp2buildTag = "api_bp2build"
|
||||
soongDocsTag = "soong_docs"
|
||||
|
||||
// bootstrapEpoch is used to determine if an incremental build is incompatible with the current
|
||||
@@ -237,6 +238,7 @@ func bootstrapGlobFileList(config Config) []string {
|
||||
config.NamedGlobFile(bp2buildTag),
|
||||
config.NamedGlobFile(jsonModuleGraphTag),
|
||||
config.NamedGlobFile(queryviewTag),
|
||||
config.NamedGlobFile(apiBp2buildTag),
|
||||
config.NamedGlobFile(soongDocsTag),
|
||||
}
|
||||
}
|
||||
@@ -307,6 +309,19 @@ func bootstrapBlueprint(ctx Context, config Config) {
|
||||
fmt.Sprintf("generating the Soong module graph as a Bazel workspace at %s", queryviewDir),
|
||||
)
|
||||
|
||||
// The BUILD files will be generated in out/soong/.api_bp2build (no symlinks to src files)
|
||||
// The final workspace will be generated in out/soong/api_bp2build
|
||||
apiBp2buildDir := filepath.Join(config.SoongOutDir(), ".api_bp2build")
|
||||
apiBp2buildInvocation := primaryBuilderInvocation(
|
||||
config,
|
||||
apiBp2buildTag,
|
||||
config.ApiBp2buildMarkerFile(),
|
||||
[]string{
|
||||
"--bazel_api_bp2build_dir", apiBp2buildDir,
|
||||
},
|
||||
fmt.Sprintf("generating BUILD files for API contributions at %s", apiBp2buildDir),
|
||||
)
|
||||
|
||||
soongDocsInvocation := primaryBuilderInvocation(
|
||||
config,
|
||||
soongDocsTag,
|
||||
@@ -345,6 +360,7 @@ func bootstrapBlueprint(ctx Context, config Config) {
|
||||
bp2buildInvocation,
|
||||
jsonModuleGraphInvocation,
|
||||
queryviewInvocation,
|
||||
apiBp2buildInvocation,
|
||||
soongDocsInvocation},
|
||||
}
|
||||
|
||||
@@ -417,6 +433,10 @@ func runSoong(ctx Context, config Config) {
|
||||
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(queryviewTag))
|
||||
}
|
||||
|
||||
if config.ApiBp2build() {
|
||||
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(apiBp2buildTag))
|
||||
}
|
||||
|
||||
if config.SoongDocs() {
|
||||
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(soongDocsTag))
|
||||
}
|
||||
@@ -480,6 +500,10 @@ func runSoong(ctx Context, config Config) {
|
||||
targets = append(targets, config.QueryviewMarkerFile())
|
||||
}
|
||||
|
||||
if config.ApiBp2build() {
|
||||
targets = append(targets, config.ApiBp2buildMarkerFile())
|
||||
}
|
||||
|
||||
if config.SoongDocs() {
|
||||
targets = append(targets, config.SoongDocsHtml())
|
||||
}
|
||||
|
Reference in New Issue
Block a user