| #!/usr/bin/python3 |
| # |
| # Copyright (C) 2022 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| from functools import lru_cache |
| import os |
| |
| from build_file_generator import AndroidBpFile, AndroidBpModule, BuildFileGenerator, ConfigAxis |
| from utils import ASSEMBLE_PHONY_TARGET, Context |
| |
| |
| class JavaApiAssemblyContext(object): |
| """Context object for managing global state of Java API Assembly.""" |
| |
| def get_java_api_assembler(self): |
| """Return a callback to assemble Java APIs. |
| |
| The callback is a member of the context object, |
| and therefore has access to its state.""" |
| return self.assemble_java_api_library |
| |
| @lru_cache(maxsize=None) |
| def _java_api_library_module(self, context: Context, |
| build_file_generator: BuildFileGenerator, |
| surface_name: str, |
| surface_version: str) -> AndroidBpModule: |
| """Initializes the java_api_library AndroidBpModule for an API surface stub |
| |
| Args: |
| context: Container for global state. |
| build_file_generator: Container for registering Android.bp files. |
| surface_name: API surface name (e.g. publicapi). |
| surface_version: API surface version (e.g. 29, 30, current). |
| |
| Returns: |
| AndroidBpModule object |
| """ |
| # Create Android.bp module. |
| # There should be one stub library per (api_surface, version). |
| name = f"{surface_name}_{surface_version}" |
| api_library_module = AndroidBpModule(name=name, |
| module_type="java_api_library") |
| staging_dir = context.out.api_library_dir(surface_name, |
| surface_version, "") |
| # Create Android.bp file |
| bp_file = AndroidBpFile(directory=staging_dir) |
| bp_file.add_comment_string("WARNING: THIS IS AN AUTOGENERATED FILE.") |
| bp_file.add_module(api_library_module) |
| build_file_generator.add_android_bp_file(bp_file) |
| |
| return api_library_module |
| |
| def assemble_java_api_library(self, context: Context, ninja, |
| build_file_generator: BuildFileGenerator, |
| stub_library) -> None: |
| """Assembles the API .txt files in the output directory. |
| |
| Args: |
| context: Container for global state. |
| ninja: Ninja writer object. ninja_tools.Ninja instance. |
| build_file_generator: Container for registering Android.bp files. |
| stub_library: Container for APIs provided by a library an API surface |
| at a specific version. api_assembly.StubLibrary instance. |
| Returns: |
| None |
| """ |
| staging_dir = context.out.api_library_dir( |
| stub_library.api_surface, |
| stub_library.api_surface_version, |
| "", |
| ) |
| # Create one java_api_library for the api surface. This should be |
| # idempotent. |
| api_library_module = self._java_api_library_module( |
| context, build_file_generator, stub_library.api_surface, |
| stub_library.api_surface_version) |
| |
| api_deps = [] |
| for c in stub_library.contributions: |
| # (A single API domain can provide multiple java libraries) |
| # Proposed layout |
| # out/api_surfaces/ |
| # publicapi/current/ |
| # <contribution1>/current.txt |
| # <contribution2>/current.txt |
| # ... |
| # systemapi/current/ |
| # <contribution1>/current.txt |
| # <contribution1>/system-current.txt |
| # <contribution2>/current.txt |
| # <contribution2>/system-current.txt |
| # ... |
| name = c.library_contribution["name"] |
| api = c.library_contribution["api"] |
| api_out = os.path.join(staging_dir, name, os.path.basename(api)) |
| ninja.add_copy_file(api_out, os.path.join( |
| c.inner_tree.root, |
| api, |
| )) |
| |
| # TODO: Short term hack to make the files in outer tree available to files |
| # in inner tree. This is needed because chdir'd trees cannot reach |
| # into outer tree's scope. |
| # The list of inner trees is hardcoded for now. |
| for inner_tree in ["system", "vendor", "apexes"]: |
| path_in_inner_tree = api_out.replace( |
| context.out.api_surfaces_dir(), |
| os.path.join(inner_tree, context.out.root(), |
| "api_surfaces")) |
| ninja.add_phony(path_in_inner_tree, api_out) |
| |
| # Add the api file to java_api_library |
| api_library_module.extend_property( |
| prop="api_files", |
| val=[os.path.join(name, os.path.basename(api))]) |
| api_deps.append(api_out) |
| |
| # Add the api files as deps of the phony assembly target |
| ninja.add_global_phony(ASSEMBLE_PHONY_TARGET, api_deps) |