diff --git a/android/bazel_handler.go b/android/bazel_handler.go index 5ac69240a..28c0e5307 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -69,6 +69,10 @@ type BazelContext interface { // Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order). GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) + // GetPrebuiltCcStaticLibraryFiles returns paths to prebuilt cc static libraries, and whether the + // results were available + GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) + // ** End cquery methods // Issues commands to Bazel to receive results for all cquery requests @@ -126,6 +130,11 @@ func (m MockBazelContext) GetOutputFilesAndCcObjectFiles(label string, archType return result, result, ok } +func (m MockBazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) { + result, ok := m.AllFiles[label] + return result, ok +} + func (m MockBazelContext) InvokeBazel() error { panic("unimplemented") } @@ -169,6 +178,19 @@ func (bazelCtx *bazelContext) GetOutputFilesAndCcObjectFiles(label string, archT return outputFiles, ccObjects, ok } +// GetPrebuiltCcStaticLibraryFiles returns a slice of prebuilt static libraries for the given +// label/archType if there are query results; otherwise, it enqueues the query and returns false. +func (bazelCtx *bazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) { + result, ok := bazelCtx.cquery(label, cquery.GetPrebuiltCcStaticLibraryFiles, archType) + if !ok { + return nil, false + } + + bazelOutput := strings.TrimSpace(result) + ret := cquery.GetPrebuiltCcStaticLibraryFiles.ParseResult(bazelOutput) + return ret, ok +} + func (n noopBazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) { panic("unimplemented") } @@ -177,6 +199,10 @@ func (n noopBazelContext) GetOutputFilesAndCcObjectFiles(label string, archType panic("unimplemented") } +func (n noopBazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) { + panic("unimplemented") +} + func (n noopBazelContext) InvokeBazel() error { panic("unimplemented") } diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go index 4a64c510b..b88da2f75 100644 --- a/bazel/cquery/request_type.go +++ b/bazel/cquery/request_type.go @@ -5,8 +5,9 @@ import ( ) var ( - GetOutputFiles = &getOutputFilesRequestType{} - GetOutputFilesAndCcObjectFiles = &getOutputFilesAndCcObjectFilesType{} + GetOutputFiles = &getOutputFilesRequestType{} + GetOutputFilesAndCcObjectFiles = &getOutputFilesAndCcObjectFilesType{} + GetPrebuiltCcStaticLibraryFiles = &getPrebuiltCcStaticLibraryFiles{} ) type GetOutputFilesAndCcObjectFiles_Result struct { @@ -86,6 +87,34 @@ func (g getOutputFilesAndCcObjectFilesType) ParseResult(rawString string) GetOut return GetOutputFilesAndCcObjectFiles_Result{outputFiles, ccObjects} } +type getPrebuiltCcStaticLibraryFiles struct{} + +// Name returns the name of the starlark function to get prebuilt cc static library files +func (g getPrebuiltCcStaticLibraryFiles) Name() string { + return "getPrebuiltCcStaticLibraryFiles" +} + +// StarlarkFunctionBody returns the unindented body of a starlark function for extracting the static +// library paths from a cc_import module. +func (g getPrebuiltCcStaticLibraryFiles) StarlarkFunctionBody() string { + return ` +linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list() + +static_libraries = [] +for linker_input in linker_inputs: + for library in linker_input.libraries: + static_libraries.append(library.static_library.path) + +return ', '.join(static_libraries)` +} + +// ParseResult returns a slice of bazel output paths to static libraries if any exist for the given +// rawString corresponding to the string output which was created by evaluating the +// StarlarkFunctionBody. +func (g getPrebuiltCcStaticLibraryFiles) ParseResult(rawString string) []string { + return strings.Split(rawString, ", ") +} + // 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 { diff --git a/cc/prebuilt.go b/cc/prebuilt.go index 6b9a3d529..3829b1e73 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -305,6 +305,7 @@ func PrebuiltStaticLibraryFactory() android.Module { func NewPrebuiltStaticLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { module, library := NewPrebuiltLibrary(hod) library.BuildOnlyStatic() + module.bazelHandler = &prebuiltStaticLibraryBazelHandler{module: module, library: library} return module, library } @@ -319,6 +320,52 @@ type prebuiltObjectLinker struct { properties prebuiltObjectProperties } +type prebuiltStaticLibraryBazelHandler struct { + bazelHandler + + module *Module + library *libraryDecorator +} + +func (h *prebuiltStaticLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool { + bazelCtx := ctx.Config().BazelContext + staticLibs, ok := bazelCtx.GetPrebuiltCcStaticLibraryFiles(label, ctx.Arch().ArchType) + if !ok { + return false + } + if len(staticLibs) > 1 { + ctx.ModuleErrorf("expected 1 static library from bazel target %q, got %s", label, staticLibs) + return false + } + + // TODO(b/184543518): cc_prebuilt_library_static 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(staticLibs) == 0 { + h.module.outputFile = android.OptionalPath{} + return true + } + + out := android.PathForBazelOut(ctx, staticLibs[0]) + h.module.outputFile = android.OptionalPathForPath(out) + + depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(out).Build() + ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ + StaticLibrary: out, + + TransitiveStaticLibrariesForOrdering: depSet, + }) + + return true +} + func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt { return &p.Prebuilt }