Call mixed mode Bazel in the symlink forest.

Test: Presubmits + manual execution.
Change-Id: Idef2d821222ccbf9385d0ea3fc92178b3206df0a
This commit is contained in:
Lukacs T. Berki
2021-04-20 13:01:07 +02:00
parent 3784448c9e
commit d6cd813abc

View File

@@ -321,9 +321,8 @@ type builtinBazelRunner struct{}
// the invocation returned an error code. // the invocation returned an error code.
func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand, func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
extraFlags ...string) (string, string, error) { extraFlags ...string) (string, string, error) {
cmdFlags := []string{"--output_base=" + paths.outputBase, command.command} cmdFlags := []string{"--output_base=" + absolutePath(paths.outputBase), command.command}
cmdFlags = append(cmdFlags, command.expression) cmdFlags = append(cmdFlags, command.expression)
cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+paths.intermediatesDir())
cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(paths, runName)) cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(paths, runName))
// Set default platforms to canonicalized values for mixed builds requests. // Set default platforms to canonicalized values for mixed builds requests.
@@ -334,20 +333,20 @@ func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.
// The actual platform values here may be overridden by configuration // The actual platform values here may be overridden by configuration
// transitions from the buildroot. // transitions from the buildroot.
cmdFlags = append(cmdFlags, cmdFlags = append(cmdFlags,
fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:android_x86_64"))) fmt.Sprintf("--platforms=%s", "//build/bazel/platforms:android_x86_64"))
cmdFlags = append(cmdFlags, cmdFlags = append(cmdFlags,
fmt.Sprintf("--extra_toolchains=%s", canonicalizeLabel("//prebuilts/clang/host/linux-x86:all"))) fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"))
// This should be parameterized on the host OS, but let's restrict to linux // This should be parameterized on the host OS, but let's restrict to linux
// to keep things simple for now. // to keep things simple for now.
cmdFlags = append(cmdFlags, cmdFlags = append(cmdFlags,
fmt.Sprintf("--host_platform=%s", canonicalizeLabel("//build/bazel/platforms:linux_x86_64"))) fmt.Sprintf("--host_platform=%s", "//build/bazel/platforms:linux_x86_64"))
// Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network. // Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
cmdFlags = append(cmdFlags, "--experimental_repository_disable_download") cmdFlags = append(cmdFlags, "--experimental_repository_disable_download")
cmdFlags = append(cmdFlags, extraFlags...) cmdFlags = append(cmdFlags, extraFlags...)
bazelCmd := exec.Command(paths.bazelPath, cmdFlags...) bazelCmd := exec.Command(paths.bazelPath, cmdFlags...)
bazelCmd.Dir = paths.workspaceDir bazelCmd.Dir = absolutePath(paths.syntheticWorkspaceDir())
bazelCmd.Env = append(os.Environ(), "HOME="+paths.homeDir, pwdPrefix(), bazelCmd.Env = append(os.Environ(), "HOME="+paths.homeDir, pwdPrefix(),
// Disables local host detection of gcc; toolchain information is defined // Disables local host detection of gcc; toolchain information is defined
// explicitly in BUILD files. // explicitly in BUILD files.
@@ -363,31 +362,6 @@ func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.
} }
} }
// Returns the string contents of a workspace file that should be output
// adjacent to the main bzl file and build file.
// This workspace file allows, via local_repository rule, sourcetree-level
// BUILD targets to be referenced via @sourceroot.
func (context *bazelContext) workspaceFileContents() []byte {
formatString := `
# This file is generated by soong_build. Do not edit.
local_repository(
name = "sourceroot",
path = "%[1]s",
)
local_repository(
name = "rules_cc",
path = "%[1]s/build/bazel/rules_cc",
)
local_repository(
name = "bazel_skylib",
path = "%[1]s/build/bazel/bazel_skylib",
)
`
return []byte(fmt.Sprintf(formatString, context.paths.workspaceDir))
}
func (context *bazelContext) mainBzlFileContents() []byte { func (context *bazelContext) mainBzlFileContents() []byte {
// TODO(cparsons): Define configuration transitions programmatically based // TODO(cparsons): Define configuration transitions programmatically based
// on available archs. // on available archs.
@@ -398,7 +372,7 @@ func (context *bazelContext) mainBzlFileContents() []byte {
def _config_node_transition_impl(settings, attr): def _config_node_transition_impl(settings, attr):
return { return {
"//command_line_option:platforms": "@sourceroot//build/bazel/platforms:android_%s" % attr.arch, "//command_line_option:platforms": "@//build/bazel/platforms:android_%s" % attr.arch,
} }
_config_node_transition = transition( _config_node_transition = transition(
@@ -447,18 +421,6 @@ phony_root = rule(
return []byte(contents) return []byte(contents)
} }
// Returns a "canonicalized" corresponding to the given sourcetree-level label.
// This abstraction is required because a sourcetree label such as //foo/bar:baz
// must be referenced via the local repository prefix, such as
// @sourceroot//foo/bar:baz.
func canonicalizeLabel(label string) string {
if strings.HasPrefix(label, "//") {
return "@sourceroot" + label
} else {
return "@sourceroot//" + label
}
}
func (context *bazelContext) mainBuildFileContents() []byte { func (context *bazelContext) mainBuildFileContents() []byte {
// TODO(cparsons): Map label to attribute programmatically; don't use hard-coded // TODO(cparsons): Map label to attribute programmatically; don't use hard-coded
// architecture mapping. // architecture mapping.
@@ -487,7 +449,7 @@ config_node(name = "%s",
labelsByArch := map[string][]string{} labelsByArch := map[string][]string{}
for val, _ := range context.requests { for val, _ := range context.requests {
labelString := fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label)) labelString := fmt.Sprintf("\"@%s\"", val.label)
archString := getArchString(val) archString := getArchString(val)
labelsByArch[archString] = append(labelsByArch[archString], labelString) labelsByArch[archString] = append(labelsByArch[archString], labelString)
} }
@@ -593,12 +555,24 @@ def format(target):
mainSwitchSection)) mainSwitchSection))
} }
// Returns a workspace-relative path containing build-related metadata required // Returns a path containing build-related metadata required for interfacing
// for interfacing with Bazel. Example: out/soong/bazel. // with Bazel. Example: out/soong/bazel.
func (p *bazelPaths) intermediatesDir() string { func (p *bazelPaths) intermediatesDir() string {
return filepath.Join(p.buildDir, "bazel") return filepath.Join(p.buildDir, "bazel")
} }
// Returns the path where the contents of the @soong_injection repository live.
// It is used by Soong to tell Bazel things it cannot over the command line.
func (p *bazelPaths) injectedFilesDir() string {
return filepath.Join(p.buildDir, "soong_injection")
}
// Returns the path of the synthetic Bazel workspace that contains a symlink
// forest composed the whole source tree and BUILD files generated by bp2build.
func (p *bazelPaths) syntheticWorkspaceDir() string {
return filepath.Join(p.buildDir, "workspace")
}
// Issues commands to Bazel to receive results for all cquery requests // Issues commands to Bazel to receive results for all cquery requests
// queued in the BazelContext. // queued in the BazelContext.
func (context *bazelContext) InvokeBazel() error { func (context *bazelContext) InvokeBazel() error {
@@ -608,47 +582,47 @@ func (context *bazelContext) InvokeBazel() error {
var cqueryErr string var cqueryErr string
var err error var err error
intermediatesDirPath := absolutePath(context.paths.intermediatesDir()) soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
if _, err := os.Stat(intermediatesDirPath); os.IsNotExist(err) { if _, err := os.Stat(soongInjectionPath); os.IsNotExist(err) {
err = os.Mkdir(intermediatesDirPath, 0777) err = os.Mkdir(soongInjectionPath, 0777)
} }
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666)
if err != nil {
return err
}
err = ioutil.WriteFile( err = ioutil.WriteFile(
filepath.Join(intermediatesDirPath, "main.bzl"), filepath.Join(soongInjectionPath, "main.bzl"),
context.mainBzlFileContents(), 0666) context.mainBzlFileContents(), 0666)
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile( err = ioutil.WriteFile(
filepath.Join(intermediatesDirPath, "BUILD.bazel"), filepath.Join(soongInjectionPath, "BUILD.bazel"),
context.mainBuildFileContents(), 0666) context.mainBuildFileContents(), 0666)
if err != nil { if err != nil {
return err return err
} }
cqueryFileRelpath := filepath.Join(context.paths.intermediatesDir(), "buildroot.cquery") cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
err = ioutil.WriteFile( err = ioutil.WriteFile(
absolutePath(cqueryFileRelpath), absolutePath(cqueryFileRelpath),
context.cqueryStarlarkFileContents(), 0666) context.cqueryStarlarkFileContents(), 0666)
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile( buildrootLabel := "@soong_injection//:buildroot"
filepath.Join(intermediatesDirPath, "WORKSPACE.bazel"),
context.workspaceFileContents(), 0666)
if err != nil {
return err
}
buildrootLabel := "//:buildroot"
cqueryOutput, cqueryErr, err = context.issueBazelCommand( cqueryOutput, cqueryErr, err = context.issueBazelCommand(
context.paths, context.paths,
bazel.CqueryBuildRootRunName, bazel.CqueryBuildRootRunName,
bazelCommand{"cquery", fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)}, bazelCommand{"cquery", fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
"--output=starlark", "--output=starlark",
"--starlark:file="+cqueryFileRelpath) "--starlark:file="+absolutePath(cqueryFileRelpath))
err = ioutil.WriteFile(filepath.Join(intermediatesDirPath, "cquery.out"), err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"),
[]byte(cqueryOutput), 0666) []byte(cqueryOutput), 0666)
if err != nil { if err != nil {
return err return err
@@ -702,7 +676,7 @@ func (context *bazelContext) InvokeBazel() error {
_, _, err = context.issueBazelCommand( _, _, err = context.issueBazelCommand(
context.paths, context.paths,
bazel.BazelBuildPhonyRootRunName, bazel.BazelBuildPhonyRootRunName,
bazelCommand{"build", "//:phonyroot"}) bazelCommand{"build", "@soong_injection//:phonyroot"})
if err != nil { if err != nil {
return err return err
@@ -781,7 +755,7 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
} }
func getCqueryId(key cqueryKey) string { func getCqueryId(key cqueryKey) string {
return canonicalizeLabel(key.label) + "|" + getArchString(key) return key.label + "|" + getArchString(key)
} }
func getArchString(key cqueryKey) string { func getArchString(key cqueryKey) string {