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

Commit 2bed9ffa authored by Christopher Parsons's avatar Christopher Parsons Committed by Gerrit Code Review
Browse files

Merge "mixed builds for cc_static_library without deps"

parents 6f688d03 808d84c4
Loading
Loading
Loading
Loading
+64 −10
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ type CqueryRequestType int
const (
	getAllFiles CqueryRequestType = iota
	getCcObjectFiles
	getAllFilesAndCcObjectFiles
)

// Map key to describe bazel cquery requests.
@@ -58,7 +59,9 @@ type BazelContext interface {
	// Retrieves these files from Bazel's CcInfo provider.
	GetCcObjectFiles(label string, archType ArchType) ([]string, bool)

	// TODO(cparsons): Other cquery-related methods should be added here.
	// Returns the results of GetAllFiles and GetCcObjectFiles in a single query (in that order).
	GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool)

	// ** End cquery methods

	// Issues commands to Bazel to receive results for all cquery requests
@@ -116,6 +119,11 @@ func (m MockBazelContext) GetCcObjectFiles(label string, archType ArchType) ([]s
	return result, ok
}

func (m MockBazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
	result, ok := m.AllFiles[label]
	return result, result, ok
}

func (m MockBazelContext) InvokeBazel() error {
	panic("unimplemented")
}
@@ -154,6 +162,22 @@ func (bazelCtx *bazelContext) GetCcObjectFiles(label string, archType ArchType)
	}
}

func (bazelCtx *bazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
	var allFiles []string
	var ccObjects []string

	result, ok := bazelCtx.cquery(label, getAllFilesAndCcObjectFiles, archType)
	if ok {
		bazelOutput := strings.TrimSpace(result)
		splitString := strings.Split(bazelOutput, "|")
		allFilesString := splitString[0]
		ccObjectsString := splitString[1]
		allFiles = strings.Split(allFilesString, ", ")
		ccObjects = strings.Split(ccObjectsString, ", ")
	}
	return allFiles, ccObjects, ok
}

func (n noopBazelContext) GetAllFiles(label string, archType ArchType) ([]string, bool) {
	panic("unimplemented")
}
@@ -162,6 +186,10 @@ func (n noopBazelContext) GetCcObjectFiles(label string, archType ArchType) ([]s
	panic("unimplemented")
}

func (n noopBazelContext) GetAllFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
	panic("unimplemented")
}

func (n noopBazelContext) InvokeBazel() error {
	panic("unimplemented")
}
@@ -253,8 +281,12 @@ func pwdPrefix() string {
	return ""
}

// Issues the given bazel command with given build label and additional flags.
// Returns (stdout, stderr, error). The first and second return values are strings
// containing the stdout and stderr of the run command, and an error is returned if
// the invocation returned an error code.
func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command string, labels []string,
	extraFlags ...string) (string, error) {
	extraFlags ...string) (string, string, error) {

	cmdFlags := []string{"--output_base=" + context.outputBase, command}
	cmdFlags = append(cmdFlags, labels...)
@@ -281,9 +313,10 @@ func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command st
	bazelCmd.Stderr = stderr

	if output, err := bazelCmd.Output(); err != nil {
		return "", fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
		return "", string(stderr.Bytes()),
			fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
	} else {
		return string(output), nil
		return string(output), string(stderr.Bytes()), nil
	}
}

@@ -452,6 +485,11 @@ phony_root(name = "phonyroot",
		strings.Join(deps_arm, ",\n            ")))
}

// Returns the file contents of the buildroot.cquery file that should be used for the cquery
// expression in order to obtain information about buildroot and its dependencies.
// The contents of this file depend on the bazelContext's requests; requests are enumerated
// and grouped by their request type. The data retrieved for each label depends on its
// request type.
func (context *bazelContext) cqueryStarlarkFileContents() []byte {
	formatString := `
# This file is generated by soong_build. Do not edit.
@@ -463,6 +501,13 @@ getCcObjectFilesLabels = {
  %s
}

getAllFilesAndCcObjectFilesLabels = {
  %s
}

def get_all_files(target):
  return [f.path for f in target.files.to_list()]

def get_cc_object_files(target):
  result = []
  linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list()
@@ -492,9 +537,11 @@ def get_arch(target):
def format(target):
  id_string = str(target.label) + "|" + get_arch(target)
  if id_string in getAllFilesLabels:
    return id_string + ">>" + ', '.join([f.path for f in target.files.to_list()])
    return id_string + ">>" + ', '.join(get_all_files(target))
  elif id_string in getCcObjectFilesLabels:
    return id_string + ">>" + ', '.join(get_cc_object_files(target))
  elif id_string in getAllFilesAndCcObjectFilesLabels:
    return id_string + ">>" + ', '.join(get_all_files(target)) + "|" + ', '.join(get_cc_object_files(target))
  else:
    # This target was not requested via cquery, and thus must be a dependency
    # of a requested target.
@@ -502,6 +549,7 @@ def format(target):
`
	var getAllFilesDeps []string = nil
	var getCcObjectFilesDeps []string = nil
	var getAllFilesAndCcObjectFilesDeps []string = nil

	for val, _ := range context.requests {
		labelWithArch := getCqueryId(val)
@@ -511,12 +559,16 @@ def format(target):
			getAllFilesDeps = append(getAllFilesDeps, mapEntryString)
		case getCcObjectFiles:
			getCcObjectFilesDeps = append(getCcObjectFilesDeps, mapEntryString)
		case getAllFilesAndCcObjectFiles:
			getAllFilesAndCcObjectFilesDeps = append(getAllFilesAndCcObjectFilesDeps, mapEntryString)
		}
	}
	getAllFilesDepsString := strings.Join(getAllFilesDeps, ",\n  ")
	getCcObjectFilesDepsString := strings.Join(getCcObjectFilesDeps, ",\n  ")
	getAllFilesAndCcObjectFilesDepsString := strings.Join(getAllFilesAndCcObjectFilesDeps, ",\n  ")

	return []byte(fmt.Sprintf(formatString, getAllFilesDepsString, getCcObjectFilesDepsString))
	return []byte(fmt.Sprintf(formatString, getAllFilesDepsString, getCcObjectFilesDepsString,
		getAllFilesAndCcObjectFilesDepsString))
}

// Returns a workspace-relative path containing build-related metadata required
@@ -531,6 +583,7 @@ func (context *bazelContext) InvokeBazel() error {
	context.results = make(map[cqueryKey]string)

	var cqueryOutput string
	var cqueryErr string
	var err error

	intermediatesDirPath := absolutePath(context.intermediatesDir())
@@ -568,7 +621,7 @@ func (context *bazelContext) InvokeBazel() error {
		return err
	}
	buildrootLabel := "//:buildroot"
	cqueryOutput, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
	cqueryOutput, cqueryErr, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
		[]string{fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
		"--output=starlark",
		"--starlark:file="+cqueryFileRelpath)
@@ -595,7 +648,8 @@ func (context *bazelContext) InvokeBazel() error {
		if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
			context.results[val] = string(cqueryResult)
		} else {
			return fmt.Errorf("missing result for bazel target %s. query output: [%s]", getCqueryId(val), cqueryOutput)
			return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
				getCqueryId(val), cqueryOutput, cqueryErr)
		}
	}

@@ -603,7 +657,7 @@ func (context *bazelContext) InvokeBazel() error {
	//
	// TODO(cparsons): Use --target_pattern_file to avoid command line limits.
	var aqueryOutput string
	aqueryOutput, err = context.issueBazelCommand(bazel.AqueryBuildRootRunName, "aquery",
	aqueryOutput, _, err = context.issueBazelCommand(bazel.AqueryBuildRootRunName, "aquery",
		[]string{fmt.Sprintf("deps(%s)", buildrootLabel),
			// Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
			// proto sources, which would add a number of unnecessary dependencies.
@@ -621,7 +675,7 @@ func (context *bazelContext) InvokeBazel() error {
	// Issue a build command of the phony root to generate symlink forests for dependencies of the
	// Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
	// but some of symlinks may be required to resolve source dependencies of the build.
	_, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build",
	_, _, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build",
		[]string{"//:phonyroot"})

	if err != nil {
+44 −0
Original line number Diff line number Diff line
@@ -230,6 +230,7 @@ func LibraryStaticFactory() android.Module {
	module, library := NewLibrary(android.HostAndDeviceSupported)
	library.BuildOnlyStatic()
	module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
	module.bazelHandler = &staticLibraryBazelHandler{module: module}
	return module.Init()
}

@@ -406,6 +407,49 @@ type libraryDecorator struct {
	collectedSnapshotHeaders android.Paths
}

type staticLibraryBazelHandler struct {
	bazelHandler

	module *Module
}

func (handler *staticLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
	bazelCtx := ctx.Config().BazelContext
	outputPaths, objPaths, ok := bazelCtx.GetAllFilesAndCcObjectFiles(label, ctx.Arch().ArchType)
	if ok {
		if len(outputPaths) != 1 {
			// TODO(cparsons): This is actually expected behavior for static libraries with no srcs.
			// We should support this.
			ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, objPaths)
			return false
		}
		outputFilePath := android.PathForBazelOut(ctx, outputPaths[0])
		handler.module.outputFile = android.OptionalPathForPath(outputFilePath)

		objFiles := make(android.Paths, len(objPaths))
		for i, objPath := range objPaths {
			objFiles[i] = android.PathForBazelOut(ctx, objPath)
		}
		objects := Objects{
			objFiles: objFiles,
		}

		ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
			StaticLibrary: outputFilePath,
			ReuseObjects:  objects,
			Objects:       objects,

			// TODO(cparsons): Include transitive static libraries in this provider to support
			// static libraries with deps.
			TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
				Direct(outputFilePath).
				Build(),
		})
		handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0]))
	}
	return ok
}

// collectHeadersForSnapshot collects all exported headers from library.
// It globs header files in the source tree for exported include directories,
// and tracks generated header files separately.