Merge "Add CcUnstrippedInfo provider and use it in mixed builds"
This commit is contained in:
@@ -144,6 +144,9 @@ type BazelContext interface {
|
|||||||
// Returns the results of the GetApexInfo query (including output files)
|
// Returns the results of the GetApexInfo query (including output files)
|
||||||
GetApexInfo(label string, cfgkey configKey) (cquery.ApexCqueryInfo, error)
|
GetApexInfo(label string, cfgkey configKey) (cquery.ApexCqueryInfo, error)
|
||||||
|
|
||||||
|
// Returns the results of the GetCcUnstrippedInfo query
|
||||||
|
GetCcUnstrippedInfo(label string, cfgkey configKey) (cquery.CcUnstrippedInfo, error)
|
||||||
|
|
||||||
// ** end Cquery Results Retrieval Functions
|
// ** end Cquery Results Retrieval Functions
|
||||||
|
|
||||||
// Issues commands to Bazel to receive results for all cquery requests
|
// Issues commands to Bazel to receive results for all cquery requests
|
||||||
@@ -224,6 +227,7 @@ type MockBazelContext struct {
|
|||||||
LabelToCcInfo map[string]cquery.CcInfo
|
LabelToCcInfo map[string]cquery.CcInfo
|
||||||
LabelToPythonBinary map[string]string
|
LabelToPythonBinary map[string]string
|
||||||
LabelToApexInfo map[string]cquery.ApexCqueryInfo
|
LabelToApexInfo map[string]cquery.ApexCqueryInfo
|
||||||
|
LabelToCcBinary map[string]cquery.CcUnstrippedInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
|
func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
|
||||||
@@ -249,6 +253,11 @@ func (n MockBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryI
|
|||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery.CcUnstrippedInfo, error) {
|
||||||
|
result, _ := m.LabelToCcBinary[label]
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m MockBazelContext) InvokeBazel(_ Config) error {
|
func (m MockBazelContext) InvokeBazel(_ Config) error {
|
||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
@@ -312,6 +321,14 @@ func (bazelCtx *bazelContext) GetApexInfo(label string, cfgKey configKey) (cquer
|
|||||||
return cquery.ApexCqueryInfo{}, fmt.Errorf("no bazel response found for %v", key)
|
return cquery.ApexCqueryInfo{}, fmt.Errorf("no bazel response found for %v", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bazelCtx *bazelContext) GetCcUnstrippedInfo(label string, cfgKey configKey) (cquery.CcUnstrippedInfo, error) {
|
||||||
|
key := makeCqueryKey(label, cquery.GetCcUnstrippedInfo, cfgKey)
|
||||||
|
if rawString, ok := bazelCtx.results[key]; ok {
|
||||||
|
return cquery.GetCcUnstrippedInfo.ParseResult(strings.TrimSpace(rawString)), nil
|
||||||
|
}
|
||||||
|
return cquery.CcUnstrippedInfo{}, fmt.Errorf("no bazel response for %s", key)
|
||||||
|
}
|
||||||
|
|
||||||
func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
|
func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
|
||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
@@ -332,6 +349,11 @@ func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryI
|
|||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
func (n noopBazelContext) InvokeBazel(_ Config) error {
|
func (n noopBazelContext) InvokeBazel(_ Config) error {
|
||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
|
@@ -7,10 +7,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GetOutputFiles = &getOutputFilesRequestType{}
|
GetOutputFiles = &getOutputFilesRequestType{}
|
||||||
GetPythonBinary = &getPythonBinaryRequestType{}
|
GetPythonBinary = &getPythonBinaryRequestType{}
|
||||||
GetCcInfo = &getCcInfoType{}
|
GetCcInfo = &getCcInfoType{}
|
||||||
GetApexInfo = &getApexInfoType{}
|
GetApexInfo = &getApexInfoType{}
|
||||||
|
GetCcUnstrippedInfo = &getCcUnstippedInfoType{}
|
||||||
)
|
)
|
||||||
|
|
||||||
type CcInfo struct {
|
type CcInfo struct {
|
||||||
@@ -30,6 +31,7 @@ type CcInfo struct {
|
|||||||
// but general cc_library will also have dynamic libraries in output files).
|
// but general cc_library will also have dynamic libraries in output files).
|
||||||
RootDynamicLibraries []string
|
RootDynamicLibraries []string
|
||||||
TocFile string
|
TocFile string
|
||||||
|
UnstrippedOutput string
|
||||||
}
|
}
|
||||||
|
|
||||||
type getOutputFilesRequestType struct{}
|
type getOutputFilesRequestType struct{}
|
||||||
@@ -135,12 +137,17 @@ sharedLibraries = []
|
|||||||
rootSharedLibraries = []
|
rootSharedLibraries = []
|
||||||
|
|
||||||
shared_info_tag = "//build/bazel/rules/cc:cc_library_shared.bzl%CcSharedLibraryOutputInfo"
|
shared_info_tag = "//build/bazel/rules/cc:cc_library_shared.bzl%CcSharedLibraryOutputInfo"
|
||||||
|
unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
|
||||||
|
unstripped = ""
|
||||||
|
|
||||||
if shared_info_tag in providers(target):
|
if shared_info_tag in providers(target):
|
||||||
shared_info = providers(target)[shared_info_tag]
|
shared_info = providers(target)[shared_info_tag]
|
||||||
path = shared_info.output_file.path
|
path = shared_info.output_file.path
|
||||||
sharedLibraries.append(path)
|
sharedLibraries.append(path)
|
||||||
rootSharedLibraries += [path]
|
rootSharedLibraries += [path]
|
||||||
|
unstripped = path
|
||||||
|
if unstripped_tag in providers(target):
|
||||||
|
unstripped = providers(target)[unstripped_tag].unstripped.path
|
||||||
else:
|
else:
|
||||||
for linker_input in linker_inputs:
|
for linker_input in linker_inputs:
|
||||||
for library in linker_input.libraries:
|
for library in linker_input.libraries:
|
||||||
@@ -168,7 +175,8 @@ return json_encode({
|
|||||||
"Headers": headers,
|
"Headers": headers,
|
||||||
"RootStaticArchives": rootStaticArchives,
|
"RootStaticArchives": rootStaticArchives,
|
||||||
"RootDynamicLibraries": rootSharedLibraries,
|
"RootDynamicLibraries": rootSharedLibraries,
|
||||||
"TocFile": toc_file
|
"TocFile": toc_file,
|
||||||
|
"UnstrippedOutput": unstripped,
|
||||||
})`
|
})`
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -237,6 +245,47 @@ func (g getApexInfoType) ParseResult(rawString string) ApexCqueryInfo {
|
|||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getCcUnstrippedInfoType implements cqueryRequest interface. It handles the
|
||||||
|
// interaction with `bazel cquery` to retrieve CcUnstrippedInfo provided
|
||||||
|
// by the` cc_binary` and `cc_shared_library` rules.
|
||||||
|
type getCcUnstippedInfoType struct{}
|
||||||
|
|
||||||
|
func (g getCcUnstippedInfoType) Name() string {
|
||||||
|
return "getCcUnstrippedInfo"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g getCcUnstippedInfoType) StarlarkFunctionBody() string {
|
||||||
|
return `unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
|
||||||
|
p = providers(target)
|
||||||
|
output_path = target.files.to_list()[0].path
|
||||||
|
unstripped = output_path
|
||||||
|
if unstripped_tag in p:
|
||||||
|
unstripped = p[unstripped_tag].unstripped.files.to_list()[0].path
|
||||||
|
return json_encode({
|
||||||
|
"OutputFile": output_path,
|
||||||
|
"UnstrippedOutput": unstripped,
|
||||||
|
})
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
|
||||||
|
// The given rawString must correspond to the string output which was created by evaluating the
|
||||||
|
// Starlark given in StarlarkFunctionBody.
|
||||||
|
func (g getCcUnstippedInfoType) ParseResult(rawString string) CcUnstrippedInfo {
|
||||||
|
var info CcUnstrippedInfo
|
||||||
|
decoder := json.NewDecoder(strings.NewReader(rawString))
|
||||||
|
decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
|
||||||
|
if err := decoder.Decode(&info); err != nil {
|
||||||
|
panic(fmt.Errorf("cannot parse cquery result '%s': %s", rawString, err))
|
||||||
|
}
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
type CcUnstrippedInfo struct {
|
||||||
|
OutputFile string
|
||||||
|
UnstrippedOutput string
|
||||||
|
}
|
||||||
|
|
||||||
// splitOrEmpty is a modification of strings.Split() that returns an empty list
|
// splitOrEmpty is a modification of strings.Split() that returns an empty list
|
||||||
// if the given string is empty.
|
// if the given string is empty.
|
||||||
func splitOrEmpty(s string, sep string) []string {
|
func splitOrEmpty(s string, sep string) []string {
|
||||||
|
@@ -165,3 +165,31 @@ func TestGetApexInfoParseResults(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetCcUnstrippedParseResults(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
input string
|
||||||
|
expectedOutput CcUnstrippedInfo
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "no result",
|
||||||
|
input: "{}",
|
||||||
|
expectedOutput: CcUnstrippedInfo{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "one result",
|
||||||
|
input: `{"OutputFile":"myapp", "UnstrippedOutput":"myapp_unstripped"}`,
|
||||||
|
expectedOutput: CcUnstrippedInfo{
|
||||||
|
OutputFile: "myapp",
|
||||||
|
UnstrippedOutput: "myapp_unstripped",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
actualOutput := GetCcUnstrippedInfo.ParseResult(tc.input)
|
||||||
|
if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
|
||||||
|
t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
13
cc/binary.go
13
cc/binary.go
@@ -577,25 +577,20 @@ var _ BazelHandler = (*ccBinaryBazelHandler)(nil)
|
|||||||
|
|
||||||
func (handler *ccBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
|
func (handler *ccBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
|
||||||
bazelCtx := ctx.Config().BazelContext
|
bazelCtx := ctx.Config().BazelContext
|
||||||
bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKey(ctx))
|
bazelCtx.QueueBazelRequest(label, cquery.GetCcUnstrippedInfo, android.GetConfigKey(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *ccBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
|
func (handler *ccBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
|
||||||
bazelCtx := ctx.Config().BazelContext
|
bazelCtx := ctx.Config().BazelContext
|
||||||
filePaths, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
|
info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKey(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ModuleErrorf(err.Error())
|
ctx.ModuleErrorf(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(filePaths) != 1 {
|
outputFilePath := android.PathForBazelOut(ctx, info.OutputFile)
|
||||||
ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, filePaths)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
outputFilePath := android.PathForBazelOut(ctx, filePaths[0])
|
|
||||||
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
|
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
|
||||||
// TODO(b/220164721): We need to decide if we should return the stripped as the unstripped.
|
handler.module.linker.(*binaryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
|
||||||
handler.module.linker.(*binaryDecorator).unstrippedOutputFile = outputFilePath
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes {
|
func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes {
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
package cc
|
package cc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"android/soong/bazel/cquery"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
@@ -30,8 +31,11 @@ cc_binary {
|
|||||||
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
|
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
|
||||||
config.BazelContext = android.MockBazelContext{
|
config.BazelContext = android.MockBazelContext{
|
||||||
OutputBaseDir: "outputbase",
|
OutputBaseDir: "outputbase",
|
||||||
LabelToOutputFiles: map[string][]string{
|
LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{
|
||||||
"//foo/bar:bar": []string{"foo"},
|
"//foo/bar:bar": cquery.CcUnstrippedInfo{
|
||||||
|
OutputFile: "foo",
|
||||||
|
UnstrippedOutput: "foo.unstripped",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ctx := testCcWithConfig(t, config)
|
ctx := testCcWithConfig(t, config)
|
||||||
@@ -46,7 +50,7 @@ cc_binary {
|
|||||||
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
|
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
|
||||||
|
|
||||||
unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile()
|
unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile()
|
||||||
expectedUnStrippedFile := "outputbase/execroot/__main__/foo"
|
expectedUnStrippedFile := "outputbase/execroot/__main__/foo.unstripped"
|
||||||
android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
|
android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -885,7 +885,7 @@ func (handler *ccLibraryBazelHandler) generateSharedBazelBuildActions(ctx androi
|
|||||||
outputFilePath := android.PathForBazelOut(ctx, rootDynamicLibraries[0])
|
outputFilePath := android.PathForBazelOut(ctx, rootDynamicLibraries[0])
|
||||||
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
|
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
|
||||||
|
|
||||||
handler.module.linker.(*libraryDecorator).unstrippedOutputFile = outputFilePath
|
handler.module.linker.(*libraryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, ccInfo.UnstrippedOutput)
|
||||||
|
|
||||||
var tocFile android.OptionalPath
|
var tocFile android.OptionalPath
|
||||||
if len(ccInfo.TocFile) > 0 {
|
if len(ccInfo.TocFile) > 0 {
|
||||||
|
@@ -259,6 +259,7 @@ cc_library {
|
|||||||
SystemIncludes: []string{"system_include"},
|
SystemIncludes: []string{"system_include"},
|
||||||
Headers: []string{"foo.h"},
|
Headers: []string{"foo.h"},
|
||||||
RootDynamicLibraries: []string{"foo.so"},
|
RootDynamicLibraries: []string{"foo.so"},
|
||||||
|
UnstrippedOutput: "foo_unstripped.so",
|
||||||
},
|
},
|
||||||
"//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
|
"//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
|
||||||
CcObjectFiles: []string{"foo.o"},
|
CcObjectFiles: []string{"foo.o"},
|
||||||
@@ -294,6 +295,7 @@ cc_library {
|
|||||||
expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
|
expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
|
||||||
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
|
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, "unstripped shared library", "outputbase/execroot/__main__/foo_unstripped.so", sharedFoo.(*Module).linker.unstrippedOutputFilePath().String())
|
||||||
flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo)
|
flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo)
|
||||||
android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
|
android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
|
||||||
android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
|
android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
|
||||||
|
Reference in New Issue
Block a user