diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go index 8e39933f6..d731f3e49 100644 --- a/bazel/cquery/request_type.go +++ b/bazel/cquery/request_type.go @@ -25,6 +25,7 @@ type CcInfo struct { // be a subset of OutputFiles. (or shared libraries, this will be equal to OutputFiles, // but general cc_library will also have dynamic libraries in output files). RootDynamicLibraries []string + TocFile string } type getOutputFilesRequestType struct{} @@ -127,6 +128,11 @@ if shared_info_tag in providers(target): for lib in shared_info.linker_input.libraries: rootDynamicLibraries += [lib.dynamic_library.path] +toc_file = "" +toc_file_tag = "//build/bazel/rules:generate_toc.bzl%CcTocInfo" +if toc_file_tag in providers(target): + toc_file = providers(target)[toc_file_tag].toc.path + returns = [ outputFiles, staticLibraries, @@ -134,10 +140,10 @@ returns = [ includes, system_includes, rootStaticArchives, - rootDynamicLibraries + rootDynamicLibraries, ] -return "|".join([", ".join(r) for r in returns])` +return "|".join([", ".join(r) for r in returns] + [toc_file])` } // ParseResult returns a value obtained by parsing the result of the request's Starlark function. @@ -148,7 +154,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { var ccObjects []string splitString := strings.Split(rawString, "|") - if expectedLen := 7; len(splitString) != expectedLen { + if expectedLen := 8; len(splitString) != expectedLen { return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString) } outputFilesString := splitString[0] @@ -161,6 +167,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { systemIncludes := splitOrEmpty(splitString[4], ", ") rootStaticArchives := splitOrEmpty(splitString[5], ", ") rootDynamicLibraries := splitOrEmpty(splitString[6], ", ") + tocFile := splitString[7] // NOTE: Will be the empty string if there wasn't return CcInfo{ OutputFiles: outputFiles, CcObjectFiles: ccObjects, @@ -169,6 +176,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { SystemIncludes: systemIncludes, RootStaticArchives: rootStaticArchives, RootDynamicLibraries: rootDynamicLibraries, + TocFile: tocFile, }, nil } diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go index 49019abac..34d083226 100644 --- a/bazel/cquery/request_type_test.go +++ b/bazel/cquery/request_type_test.go @@ -71,7 +71,7 @@ func TestGetCcInfoParseResults(t *testing.T) { }{ { description: "no result", - input: "||||||", + input: "|||||||", expectedOutput: CcInfo{ OutputFiles: []string{}, CcObjectFiles: []string{}, @@ -80,11 +80,12 @@ func TestGetCcInfoParseResults(t *testing.T) { SystemIncludes: []string{}, RootStaticArchives: []string{}, RootDynamicLibraries: []string{}, + TocFile: "", }, }, { description: "only output", - input: "test||||||", + input: "test|||||||", expectedOutput: CcInfo{ OutputFiles: []string{"test"}, CcObjectFiles: []string{}, @@ -93,11 +94,12 @@ func TestGetCcInfoParseResults(t *testing.T) { SystemIncludes: []string{}, RootStaticArchives: []string{}, RootDynamicLibraries: []string{}, + TocFile: "", }, }, { description: "all items set", - input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|rootstaticarchive1|rootdynamiclibrary1", + input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc", expectedOutput: CcInfo{ OutputFiles: []string{"out1", "out2"}, CcObjectFiles: []string{"object1", "object2"}, @@ -106,19 +108,20 @@ func TestGetCcInfoParseResults(t *testing.T) { SystemIncludes: []string{"system/dir", "system/other/dir"}, RootStaticArchives: []string{"rootstaticarchive1"}, RootDynamicLibraries: []string{"rootdynamiclibrary1"}, + TocFile: "lib.so.toc", }, }, { description: "too few result splits", input: "|", expectedOutput: CcInfo{}, - expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 7, []string{"", ""}), + expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 8, []string{"", ""}), }, { description: "too many result splits", input: strings.Repeat("|", 8), expectedOutput: CcInfo{}, - expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 7, make([]string, 9)), + expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 8, make([]string, 9)), }, } for _, tc := range testCases { diff --git a/cc/library.go b/cc/library.go index 47351ba8d..703d57fef 100644 --- a/cc/library.go +++ b/cc/library.go @@ -604,7 +604,10 @@ func (handler *ccLibraryBazelHandler) generateSharedBazelBuildActions(ctx androi handler.module.linker.(*libraryDecorator).unstrippedOutputFile = outputFilePath - tocFile := getTocFile(ctx, label, ccInfo.OutputFiles) + var tocFile android.OptionalPath + if len(ccInfo.TocFile) > 0 { + tocFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, ccInfo.TocFile)) + } handler.module.linker.(*libraryDecorator).tocFile = tocFile ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{ @@ -617,25 +620,6 @@ func (handler *ccLibraryBazelHandler) generateSharedBazelBuildActions(ctx androi return true } -// getTocFile looks for the .so.toc file in the target's output files, if any. The .so.toc file -// contains the table of contents of all symbols of a shared object. -func getTocFile(ctx android.ModuleContext, label string, outputFiles []string) android.OptionalPath { - var tocFile string - for _, file := range outputFiles { - if strings.HasSuffix(file, ".so.toc") { - if tocFile != "" { - ctx.ModuleErrorf("The %s target cannot produce more than 1 .toc file.", label) - } - tocFile = file - // Don't break to validate that there are no multiple .toc files per .so. - } - } - if tocFile == "" { - return android.OptionalPath{} - } - return android.OptionalPathForPath(android.PathForBazelOut(ctx, tocFile)) -} - func (handler *ccLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool { bazelCtx := ctx.Config().BazelContext ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType) diff --git a/cc/library_test.go b/cc/library_test.go index 6caee49d7..7ddfaa7fd 100644 --- a/cc/library_test.go +++ b/cc/library_test.go @@ -337,19 +337,29 @@ cc_library_shared { Includes: []string{"include"}, SystemIncludes: []string{"system_include"}, RootDynamicLibraries: []string{"foo.so"}, + TocFile: "foo.so.toc", }, }, } ctx := testCcWithConfig(t, config) sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() - outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("") + producer := sharedFoo.(android.OutputFileProducer) + outputFiles, err := producer.OutputFiles("") if err != nil { t.Errorf("Unexpected error getting cc_object outputfiles %s", err) } expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.so"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) + tocFilePath := sharedFoo.(*Module).Toc() + if !tocFilePath.Valid() { + t.Errorf("Invalid tocFilePath: %s", tocFilePath) + } + tocFile := tocFilePath.Path() + expectedToc := "outputbase/execroot/__main__/foo.so.toc" + android.AssertStringEquals(t, "toc file", expectedToc, tocFile.String()) + entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0] expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"} gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"]