Loading android/bazel_handler.go +22 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,9 @@ type BazelContext interface { // Returns the results of the GetApexInfo query (including output files) 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 // Issues commands to Bazel to receive results for all cquery requests Loading Loading @@ -224,6 +227,7 @@ type MockBazelContext struct { LabelToCcInfo map[string]cquery.CcInfo LabelToPythonBinary map[string]string LabelToApexInfo map[string]cquery.ApexCqueryInfo LabelToCcBinary map[string]cquery.CcUnstrippedInfo } func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) { Loading @@ -249,6 +253,11 @@ func (n MockBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryI 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 { panic("unimplemented") } Loading Loading @@ -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) } 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) { panic("unimplemented") } Loading @@ -332,6 +349,11 @@ func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryI panic("unimplemented") } func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) { //TODO implement me panic("implement me") } func (n noopBazelContext) InvokeBazel(_ Config) error { panic("unimplemented") } Loading bazel/cquery/request_type.go +54 −5 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ var ( GetPythonBinary = &getPythonBinaryRequestType{} GetCcInfo = &getCcInfoType{} GetApexInfo = &getApexInfoType{} GetCcUnstrippedInfo = &getCcUnstippedInfoType{} ) type CcInfo struct { Loading @@ -30,6 +31,7 @@ type CcInfo struct { // but general cc_library will also have dynamic libraries in output files). RootDynamicLibraries []string TocFile string UnstrippedOutput string } type getOutputFilesRequestType struct{} Loading Loading @@ -135,12 +137,17 @@ sharedLibraries = [] rootSharedLibraries = [] 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): shared_info = providers(target)[shared_info_tag] path = shared_info.output_file.path sharedLibraries.append(path) rootSharedLibraries += [path] unstripped = path if unstripped_tag in providers(target): unstripped = providers(target)[unstripped_tag].unstripped.path else: for linker_input in linker_inputs: for library in linker_input.libraries: Loading Loading @@ -168,7 +175,8 @@ return json_encode({ "Headers": headers, "RootStaticArchives": rootStaticArchives, "RootDynamicLibraries": rootSharedLibraries, "TocFile": toc_file "TocFile": toc_file, "UnstrippedOutput": unstripped, })` } Loading Loading @@ -237,6 +245,47 @@ func (g getApexInfoType) ParseResult(rawString string) ApexCqueryInfo { 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 // if the given string is empty. func splitOrEmpty(s string, sep string) []string { Loading bazel/cquery/request_type_test.go +28 −0 Original line number Diff line number Diff line Loading @@ -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) } } } cc/binary.go +4 −9 Original line number Diff line number Diff line Loading @@ -577,25 +577,20 @@ var _ BazelHandler = (*ccBinaryBazelHandler)(nil) func (handler *ccBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) { 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) { bazelCtx := ctx.Config().BazelContext filePaths, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx)) info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKey(ctx)) if err != nil { ctx.ModuleErrorf(err.Error()) return } if len(filePaths) != 1 { ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, filePaths) return } outputFilePath := android.PathForBazelOut(ctx, filePaths[0]) outputFilePath := android.PathForBazelOut(ctx, info.OutputFile) 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 = outputFilePath handler.module.linker.(*binaryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput) } func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes { Loading cc/binary_test.go +7 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package cc import ( "android/soong/bazel/cquery" "testing" "android/soong/android" Loading @@ -30,8 +31,11 @@ cc_binary { config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) config.BazelContext = android.MockBazelContext{ OutputBaseDir: "outputbase", LabelToOutputFiles: map[string][]string{ "//foo/bar:bar": []string{"foo"}, LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{ "//foo/bar:bar": cquery.CcUnstrippedInfo{ OutputFile: "foo", UnstrippedOutput: "foo.unstripped", }, }, } ctx := testCcWithConfig(t, config) Loading @@ -46,7 +50,7 @@ cc_binary { android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile() expectedUnStrippedFile := "outputbase/execroot/__main__/foo" expectedUnStrippedFile := "outputbase/execroot/__main__/foo.unstripped" android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String()) } Loading Loading
android/bazel_handler.go +22 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,9 @@ type BazelContext interface { // Returns the results of the GetApexInfo query (including output files) 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 // Issues commands to Bazel to receive results for all cquery requests Loading Loading @@ -224,6 +227,7 @@ type MockBazelContext struct { LabelToCcInfo map[string]cquery.CcInfo LabelToPythonBinary map[string]string LabelToApexInfo map[string]cquery.ApexCqueryInfo LabelToCcBinary map[string]cquery.CcUnstrippedInfo } func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) { Loading @@ -249,6 +253,11 @@ func (n MockBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryI 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 { panic("unimplemented") } Loading Loading @@ -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) } 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) { panic("unimplemented") } Loading @@ -332,6 +349,11 @@ func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryI panic("unimplemented") } func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) { //TODO implement me panic("implement me") } func (n noopBazelContext) InvokeBazel(_ Config) error { panic("unimplemented") } Loading
bazel/cquery/request_type.go +54 −5 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ var ( GetPythonBinary = &getPythonBinaryRequestType{} GetCcInfo = &getCcInfoType{} GetApexInfo = &getApexInfoType{} GetCcUnstrippedInfo = &getCcUnstippedInfoType{} ) type CcInfo struct { Loading @@ -30,6 +31,7 @@ type CcInfo struct { // but general cc_library will also have dynamic libraries in output files). RootDynamicLibraries []string TocFile string UnstrippedOutput string } type getOutputFilesRequestType struct{} Loading Loading @@ -135,12 +137,17 @@ sharedLibraries = [] rootSharedLibraries = [] 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): shared_info = providers(target)[shared_info_tag] path = shared_info.output_file.path sharedLibraries.append(path) rootSharedLibraries += [path] unstripped = path if unstripped_tag in providers(target): unstripped = providers(target)[unstripped_tag].unstripped.path else: for linker_input in linker_inputs: for library in linker_input.libraries: Loading Loading @@ -168,7 +175,8 @@ return json_encode({ "Headers": headers, "RootStaticArchives": rootStaticArchives, "RootDynamicLibraries": rootSharedLibraries, "TocFile": toc_file "TocFile": toc_file, "UnstrippedOutput": unstripped, })` } Loading Loading @@ -237,6 +245,47 @@ func (g getApexInfoType) ParseResult(rawString string) ApexCqueryInfo { 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 // if the given string is empty. func splitOrEmpty(s string, sep string) []string { Loading
bazel/cquery/request_type_test.go +28 −0 Original line number Diff line number Diff line Loading @@ -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) } } }
cc/binary.go +4 −9 Original line number Diff line number Diff line Loading @@ -577,25 +577,20 @@ var _ BazelHandler = (*ccBinaryBazelHandler)(nil) func (handler *ccBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) { 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) { bazelCtx := ctx.Config().BazelContext filePaths, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx)) info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKey(ctx)) if err != nil { ctx.ModuleErrorf(err.Error()) return } if len(filePaths) != 1 { ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, filePaths) return } outputFilePath := android.PathForBazelOut(ctx, filePaths[0]) outputFilePath := android.PathForBazelOut(ctx, info.OutputFile) 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 = outputFilePath handler.module.linker.(*binaryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput) } func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes { Loading
cc/binary_test.go +7 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package cc import ( "android/soong/bazel/cquery" "testing" "android/soong/android" Loading @@ -30,8 +31,11 @@ cc_binary { config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) config.BazelContext = android.MockBazelContext{ OutputBaseDir: "outputbase", LabelToOutputFiles: map[string][]string{ "//foo/bar:bar": []string{"foo"}, LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{ "//foo/bar:bar": cquery.CcUnstrippedInfo{ OutputFile: "foo", UnstrippedOutput: "foo.unstripped", }, }, } ctx := testCcWithConfig(t, config) Loading @@ -46,7 +50,7 @@ cc_binary { android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile() expectedUnStrippedFile := "outputbase/execroot/__main__/foo" expectedUnStrippedFile := "outputbase/execroot/__main__/foo.unstripped" android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String()) } Loading