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
1 changed files with 39 additions and 65 deletions

View File

@ -321,9 +321,8 @@ type builtinBazelRunner struct{}
// the invocation returned an error code.
func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
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, "--package_path=%workspace%/"+paths.intermediatesDir())
cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(paths, runName))
// 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
// transitions from the buildroot.
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,
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
// to keep things simple for now.
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.
cmdFlags = append(cmdFlags, "--experimental_repository_disable_download")
cmdFlags = append(cmdFlags, extraFlags...)
bazelCmd := exec.Command(paths.bazelPath, cmdFlags...)
bazelCmd.Dir = paths.workspaceDir
bazelCmd.Dir = absolutePath(paths.syntheticWorkspaceDir())
bazelCmd.Env = append(os.Environ(), "HOME="+paths.homeDir, pwdPrefix(),
// Disables local host detection of gcc; toolchain information is defined
// 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 {
// TODO(cparsons): Define configuration transitions programmatically based
// on available archs.
@ -398,7 +372,7 @@ func (context *bazelContext) mainBzlFileContents() []byte {
def _config_node_transition_impl(settings, attr):
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(
@ -447,18 +421,6 @@ phony_root = rule(
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 {
// TODO(cparsons): Map label to attribute programmatically; don't use hard-coded
// architecture mapping.
@ -487,7 +449,7 @@ config_node(name = "%s",
labelsByArch := map[string][]string{}
for val, _ := range context.requests {
labelString := fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label))
labelString := fmt.Sprintf("\"@%s\"", val.label)
archString := getArchString(val)
labelsByArch[archString] = append(labelsByArch[archString], labelString)
}
@ -593,12 +555,24 @@ def format(target):
mainSwitchSection))
}
// Returns a workspace-relative path containing build-related metadata required
// for interfacing with Bazel. Example: out/soong/bazel.
// Returns a path containing build-related metadata required for interfacing
// with Bazel. Example: out/soong/bazel.
func (p *bazelPaths) intermediatesDir() string {
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
// queued in the BazelContext.
func (context *bazelContext) InvokeBazel() error {
@ -608,47 +582,47 @@ func (context *bazelContext) InvokeBazel() error {
var cqueryErr string
var err error
intermediatesDirPath := absolutePath(context.paths.intermediatesDir())
if _, err := os.Stat(intermediatesDirPath); os.IsNotExist(err) {
err = os.Mkdir(intermediatesDirPath, 0777)
soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
if _, err := os.Stat(soongInjectionPath); os.IsNotExist(err) {
err = os.Mkdir(soongInjectionPath, 0777)
}
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666)
if err != nil {
return err
}
err = ioutil.WriteFile(
filepath.Join(intermediatesDirPath, "main.bzl"),
filepath.Join(soongInjectionPath, "main.bzl"),
context.mainBzlFileContents(), 0666)
if err != nil {
return err
}
err = ioutil.WriteFile(
filepath.Join(intermediatesDirPath, "BUILD.bazel"),
filepath.Join(soongInjectionPath, "BUILD.bazel"),
context.mainBuildFileContents(), 0666)
if err != nil {
return err
}
cqueryFileRelpath := filepath.Join(context.paths.intermediatesDir(), "buildroot.cquery")
cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
err = ioutil.WriteFile(
absolutePath(cqueryFileRelpath),
context.cqueryStarlarkFileContents(), 0666)
if err != nil {
return err
}
err = ioutil.WriteFile(
filepath.Join(intermediatesDirPath, "WORKSPACE.bazel"),
context.workspaceFileContents(), 0666)
if err != nil {
return err
}
buildrootLabel := "//:buildroot"
buildrootLabel := "@soong_injection//:buildroot"
cqueryOutput, cqueryErr, err = context.issueBazelCommand(
context.paths,
bazel.CqueryBuildRootRunName,
bazelCommand{"cquery", fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
"--output=starlark",
"--starlark:file="+cqueryFileRelpath)
err = ioutil.WriteFile(filepath.Join(intermediatesDirPath, "cquery.out"),
"--starlark:file="+absolutePath(cqueryFileRelpath))
err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"),
[]byte(cqueryOutput), 0666)
if err != nil {
return err
@ -702,7 +676,7 @@ func (context *bazelContext) InvokeBazel() error {
_, _, err = context.issueBazelCommand(
context.paths,
bazel.BazelBuildPhonyRootRunName,
bazelCommand{"build", "//:phonyroot"})
bazelCommand{"build", "@soong_injection//:phonyroot"})
if err != nil {
return err
@ -781,7 +755,7 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
}
func getCqueryId(key cqueryKey) string {
return canonicalizeLabel(key.label) + "|" + getArchString(key)
return key.label + "|" + getArchString(key)
}
func getArchString(key cqueryKey) string {