Invoke queryview from the bootstrap Ninja file.
It used to be invoked from out/soong/build.ninja, which required two soong_build invocations one after the other (ne to generate out/soong/build.ninja, one to generate the queryview workspace). This was slower and required some shell-quoted-in-ninja-quoted-in-Go . Test: Presubmits. Change-Id: Idda79c067606663b66e9f94626fa24f3b5af4114
This commit is contained in:
@@ -66,7 +66,6 @@ bootstrap_go_package {
|
|||||||
"prebuilt.go",
|
"prebuilt.go",
|
||||||
"prebuilt_build_tool.go",
|
"prebuilt_build_tool.go",
|
||||||
"proto.go",
|
"proto.go",
|
||||||
"queryview.go",
|
|
||||||
"register.go",
|
"register.go",
|
||||||
"rule_builder.go",
|
"rule_builder.go",
|
||||||
"sandbox.go",
|
"sandbox.go",
|
||||||
|
@@ -1,112 +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 (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The Bazel QueryView singleton is responsible for generating the Ninja actions
|
|
||||||
// for calling the soong_build primary builder in the main build.ninja file.
|
|
||||||
func init() {
|
|
||||||
RegisterSingletonType("bazel_queryview", BazelQueryViewSingleton)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BazelQueryViewSingleton is the singleton responsible for registering the
|
|
||||||
// soong_build build statement that will convert the Soong module graph after
|
|
||||||
// applying *all* mutators, enabing the feature to query the final state of the
|
|
||||||
// Soong graph. This mode is meant for querying the build graph state, and not meant
|
|
||||||
// for generating BUILD files to be checked in.
|
|
||||||
func BazelQueryViewSingleton() Singleton {
|
|
||||||
return &bazelQueryViewSingleton{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BazelConverterSingleton is the singleton responsible for registering the soong_build
|
|
||||||
// build statement that will convert the Soong module graph by applying an alternate
|
|
||||||
// pipeline of mutators, with the goal of reaching semantic equivalence between the original
|
|
||||||
// Blueprint and final BUILD files. Using this mode, the goal is to be able to
|
|
||||||
// build with these BUILD files directly in the source tree.
|
|
||||||
func BazelConverterSingleton() Singleton {
|
|
||||||
return &bazelConverterSingleton{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type bazelQueryViewSingleton struct{}
|
|
||||||
type bazelConverterSingleton struct{}
|
|
||||||
|
|
||||||
func generateBuildActionsForBazelConversion(ctx SingletonContext, converterMode bool) {
|
|
||||||
name := "queryview"
|
|
||||||
descriptionTemplate := "[EXPERIMENTAL, PRE-PRODUCTION] Creating the Bazel QueryView workspace with %s at $outDir"
|
|
||||||
|
|
||||||
// Create a build and rule statement, using the Bazel QueryView's WORKSPACE
|
|
||||||
// file as the output file marker.
|
|
||||||
var deps Paths
|
|
||||||
moduleListFilePath := pathForBuildToolDep(ctx, ctx.Config().moduleListFile)
|
|
||||||
deps = append(deps, moduleListFilePath)
|
|
||||||
deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
|
|
||||||
|
|
||||||
bazelQueryViewDirectory := PathForOutput(ctx, name)
|
|
||||||
bazelQueryViewWorkspaceFile := bazelQueryViewDirectory.Join(ctx, "WORKSPACE")
|
|
||||||
primaryBuilder := primaryBuilderPath(ctx)
|
|
||||||
bazelQueryView := ctx.Rule(pctx, "bazelQueryView",
|
|
||||||
blueprint.RuleParams{
|
|
||||||
Command: fmt.Sprintf(
|
|
||||||
`rm -rf "${outDir}/"* && `+
|
|
||||||
`mkdir -p "${outDir}" && `+
|
|
||||||
`echo WORKSPACE: $$(cat "%s") > "${outDir}/.queryview-depfile.d" && `+
|
|
||||||
`BUILDER="%s" && `+
|
|
||||||
`echo BUILDER=$$BUILDER && `+
|
|
||||||
`cd "$$(dirname "$$BUILDER")" && `+
|
|
||||||
`echo PWD=$$PWD && `+
|
|
||||||
`ABSBUILDER="$$PWD/$$(basename "$$BUILDER")" && `+
|
|
||||||
`echo ABSBUILDER=$$ABSBUILDER && `+
|
|
||||||
`cd / && `+
|
|
||||||
`env -i "$$ABSBUILDER" --bazel_queryview_dir "${outDir}" "%s"`,
|
|
||||||
moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
|
|
||||||
primaryBuilder.String(),
|
|
||||||
strings.Join(os.Args[1:], "\" \""),
|
|
||||||
),
|
|
||||||
CommandDeps: []string{primaryBuilder.String()},
|
|
||||||
Description: fmt.Sprintf(
|
|
||||||
descriptionTemplate,
|
|
||||||
primaryBuilder.Base()),
|
|
||||||
Deps: blueprint.DepsGCC,
|
|
||||||
Depfile: "${outDir}/.queryview-depfile.d",
|
|
||||||
},
|
|
||||||
"outDir")
|
|
||||||
|
|
||||||
ctx.Build(pctx, BuildParams{
|
|
||||||
Rule: bazelQueryView,
|
|
||||||
Output: bazelQueryViewWorkspaceFile,
|
|
||||||
Inputs: deps,
|
|
||||||
Args: map[string]string{
|
|
||||||
"outDir": bazelQueryViewDirectory.String(),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Add a phony target for generating the workspace
|
|
||||||
ctx.Phony(name, bazelQueryViewWorkspaceFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *bazelQueryViewSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|
||||||
generateBuildActionsForBazelConversion(ctx, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *bazelConverterSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|
||||||
generateBuildActionsForBazelConversion(ctx, true)
|
|
||||||
}
|
|
@@ -156,13 +156,15 @@ func runMixedModeBuild(configuration android.Config, firstCtx *android.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run the code-generation phase to convert BazelTargetModules to BUILD files.
|
// Run the code-generation phase to convert BazelTargetModules to BUILD files.
|
||||||
func runQueryView(configuration android.Config, ctx *android.Context) {
|
func runQueryView(queryviewDir, queryviewMarker string, configuration android.Config, ctx *android.Context) {
|
||||||
codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
|
codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
|
||||||
absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir)
|
absoluteQueryViewDir := shared.JoinPath(topDir, queryviewDir)
|
||||||
if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
|
if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%s", err)
|
fmt.Fprintf(os.Stderr, "%s", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
touch(shared.JoinPath(topDir, queryviewMarker))
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSoongDocs(configuration android.Config) {
|
func runSoongDocs(configuration android.Config) {
|
||||||
@@ -244,8 +246,10 @@ func doChosenActivity(configuration android.Config, extraNinjaDeps []string) str
|
|||||||
|
|
||||||
// Convert the Soong module graph into Bazel BUILD files.
|
// Convert the Soong module graph into Bazel BUILD files.
|
||||||
if generateQueryView {
|
if generateQueryView {
|
||||||
runQueryView(configuration, ctx)
|
queryviewMarkerFile := bazelQueryViewDir + ".marker"
|
||||||
return cmdlineArgs.OutFile // TODO: This is a lie
|
runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
|
||||||
|
writeDepFile(queryviewMarkerFile, ninjaDeps)
|
||||||
|
return queryviewMarkerFile
|
||||||
} else if moduleGraphFile != "" {
|
} else if moduleGraphFile != "" {
|
||||||
writeJsonModuleGraph(ctx, moduleGraphFile)
|
writeJsonModuleGraph(ctx, moduleGraphFile)
|
||||||
writeDepFile(moduleGraphFile, ninjaDeps)
|
writeDepFile(moduleGraphFile, ninjaDeps)
|
||||||
|
@@ -785,6 +785,28 @@ function test_bp2build_back_and_forth_null_build {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_queryview_smoke() {
|
||||||
|
setup
|
||||||
|
|
||||||
|
run_soong queryview
|
||||||
|
[[ -e out/soong/queryview/WORKSPACE ]] || fail "queryview WORKSPACE file not created"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_queryview_null_build() {
|
||||||
|
setup
|
||||||
|
|
||||||
|
run_soong queryview
|
||||||
|
local output_mtime1=$(stat -c "%y" out/soong/queryview.marker)
|
||||||
|
|
||||||
|
run_soong queryview
|
||||||
|
local output_mtime2=$(stat -c "%y" out/soong/queryview.marker)
|
||||||
|
|
||||||
|
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
|
||||||
|
fail "Queryview marker file changed on null build"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
test_smoke
|
test_smoke
|
||||||
test_null_build
|
test_null_build
|
||||||
test_null_build_after_docs
|
test_null_build_after_docs
|
||||||
@@ -801,6 +823,8 @@ test_multiple_soong_build_modes
|
|||||||
test_dump_json_module_graph
|
test_dump_json_module_graph
|
||||||
test_json_module_graph_back_and_forth_null_build
|
test_json_module_graph_back_and_forth_null_build
|
||||||
test_write_to_source_tree
|
test_write_to_source_tree
|
||||||
|
test_queryview_smoke
|
||||||
|
test_queryview_null_build
|
||||||
test_bp2build_smoke
|
test_bp2build_smoke
|
||||||
test_bp2build_generates_marker_file
|
test_bp2build_generates_marker_file
|
||||||
test_bp2build_null_build
|
test_bp2build_null_build
|
||||||
|
@@ -49,6 +49,7 @@ type configImpl struct {
|
|||||||
dist bool
|
dist bool
|
||||||
jsonModuleGraph bool
|
jsonModuleGraph bool
|
||||||
bp2build bool
|
bp2build bool
|
||||||
|
queryview bool
|
||||||
skipConfig bool
|
skipConfig bool
|
||||||
skipKati bool
|
skipKati bool
|
||||||
skipKatiNinja bool
|
skipKatiNinja bool
|
||||||
@@ -643,6 +644,8 @@ func (c *configImpl) parseArgs(ctx Context, args []string) {
|
|||||||
c.jsonModuleGraph = true
|
c.jsonModuleGraph = true
|
||||||
} else if arg == "bp2build" {
|
} else if arg == "bp2build" {
|
||||||
c.bp2build = true
|
c.bp2build = true
|
||||||
|
} else if arg == "queryview" {
|
||||||
|
c.queryview = true
|
||||||
} else {
|
} else {
|
||||||
if arg == "checkbuild" {
|
if arg == "checkbuild" {
|
||||||
c.checkbuild = true
|
c.checkbuild = true
|
||||||
@@ -720,7 +723,7 @@ func (c *configImpl) SoongBuildInvocationNeeded() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.JsonModuleGraph() && !c.Bp2Build() {
|
if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() {
|
||||||
// Command line was empty, the default Ninja target is built
|
// Command line was empty, the default Ninja target is built
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -785,6 +788,10 @@ func (c *configImpl) Bp2BuildMarkerFile() string {
|
|||||||
return shared.JoinPath(c.SoongOutDir(), ".bootstrap/bp2build_workspace_marker")
|
return shared.JoinPath(c.SoongOutDir(), ".bootstrap/bp2build_workspace_marker")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *configImpl) QueryviewMarkerFile() string {
|
||||||
|
return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
|
||||||
|
}
|
||||||
|
|
||||||
func (c *configImpl) ModuleGraphFile() string {
|
func (c *configImpl) ModuleGraphFile() string {
|
||||||
return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
|
return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
|
||||||
}
|
}
|
||||||
@@ -822,6 +829,10 @@ func (c *configImpl) Bp2Build() bool {
|
|||||||
return c.bp2build
|
return c.bp2build
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *configImpl) Queryview() bool {
|
||||||
|
return c.queryview
|
||||||
|
}
|
||||||
|
|
||||||
func (c *configImpl) IsVerbose() bool {
|
func (c *configImpl) IsVerbose() bool {
|
||||||
return c.verbose
|
return c.verbose
|
||||||
}
|
}
|
||||||
|
@@ -142,6 +142,7 @@ func bootstrapBlueprint(ctx Context, config Config) {
|
|||||||
|
|
||||||
bootstrapGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.ninja")
|
bootstrapGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.ninja")
|
||||||
bp2buildGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.bp2build.ninja")
|
bp2buildGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.bp2build.ninja")
|
||||||
|
queryviewGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.queryview.ninja")
|
||||||
moduleGraphGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.modulegraph.ninja")
|
moduleGraphGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.modulegraph.ninja")
|
||||||
|
|
||||||
// The glob .ninja files are subninja'd. However, they are generated during
|
// The glob .ninja files are subninja'd. However, they are generated during
|
||||||
@@ -149,6 +150,9 @@ func bootstrapBlueprint(ctx Context, config Config) {
|
|||||||
// fail on clean builds
|
// fail on clean builds
|
||||||
writeEmptyGlobFile(ctx, bootstrapGlobFile)
|
writeEmptyGlobFile(ctx, bootstrapGlobFile)
|
||||||
writeEmptyGlobFile(ctx, bp2buildGlobFile)
|
writeEmptyGlobFile(ctx, bp2buildGlobFile)
|
||||||
|
writeEmptyGlobFile(ctx, queryviewGlobFile)
|
||||||
|
writeEmptyGlobFile(ctx, moduleGraphGlobFile)
|
||||||
|
|
||||||
bootstrapDepFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build.ninja.d")
|
bootstrapDepFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build.ninja.d")
|
||||||
|
|
||||||
args.RunGoTests = !config.skipSoongTests
|
args.RunGoTests = !config.skipSoongTests
|
||||||
@@ -160,7 +164,7 @@ func bootstrapBlueprint(ctx Context, config Config) {
|
|||||||
// The primary builder (aka soong_build) will use bootstrapGlobFile as the globFile to generate build.ninja(.d)
|
// The primary builder (aka soong_build) will use bootstrapGlobFile as the globFile to generate build.ninja(.d)
|
||||||
// Building soong_build does not require a glob file
|
// Building soong_build does not require a glob file
|
||||||
// Using "" instead of "<soong_build_glob>.ninja" will ensure that an unused glob file is not written to out/soong/.bootstrap during StagePrimary
|
// Using "" instead of "<soong_build_glob>.ninja" will ensure that an unused glob file is not written to out/soong/.bootstrap during StagePrimary
|
||||||
args.Subninjas = []string{bootstrapGlobFile, bp2buildGlobFile}
|
args.Subninjas = []string{bootstrapGlobFile, bp2buildGlobFile, moduleGraphGlobFile, queryviewGlobFile}
|
||||||
args.EmptyNinjaFile = config.EmptyNinjaFile()
|
args.EmptyNinjaFile = config.EmptyNinjaFile()
|
||||||
|
|
||||||
args.DelveListen = os.Getenv("SOONG_DELVE")
|
args.DelveListen = os.Getenv("SOONG_DELVE")
|
||||||
@@ -206,6 +210,22 @@ func bootstrapBlueprint(ctx Context, config Config) {
|
|||||||
Args: bp2buildArgs,
|
Args: bp2buildArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queryviewArgs := []string{
|
||||||
|
"--bazel_queryview_dir", filepath.Join(config.SoongOutDir(), "queryview"),
|
||||||
|
"--globListDir", "queryview",
|
||||||
|
"--globFile", queryviewGlobFile,
|
||||||
|
}
|
||||||
|
|
||||||
|
queryviewArgs = append(queryviewArgs, commonArgs...)
|
||||||
|
queryviewArgs = append(queryviewArgs, environmentArgs(config, ".queryview")...)
|
||||||
|
queryviewArgs = append(queryviewArgs, "Android.bp")
|
||||||
|
|
||||||
|
queryviewInvocation := bootstrap.PrimaryBuilderInvocation{
|
||||||
|
Inputs: []string{"Android.bp"},
|
||||||
|
Outputs: []string{config.QueryviewMarkerFile()},
|
||||||
|
Args: queryviewArgs,
|
||||||
|
}
|
||||||
|
|
||||||
moduleGraphArgs := []string{
|
moduleGraphArgs := []string{
|
||||||
"--module_graph_file", config.ModuleGraphFile(),
|
"--module_graph_file", config.ModuleGraphFile(),
|
||||||
"--globListDir", "modulegraph",
|
"--globListDir", "modulegraph",
|
||||||
@@ -226,6 +246,7 @@ func bootstrapBlueprint(ctx Context, config Config) {
|
|||||||
bp2buildInvocation,
|
bp2buildInvocation,
|
||||||
mainSoongBuildInvocation,
|
mainSoongBuildInvocation,
|
||||||
moduleGraphInvocation,
|
moduleGraphInvocation,
|
||||||
|
queryviewInvocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
blueprintCtx := blueprint.NewContext()
|
blueprintCtx := blueprint.NewContext()
|
||||||
@@ -361,6 +382,10 @@ func runSoong(ctx Context, config Config) {
|
|||||||
targets = append(targets, config.Bp2BuildMarkerFile())
|
targets = append(targets, config.Bp2BuildMarkerFile())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Queryview() {
|
||||||
|
targets = append(targets, config.QueryviewMarkerFile())
|
||||||
|
}
|
||||||
|
|
||||||
if config.SoongBuildInvocationNeeded() {
|
if config.SoongBuildInvocationNeeded() {
|
||||||
// This build generates <builddir>/build.ninja, which is used later by build/soong/ui/build/build.go#Build().
|
// This build generates <builddir>/build.ninja, which is used later by build/soong/ui/build/build.go#Build().
|
||||||
targets = append(targets, config.MainNinjaFile())
|
targets = append(targets, config.MainNinjaFile())
|
||||||
|
Reference in New Issue
Block a user