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

Commit 8ccdb635 authored by Chris Parsons's avatar Chris Parsons
Browse files

Use packagepath and local_repository for mixed builds

This allows mixed builds to continue functioning even given the toplevel
WORKSPACE file containing toplevel_output_directories with out/.

Test: Manually verified on aosp_flame building libc.
Change-Id: I80fc4853421317e2d2c7f03d92d58286df1342ce
parent beab64ea
Loading
Loading
Loading
Loading
+53 −7
Original line number Diff line number Diff line
@@ -195,6 +195,7 @@ func (context *bazelContext) issueBazelCommand(command string, labels []string,
	cmdFlags := []string{"--bazelrc=build/bazel/common.bazelrc",
		"--output_base=" + context.outputBase, command}
	cmdFlags = append(cmdFlags, labels...)
	cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir())
	cmdFlags = append(cmdFlags, extraFlags...)

	bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
@@ -211,6 +212,21 @@ func (context *bazelContext) issueBazelCommand(command string, labels []string,
	}
}

// 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 = "%s",
)
`
	return []byte(fmt.Sprintf(formatString, context.workspaceDir))
}

func (context *bazelContext) mainBzlFileContents() []byte {
	contents := `
# This file is generated by soong_build. Do not edit.
@@ -225,6 +241,18 @@ mixed_build_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 {
	formatString := `
# This file is generated by soong_build. Do not edit.
@@ -236,7 +264,7 @@ mixed_build_root(name = "buildroot",
`
	var buildRootDeps []string = nil
	for val, _ := range context.requests {
		buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\"", val.label))
		buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label)))
	}
	buildRootDepsString := strings.Join(buildRootDeps, ",\n            ")

@@ -262,13 +290,19 @@ def format(target):
	// TODO(cparsons): Sort by request type instead of assuming all requests
	// are of GetAllFiles type.
	for val, _ := range context.requests {
		buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\" : True", val.label))
		buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\" : True", canonicalizeLabel(val.label)))
	}
	buildRootDepsString := strings.Join(buildRootDeps, ",\n  ")

	return []byte(fmt.Sprintf(formatString, buildRootDepsString))
}

// Returns a workspace-relative path containing build-related metadata required
// for interfacing with Bazel. Example: out/soong/bazel.
func (context *bazelContext) intermediatesDir() string {
	return filepath.Join(context.buildDir, "bazel")
}

// Issues commands to Bazel to receive results for all cquery requests
// queued in the BazelContext.
func (context *bazelContext) InvokeBazel() error {
@@ -276,26 +310,38 @@ func (context *bazelContext) InvokeBazel() error {

	var cqueryOutput string
	var err error

	err = os.Mkdir(absolutePath(context.intermediatesDir()), 0777)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(
		absolutePath(filepath.Join(context.buildDir, "main.bzl")),
		absolutePath(filepath.Join(context.intermediatesDir(), "main.bzl")),
		context.mainBzlFileContents(), 0666)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(
		absolutePath(filepath.Join(context.buildDir, "BUILD.bazel")),
		absolutePath(filepath.Join(context.intermediatesDir(), "BUILD.bazel")),
		context.mainBuildFileContents(), 0666)
	if err != nil {
		return err
	}
	cquery_file_relpath := filepath.Join(context.buildDir, "buildroot.cquery")
	cquery_file_relpath := filepath.Join(context.intermediatesDir(), "buildroot.cquery")
	err = ioutil.WriteFile(
		absolutePath(cquery_file_relpath),
		context.cqueryStarlarkFileContents(), 0666)
	if err != nil {
		return err
	}
	buildroot_label := fmt.Sprintf("//%s:buildroot", context.buildDir)
	workspace_file_relpath := filepath.Join(context.intermediatesDir(), "WORKSPACE.bazel")
	err = ioutil.WriteFile(
		absolutePath(workspace_file_relpath),
		context.workspaceFileContents(), 0666)
	if err != nil {
		return err
	}
	buildroot_label := "//:buildroot"
	cqueryOutput, err = context.issueBazelCommand("cquery",
		[]string{fmt.Sprintf("deps(%s)", buildroot_label)},
		"--output=starlark",
@@ -314,7 +360,7 @@ func (context *bazelContext) InvokeBazel() error {
	}

	for val, _ := range context.requests {
		if cqueryResult, ok := cqueryResults[val.label]; ok {
		if cqueryResult, ok := cqueryResults[canonicalizeLabel(val.label)]; ok {
			context.results[val] = string(cqueryResult)
		} else {
			return fmt.Errorf("missing result for bazel target %s", val.label)