Merge "mixed builds for cc_static_library without deps" am: 2bed9ffaf4
am: a86985e40a
am: 3cb7e6bd83
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1625068 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Iddbc0f04dec0faeb70f5ccfe694dd3deaa65cb61
This commit is contained in:
commit
3a642e2800
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue