Loading bazel/cquery/request_type.go +41 −18 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ var ( type CcInfo struct { OutputFiles []string CcObjectFiles []string CcSharedLibraryFiles []string CcStaticLibraryFiles []string Includes []string SystemIncludes []string Loading Loading @@ -128,28 +129,43 @@ else: if linker_input.owner == target.label: rootStaticArchives.append(library.static_library.path) rootDynamicLibraries = [] sharedLibraries = [] rootSharedLibraries = [] shared_info_tag = "@rules_cc//examples:experimental_cc_shared_library.bzl%CcSharedLibraryInfo" if shared_info_tag in providers(target): shared_info = providers(target)[shared_info_tag] for lib in shared_info.linker_input.libraries: rootDynamicLibraries += [lib.dynamic_library.path] path = lib.dynamic_library.path rootSharedLibraries += [path] sharedLibraries.append(path) else: for linker_input in linker_inputs: for library in linker_input.libraries: if library.dynamic_library: path = library.dynamic_library.path sharedLibraries.append(path) if linker_input.owner == target.label: rootSharedLibraries.append(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 else: # NOTE: It's OK if there's no ToC, as Soong just uses it for optimization pass returns = [ outputFiles, staticLibraries, ccObjectFiles, sharedLibraries, staticLibraries, includes, system_includes, headers, rootStaticArchives, rootDynamicLibraries, rootSharedLibraries, [toc_file] ] Loading @@ -160,28 +176,35 @@ return "|".join([", ".join(r) for r in returns])` // The given rawString must correspond to the string output which was created by evaluating the // Starlark given in StarlarkFunctionBody. func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { var outputFiles []string var ccObjects []string const expectedLen = 10 splitString := strings.Split(rawString, "|") if expectedLen := 9; len(splitString) != expectedLen { if len(splitString) != expectedLen { return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString) } outputFilesString := splitString[0] ccStaticLibrariesString := splitString[1] ccObjectsString := splitString[2] outputFiles = splitOrEmpty(outputFilesString, ", ") ccObjectsString := splitString[1] ccSharedLibrariesString := splitString[2] ccStaticLibrariesString := splitString[3] includesString := splitString[4] systemIncludesString := splitString[5] headersString := splitString[6] rootStaticArchivesString := splitString[7] rootDynamicLibrariesString := splitString[8] tocFile := splitString[9] // NOTE: Will be the empty string if there wasn't outputFiles := splitOrEmpty(outputFilesString, ", ") ccObjects := splitOrEmpty(ccObjectsString, ", ") ccSharedLibraries := splitOrEmpty(ccSharedLibrariesString, ", ") ccStaticLibraries := splitOrEmpty(ccStaticLibrariesString, ", ") ccObjects = splitOrEmpty(ccObjectsString, ", ") includes := splitOrEmpty(splitString[3], ", ") systemIncludes := splitOrEmpty(splitString[4], ", ") headers := splitOrEmpty(splitString[5], ", ") rootStaticArchives := splitOrEmpty(splitString[6], ", ") rootDynamicLibraries := splitOrEmpty(splitString[7], ", ") tocFile := splitString[8] // NOTE: Will be the empty string if there wasn't includes := splitOrEmpty(includesString, ", ") systemIncludes := splitOrEmpty(systemIncludesString, ", ") headers := splitOrEmpty(headersString, ", ") rootStaticArchives := splitOrEmpty(rootStaticArchivesString, ", ") rootDynamicLibraries := splitOrEmpty(rootDynamicLibrariesString, ", ") return CcInfo{ OutputFiles: outputFiles, CcObjectFiles: ccObjects, CcSharedLibraryFiles: ccSharedLibraries, CcStaticLibraryFiles: ccStaticLibraries, Includes: includes, SystemIncludes: systemIncludes, Loading bazel/cquery/request_type_test.go +38 −8 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ func TestGetPythonBinaryParseResults(t *testing.T) { } func TestGetCcInfoParseResults(t *testing.T) { const expectedSplits = 10 noResult := strings.Repeat("|", expectedSplits-1) testCases := []struct { description string input string Loading @@ -71,10 +73,11 @@ func TestGetCcInfoParseResults(t *testing.T) { }{ { description: "no result", input: "||||||||", input: noResult, expectedOutput: CcInfo{ OutputFiles: []string{}, CcObjectFiles: []string{}, CcSharedLibraryFiles: []string{}, CcStaticLibraryFiles: []string{}, Includes: []string{}, SystemIncludes: []string{}, Loading @@ -86,10 +89,11 @@ func TestGetCcInfoParseResults(t *testing.T) { }, { description: "only output", input: "test||||||||", input: "test" + noResult, expectedOutput: CcInfo{ OutputFiles: []string{"test"}, CcObjectFiles: []string{}, CcSharedLibraryFiles: []string{}, CcStaticLibraryFiles: []string{}, Includes: []string{}, SystemIncludes: []string{}, Loading @@ -99,12 +103,38 @@ func TestGetCcInfoParseResults(t *testing.T) { TocFile: "", }, }, { description: "only ToC", input: noResult + "test", expectedOutput: CcInfo{ OutputFiles: []string{}, CcObjectFiles: []string{}, CcSharedLibraryFiles: []string{}, CcStaticLibraryFiles: []string{}, Includes: []string{}, SystemIncludes: []string{}, Headers: []string{}, RootStaticArchives: []string{}, RootDynamicLibraries: []string{}, TocFile: "test", }, }, { description: "all items set", input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|dir/subdir/hdr.h|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc", input: "out1, out2" + "|object1, object2" + "|shared_lib1, shared_lib2" + "|static_lib1, static_lib2" + "|., dir/subdir" + "|system/dir, system/other/dir" + "|dir/subdir/hdr.h" + "|rootstaticarchive1" + "|rootdynamiclibrary1" + "|lib.so.toc", expectedOutput: CcInfo{ OutputFiles: []string{"out1", "out2"}, CcObjectFiles: []string{"object1", "object2"}, CcSharedLibraryFiles: []string{"shared_lib1", "shared_lib2"}, CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"}, Includes: []string{".", "dir/subdir"}, SystemIncludes: []string{"system/dir", "system/other/dir"}, Loading @@ -118,22 +148,22 @@ func TestGetCcInfoParseResults(t *testing.T) { description: "too few result splits", input: "|", expectedOutput: CcInfo{}, expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, []string{"", ""}), expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, []string{"", ""}), }, { description: "too many result splits", input: strings.Repeat("|", 50), input: strings.Repeat("|", expectedSplits+1), // 2 too many expectedOutput: CcInfo{}, expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, make([]string, 51)), expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, make([]string, expectedSplits+2)), }, } for _, tc := range testCases { actualOutput, err := GetCcInfo.ParseResult(tc.input) if (err == nil && tc.expectedErrorMessage != "") || (err != nil && err.Error() != tc.expectedErrorMessage) { t.Errorf("%q: expected Error %s, got %s", tc.description, tc.expectedErrorMessage, err) t.Errorf("%q:\nexpected Error %s\n, got %s", tc.description, tc.expectedErrorMessage, err) } else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) { t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput) t.Errorf("%q:\n expected %#v\n!= actual %#v", tc.description, tc.expectedOutput, actualOutput) } } } cc/androidmk.go +1 −1 Original line number Diff line number Diff line Loading @@ -241,7 +241,7 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries entries.Class = "SHARED_LIBRARIES" entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { entries.SetString("LOCAL_SOONG_TOC", library.toc().String()) if !library.buildStubs() { if !library.buildStubs() && library.unstrippedOutputFile != nil { entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", library.unstrippedOutputFile.String()) } if len(library.Properties.Overrides) > 0 { Loading cc/prebuilt.go +64 −0 Original line number Diff line number Diff line Loading @@ -298,6 +298,7 @@ func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libr module, library := NewPrebuiltLibrary(hod, "srcs") library.BuildOnlyShared() module.bazelable = true module.bazelHandler = &prebuiltSharedLibraryBazelHandler{module: module, library: library} // Prebuilt shared libraries can be included in APEXes android.InitApexModule(module) Loading Loading @@ -426,6 +427,69 @@ func (h *prebuiltStaticLibraryBazelHandler) GenerateBazelBuildActions(ctx androi return true } type prebuiltSharedLibraryBazelHandler struct { android.BazelHandler module *Module library *libraryDecorator } func (h *prebuiltSharedLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool { bazelCtx := ctx.Config().BazelContext ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx)) if err != nil { ctx.ModuleErrorf("Error getting Bazel CcInfo for %s: %s", label, err) } if !ok { return false } sharedLibs := ccInfo.CcSharedLibraryFiles if len(sharedLibs) != 1 { ctx.ModuleErrorf("expected 1 shared library from bazel target %s, got %q", label, sharedLibs) return false } // TODO(b/184543518): cc_prebuilt_library_shared may have properties for re-exporting flags // TODO(eakammer):Add stub-related flags if this library is a stub library. // h.library.exportVersioningMacroIfNeeded(ctx) // Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise // validation will fail. For now, set this to an empty list. // TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation. h.library.collectedSnapshotHeaders = android.Paths{} if len(sharedLibs) == 0 { h.module.outputFile = android.OptionalPath{} return true } out := android.PathForBazelOut(ctx, sharedLibs[0]) h.module.outputFile = android.OptionalPathForPath(out) // FIXME(b/214600441): We don't yet strip prebuilt shared libraries h.library.unstrippedOutputFile = out var toc android.Path if len(ccInfo.TocFile) > 0 { toc = android.PathForBazelOut(ctx, ccInfo.TocFile) } else { toc = out // Just reuse `out` so ninja still gets an input but won't matter } info := SharedLibraryInfo{ SharedLibrary: out, TableOfContents: android.OptionalPathForPath(toc), Target: ctx.Target(), } ctx.SetProvider(SharedLibraryInfoProvider, info) h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo) h.module.maybeUnhideFromMake() return true } func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt { return &p.Prebuilt } Loading cc/prebuilt_test.go +72 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ import ( "testing" "android/soong/android" "android/soong/bazel/cquery" "github.com/google/blueprint" ) Loading Loading @@ -378,3 +378,74 @@ func TestPrebuiltLibrarySanitized(t *testing.T) { static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module) assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a") } func TestPrebuiltLibrarySharedWithBazelWithoutToc(t *testing.T) { const bp = ` cc_prebuilt_library_shared { name: "foo", srcs: ["foo.so"], bazel_module: { label: "//foo/bar:bar" }, }` outBaseDir := "outputbase" config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) config.BazelContext = android.MockBazelContext{ OutputBaseDir: outBaseDir, LabelToCcInfo: map[string]cquery.CcInfo{ "//foo/bar:bar": cquery.CcInfo{ CcSharedLibraryFiles: []string{"foo.so"}, }, }, } ctx := testCcWithConfig(t, config) sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() pathPrefix := outBaseDir + "/execroot/__main__/" info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo) android.AssertPathRelativeToTopEquals(t, "prebuilt shared library", pathPrefix+"foo.so", info.SharedLibrary) android.AssertPathRelativeToTopEquals(t, "prebuilt's 'nullary' ToC", pathPrefix+"foo.so", info.TableOfContents.Path()) outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("") if err != nil { t.Errorf("Unexpected error getting cc_object outputfiles %s", err) } expectedOutputFiles := []string{pathPrefix + "foo.so"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) } func TestPrebuiltLibrarySharedWithBazelWithToc(t *testing.T) { const bp = ` cc_prebuilt_library_shared { name: "foo", srcs: ["foo.so"], bazel_module: { label: "//foo/bar:bar" }, }` outBaseDir := "outputbase" config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) config.BazelContext = android.MockBazelContext{ OutputBaseDir: outBaseDir, LabelToCcInfo: map[string]cquery.CcInfo{ "//foo/bar:bar": cquery.CcInfo{ CcSharedLibraryFiles: []string{"foo.so"}, TocFile: "toc", }, }, } ctx := testCcWithConfig(t, config) sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() pathPrefix := outBaseDir + "/execroot/__main__/" info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo) android.AssertPathRelativeToTopEquals(t, "prebuilt shared library's ToC", pathPrefix+"toc", info.TableOfContents.Path()) android.AssertPathRelativeToTopEquals(t, "prebuilt shared library", pathPrefix+"foo.so", info.SharedLibrary) outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("") if err != nil { t.Errorf("Unexpected error getting cc_object outputfiles %s", err) } expectedOutputFiles := []string{pathPrefix + "foo.so"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) } Loading
bazel/cquery/request_type.go +41 −18 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ var ( type CcInfo struct { OutputFiles []string CcObjectFiles []string CcSharedLibraryFiles []string CcStaticLibraryFiles []string Includes []string SystemIncludes []string Loading Loading @@ -128,28 +129,43 @@ else: if linker_input.owner == target.label: rootStaticArchives.append(library.static_library.path) rootDynamicLibraries = [] sharedLibraries = [] rootSharedLibraries = [] shared_info_tag = "@rules_cc//examples:experimental_cc_shared_library.bzl%CcSharedLibraryInfo" if shared_info_tag in providers(target): shared_info = providers(target)[shared_info_tag] for lib in shared_info.linker_input.libraries: rootDynamicLibraries += [lib.dynamic_library.path] path = lib.dynamic_library.path rootSharedLibraries += [path] sharedLibraries.append(path) else: for linker_input in linker_inputs: for library in linker_input.libraries: if library.dynamic_library: path = library.dynamic_library.path sharedLibraries.append(path) if linker_input.owner == target.label: rootSharedLibraries.append(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 else: # NOTE: It's OK if there's no ToC, as Soong just uses it for optimization pass returns = [ outputFiles, staticLibraries, ccObjectFiles, sharedLibraries, staticLibraries, includes, system_includes, headers, rootStaticArchives, rootDynamicLibraries, rootSharedLibraries, [toc_file] ] Loading @@ -160,28 +176,35 @@ return "|".join([", ".join(r) for r in returns])` // The given rawString must correspond to the string output which was created by evaluating the // Starlark given in StarlarkFunctionBody. func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) { var outputFiles []string var ccObjects []string const expectedLen = 10 splitString := strings.Split(rawString, "|") if expectedLen := 9; len(splitString) != expectedLen { if len(splitString) != expectedLen { return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString) } outputFilesString := splitString[0] ccStaticLibrariesString := splitString[1] ccObjectsString := splitString[2] outputFiles = splitOrEmpty(outputFilesString, ", ") ccObjectsString := splitString[1] ccSharedLibrariesString := splitString[2] ccStaticLibrariesString := splitString[3] includesString := splitString[4] systemIncludesString := splitString[5] headersString := splitString[6] rootStaticArchivesString := splitString[7] rootDynamicLibrariesString := splitString[8] tocFile := splitString[9] // NOTE: Will be the empty string if there wasn't outputFiles := splitOrEmpty(outputFilesString, ", ") ccObjects := splitOrEmpty(ccObjectsString, ", ") ccSharedLibraries := splitOrEmpty(ccSharedLibrariesString, ", ") ccStaticLibraries := splitOrEmpty(ccStaticLibrariesString, ", ") ccObjects = splitOrEmpty(ccObjectsString, ", ") includes := splitOrEmpty(splitString[3], ", ") systemIncludes := splitOrEmpty(splitString[4], ", ") headers := splitOrEmpty(splitString[5], ", ") rootStaticArchives := splitOrEmpty(splitString[6], ", ") rootDynamicLibraries := splitOrEmpty(splitString[7], ", ") tocFile := splitString[8] // NOTE: Will be the empty string if there wasn't includes := splitOrEmpty(includesString, ", ") systemIncludes := splitOrEmpty(systemIncludesString, ", ") headers := splitOrEmpty(headersString, ", ") rootStaticArchives := splitOrEmpty(rootStaticArchivesString, ", ") rootDynamicLibraries := splitOrEmpty(rootDynamicLibrariesString, ", ") return CcInfo{ OutputFiles: outputFiles, CcObjectFiles: ccObjects, CcSharedLibraryFiles: ccSharedLibraries, CcStaticLibraryFiles: ccStaticLibraries, Includes: includes, SystemIncludes: systemIncludes, Loading
bazel/cquery/request_type_test.go +38 −8 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ func TestGetPythonBinaryParseResults(t *testing.T) { } func TestGetCcInfoParseResults(t *testing.T) { const expectedSplits = 10 noResult := strings.Repeat("|", expectedSplits-1) testCases := []struct { description string input string Loading @@ -71,10 +73,11 @@ func TestGetCcInfoParseResults(t *testing.T) { }{ { description: "no result", input: "||||||||", input: noResult, expectedOutput: CcInfo{ OutputFiles: []string{}, CcObjectFiles: []string{}, CcSharedLibraryFiles: []string{}, CcStaticLibraryFiles: []string{}, Includes: []string{}, SystemIncludes: []string{}, Loading @@ -86,10 +89,11 @@ func TestGetCcInfoParseResults(t *testing.T) { }, { description: "only output", input: "test||||||||", input: "test" + noResult, expectedOutput: CcInfo{ OutputFiles: []string{"test"}, CcObjectFiles: []string{}, CcSharedLibraryFiles: []string{}, CcStaticLibraryFiles: []string{}, Includes: []string{}, SystemIncludes: []string{}, Loading @@ -99,12 +103,38 @@ func TestGetCcInfoParseResults(t *testing.T) { TocFile: "", }, }, { description: "only ToC", input: noResult + "test", expectedOutput: CcInfo{ OutputFiles: []string{}, CcObjectFiles: []string{}, CcSharedLibraryFiles: []string{}, CcStaticLibraryFiles: []string{}, Includes: []string{}, SystemIncludes: []string{}, Headers: []string{}, RootStaticArchives: []string{}, RootDynamicLibraries: []string{}, TocFile: "test", }, }, { description: "all items set", input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|dir/subdir/hdr.h|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc", input: "out1, out2" + "|object1, object2" + "|shared_lib1, shared_lib2" + "|static_lib1, static_lib2" + "|., dir/subdir" + "|system/dir, system/other/dir" + "|dir/subdir/hdr.h" + "|rootstaticarchive1" + "|rootdynamiclibrary1" + "|lib.so.toc", expectedOutput: CcInfo{ OutputFiles: []string{"out1", "out2"}, CcObjectFiles: []string{"object1", "object2"}, CcSharedLibraryFiles: []string{"shared_lib1", "shared_lib2"}, CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"}, Includes: []string{".", "dir/subdir"}, SystemIncludes: []string{"system/dir", "system/other/dir"}, Loading @@ -118,22 +148,22 @@ func TestGetCcInfoParseResults(t *testing.T) { description: "too few result splits", input: "|", expectedOutput: CcInfo{}, expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, []string{"", ""}), expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, []string{"", ""}), }, { description: "too many result splits", input: strings.Repeat("|", 50), input: strings.Repeat("|", expectedSplits+1), // 2 too many expectedOutput: CcInfo{}, expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, make([]string, 51)), expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, make([]string, expectedSplits+2)), }, } for _, tc := range testCases { actualOutput, err := GetCcInfo.ParseResult(tc.input) if (err == nil && tc.expectedErrorMessage != "") || (err != nil && err.Error() != tc.expectedErrorMessage) { t.Errorf("%q: expected Error %s, got %s", tc.description, tc.expectedErrorMessage, err) t.Errorf("%q:\nexpected Error %s\n, got %s", tc.description, tc.expectedErrorMessage, err) } else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) { t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput) t.Errorf("%q:\n expected %#v\n!= actual %#v", tc.description, tc.expectedOutput, actualOutput) } } }
cc/androidmk.go +1 −1 Original line number Diff line number Diff line Loading @@ -241,7 +241,7 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries entries.Class = "SHARED_LIBRARIES" entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { entries.SetString("LOCAL_SOONG_TOC", library.toc().String()) if !library.buildStubs() { if !library.buildStubs() && library.unstrippedOutputFile != nil { entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", library.unstrippedOutputFile.String()) } if len(library.Properties.Overrides) > 0 { Loading
cc/prebuilt.go +64 −0 Original line number Diff line number Diff line Loading @@ -298,6 +298,7 @@ func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libr module, library := NewPrebuiltLibrary(hod, "srcs") library.BuildOnlyShared() module.bazelable = true module.bazelHandler = &prebuiltSharedLibraryBazelHandler{module: module, library: library} // Prebuilt shared libraries can be included in APEXes android.InitApexModule(module) Loading Loading @@ -426,6 +427,69 @@ func (h *prebuiltStaticLibraryBazelHandler) GenerateBazelBuildActions(ctx androi return true } type prebuiltSharedLibraryBazelHandler struct { android.BazelHandler module *Module library *libraryDecorator } func (h *prebuiltSharedLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool { bazelCtx := ctx.Config().BazelContext ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx)) if err != nil { ctx.ModuleErrorf("Error getting Bazel CcInfo for %s: %s", label, err) } if !ok { return false } sharedLibs := ccInfo.CcSharedLibraryFiles if len(sharedLibs) != 1 { ctx.ModuleErrorf("expected 1 shared library from bazel target %s, got %q", label, sharedLibs) return false } // TODO(b/184543518): cc_prebuilt_library_shared may have properties for re-exporting flags // TODO(eakammer):Add stub-related flags if this library is a stub library. // h.library.exportVersioningMacroIfNeeded(ctx) // Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise // validation will fail. For now, set this to an empty list. // TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation. h.library.collectedSnapshotHeaders = android.Paths{} if len(sharedLibs) == 0 { h.module.outputFile = android.OptionalPath{} return true } out := android.PathForBazelOut(ctx, sharedLibs[0]) h.module.outputFile = android.OptionalPathForPath(out) // FIXME(b/214600441): We don't yet strip prebuilt shared libraries h.library.unstrippedOutputFile = out var toc android.Path if len(ccInfo.TocFile) > 0 { toc = android.PathForBazelOut(ctx, ccInfo.TocFile) } else { toc = out // Just reuse `out` so ninja still gets an input but won't matter } info := SharedLibraryInfo{ SharedLibrary: out, TableOfContents: android.OptionalPathForPath(toc), Target: ctx.Target(), } ctx.SetProvider(SharedLibraryInfoProvider, info) h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo) h.module.maybeUnhideFromMake() return true } func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt { return &p.Prebuilt } Loading
cc/prebuilt_test.go +72 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ import ( "testing" "android/soong/android" "android/soong/bazel/cquery" "github.com/google/blueprint" ) Loading Loading @@ -378,3 +378,74 @@ func TestPrebuiltLibrarySanitized(t *testing.T) { static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module) assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a") } func TestPrebuiltLibrarySharedWithBazelWithoutToc(t *testing.T) { const bp = ` cc_prebuilt_library_shared { name: "foo", srcs: ["foo.so"], bazel_module: { label: "//foo/bar:bar" }, }` outBaseDir := "outputbase" config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) config.BazelContext = android.MockBazelContext{ OutputBaseDir: outBaseDir, LabelToCcInfo: map[string]cquery.CcInfo{ "//foo/bar:bar": cquery.CcInfo{ CcSharedLibraryFiles: []string{"foo.so"}, }, }, } ctx := testCcWithConfig(t, config) sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() pathPrefix := outBaseDir + "/execroot/__main__/" info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo) android.AssertPathRelativeToTopEquals(t, "prebuilt shared library", pathPrefix+"foo.so", info.SharedLibrary) android.AssertPathRelativeToTopEquals(t, "prebuilt's 'nullary' ToC", pathPrefix+"foo.so", info.TableOfContents.Path()) outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("") if err != nil { t.Errorf("Unexpected error getting cc_object outputfiles %s", err) } expectedOutputFiles := []string{pathPrefix + "foo.so"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) } func TestPrebuiltLibrarySharedWithBazelWithToc(t *testing.T) { const bp = ` cc_prebuilt_library_shared { name: "foo", srcs: ["foo.so"], bazel_module: { label: "//foo/bar:bar" }, }` outBaseDir := "outputbase" config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) config.BazelContext = android.MockBazelContext{ OutputBaseDir: outBaseDir, LabelToCcInfo: map[string]cquery.CcInfo{ "//foo/bar:bar": cquery.CcInfo{ CcSharedLibraryFiles: []string{"foo.so"}, TocFile: "toc", }, }, } ctx := testCcWithConfig(t, config) sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() pathPrefix := outBaseDir + "/execroot/__main__/" info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo) android.AssertPathRelativeToTopEquals(t, "prebuilt shared library's ToC", pathPrefix+"toc", info.TableOfContents.Path()) android.AssertPathRelativeToTopEquals(t, "prebuilt shared library", pathPrefix+"foo.so", info.SharedLibrary) outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("") if err != nil { t.Errorf("Unexpected error getting cc_object outputfiles %s", err) } expectedOutputFiles := []string{pathPrefix + "foo.so"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) }