| package cquery |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| "strings" |
| ) |
| |
| var ( |
| GetOutputFiles = &getOutputFilesRequestType{} |
| GetPythonBinary = &getPythonBinaryRequestType{} |
| GetCcInfo = &getCcInfoType{} |
| GetApexInfo = &getApexInfoType{} |
| GetCcUnstrippedInfo = &getCcUnstippedInfoType{} |
| ) |
| |
| type CcInfo struct { |
| OutputFiles []string |
| CcObjectFiles []string |
| CcSharedLibraryFiles []string |
| CcStaticLibraryFiles []string |
| Includes []string |
| SystemIncludes []string |
| Headers []string |
| // Archives owned by the current target (not by its dependencies). These will |
| // be a subset of OutputFiles. (or static libraries, this will be equal to OutputFiles, |
| // but general cc_library will also have dynamic libraries in output files). |
| RootStaticArchives []string |
| // Dynamic libraries (.so files) created by the current target. These will |
| // 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 |
| TidyFiles []string |
| TocFile string |
| UnstrippedOutput string |
| } |
| |
| type getOutputFilesRequestType struct{} |
| |
| type getPythonBinaryRequestType struct{} |
| |
| // Name returns a string name for this request type. Such request type names must be unique, |
| // and must only consist of alphanumeric characters. |
| func (g getOutputFilesRequestType) Name() string { |
| return "getOutputFiles" |
| } |
| |
| // StarlarkFunctionBody returns a starlark function body to process this request type. |
| // The returned string is the body of a Starlark function which obtains |
| // all request-relevant information about a target and returns a string containing |
| // this information. |
| // The function should have the following properties: |
| // - `target` is the only parameter to this function (a configured target). |
| // - The return value must be a string. |
| // - The function body should not be indented outside of its own scope. |
| func (g getOutputFilesRequestType) StarlarkFunctionBody() string { |
| return "return ', '.join([f.path for f in target.files.to_list()])" |
| } |
| |
| // 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 getOutputFilesRequestType) ParseResult(rawString string) []string { |
| return splitOrEmpty(rawString, ", ") |
| } |
| |
| // Name returns a string name for this request type. Such request type names must be unique, |
| // and must only consist of alphanumeric characters. |
| func (g getPythonBinaryRequestType) Name() string { |
| return "getPythonBinary" |
| } |
| |
| // StarlarkFunctionBody returns a starlark function body to process this request type. |
| // The returned string is the body of a Starlark function which obtains |
| // all request-relevant information about a target and returns a string containing |
| // this information. |
| // The function should have the following properties: |
| // - `target` is the only parameter to this function (a configured target). |
| // - The return value must be a string. |
| // - The function body should not be indented outside of its own scope. |
| func (g getPythonBinaryRequestType) StarlarkFunctionBody() string { |
| return "return providers(target)['FilesToRunProvider'].executable.path" |
| } |
| |
| // 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 getPythonBinaryRequestType) ParseResult(rawString string) string { |
| return rawString |
| } |
| |
| type getCcInfoType struct{} |
| |
| // Name returns a string name for this request type. Such request type names must be unique, |
| // and must only consist of alphanumeric characters. |
| func (g getCcInfoType) Name() string { |
| return "getCcInfo" |
| } |
| |
| // StarlarkFunctionBody returns a starlark function body to process this request type. |
| // The returned string is the body of a Starlark function which obtains |
| // all request-relevant information about a target and returns a string containing |
| // this information. |
| // The function should have the following properties: |
| // - `target` is the only parameter to this function (a configured target). |
| // - The return value must be a string. |
| // - The function body should not be indented outside of its own scope. |
| func (g getCcInfoType) StarlarkFunctionBody() string { |
| return ` |
| outputFiles = [f.path for f in target.files.to_list()] |
| cc_info = providers(target)["CcInfo"] |
| |
| includes = cc_info.compilation_context.includes.to_list() |
| system_includes = cc_info.compilation_context.system_includes.to_list() |
| headers = [f.path for f in cc_info.compilation_context.headers.to_list()] |
| |
| ccObjectFiles = [] |
| staticLibraries = [] |
| rootStaticArchives = [] |
| linker_inputs = cc_info.linking_context.linker_inputs.to_list() |
| |
| static_info_tag = "//build/bazel/rules/cc:cc_library_static.bzl%CcStaticLibraryInfo" |
| if static_info_tag in providers(target): |
| static_info = providers(target)[static_info_tag] |
| ccObjectFiles = [f.path for f in static_info.objects] |
| rootStaticArchives = [static_info.root_static_archive.path] |
| else: |
| for linker_input in linker_inputs: |
| for library in linker_input.libraries: |
| for object in library.objects: |
| ccObjectFiles += [object.path] |
| if library.static_library: |
| staticLibraries.append(library.static_library.path) |
| if linker_input.owner == target.label: |
| rootStaticArchives.append(library.static_library.path) |
| |
| 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: |
| 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/cc: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 |
| |
| tidy_files = [] |
| p = providers(target) |
| clang_tidy_info = p.get("//build/bazel/rules/cc:clang_tidy.bzl%ClangTidyInfo") |
| if clang_tidy_info: |
| tidy_files = [v.path for v in clang_tidy_info.tidy_files.to_list()] |
| |
| return json_encode({ |
| "OutputFiles": outputFiles, |
| "CcObjectFiles": ccObjectFiles, |
| "CcSharedLibraryFiles": sharedLibraries, |
| "CcStaticLibraryFiles": staticLibraries, |
| "Includes": includes, |
| "SystemIncludes": system_includes, |
| "Headers": headers, |
| "RootStaticArchives": rootStaticArchives, |
| "RootDynamicLibraries": rootSharedLibraries, |
| "TidyFiles": tidy_files, |
| "TocFile": toc_file, |
| "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 getCcInfoType) ParseResult(rawString string) (CcInfo, error) { |
| var ccInfo CcInfo |
| if err := parseJson(rawString, &ccInfo); err != nil { |
| return ccInfo, err |
| } |
| return ccInfo, nil |
| } |
| |
| // Query Bazel for the artifacts generated by the apex modules. |
| type getApexInfoType struct{} |
| |
| // Name returns a string name for this request type. Such request type names must be unique, |
| // and must only consist of alphanumeric characters. |
| func (g getApexInfoType) Name() string { |
| return "getApexInfo" |
| } |
| |
| // StarlarkFunctionBody returns a starlark function body to process this request type. |
| // The returned string is the body of a Starlark function which obtains |
| // all request-relevant information about a target and returns a string containing |
| // this information. The function should have the following properties: |
| // - `target` is the only parameter to this function (a configured target). |
| // - The return value must be a string. |
| // - The function body should not be indented outside of its own scope. |
| func (g getApexInfoType) StarlarkFunctionBody() string { |
| return `info = providers(target)["//build/bazel/rules/apex:apex.bzl%ApexInfo"] |
| bundle_key_info = info.bundle_key_info |
| container_key_info = info.container_key_info |
| return json_encode({ |
| "signed_output": info.signed_output.path, |
| "unsigned_output": info.unsigned_output.path, |
| "provides_native_libs": [str(lib) for lib in info.provides_native_libs], |
| "requires_native_libs": [str(lib) for lib in info.requires_native_libs], |
| "bundle_key_info": [bundle_key_info.public_key.path, bundle_key_info.private_key.path], |
| "container_key_info": [container_key_info.pem.path, container_key_info.pk8.path, container_key_info.key_name], |
| "package_name": info.package_name, |
| "symbols_used_by_apex": info.symbols_used_by_apex.path, |
| "java_symbols_used_by_apex": info.java_symbols_used_by_apex.path, |
| "backing_libs": info.backing_libs.path, |
| "bundle_file": info.base_with_config_zip.path, |
| "installed_files": info.installed_files.path, |
| })` |
| } |
| |
| type ApexInfo struct { |
| SignedOutput string `json:"signed_output"` |
| UnsignedOutput string `json:"unsigned_output"` |
| ProvidesLibs []string `json:"provides_native_libs"` |
| RequiresLibs []string `json:"requires_native_libs"` |
| BundleKeyInfo []string `json:"bundle_key_info"` |
| ContainerKeyInfo []string `json:"container_key_info"` |
| PackageName string `json:"package_name"` |
| SymbolsUsedByApex string `json:"symbols_used_by_apex"` |
| JavaSymbolsUsedByApex string `json:"java_symbols_used_by_apex"` |
| BackingLibs string `json:"backing_libs"` |
| BundleFile string `json:"bundle_file"` |
| InstalledFiles string `json:"installed_files"` |
| } |
| |
| // 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 getApexInfoType) ParseResult(rawString string) (ApexInfo, error) { |
| var info ApexInfo |
| err := parseJson(rawString, &info) |
| return info, err |
| } |
| |
| // 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, error) { |
| var info CcUnstrippedInfo |
| err := parseJson(rawString, &info) |
| return info, err |
| } |
| |
| 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 { |
| if len(s) < 1 { |
| return []string{} |
| } else { |
| return strings.Split(s, sep) |
| } |
| } |
| |
| // parseJson decodes json string into the fields of the receiver. |
| // Unknown attribute name causes panic. |
| func parseJson(jsonString string, info interface{}) error { |
| decoder := json.NewDecoder(strings.NewReader(jsonString)) |
| decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests |
| err := decoder.Decode(info) |
| if err != nil { |
| return fmt.Errorf("cannot parse cquery result '%s': %s", jsonString, err) |
| } |
| return nil |
| } |