1#!/usr/bin/python3 2# 3# Copyright (C) 2022 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""A module for writing ninja rules that generate C stubs.""" 18 19import os 20 21from typing import NamedTuple 22 23from ninja_tools import Ninja 24from ninja_syntax import Variable, Rule, BuildAction 25 26# This is the path relative to outer tree root 27NDKSTUBGEN = "orchestrator/build/orchestrator/core/cc/ndkstubgen_runner.sh" 28 29class GenCcStubsInput: 30 31 def __init__(self, arch: str, version: str, api: str, version_map: str, additional_args=""): 32 self.arch = arch # target device arch (e.g. x86) 33 self.version = version # numeric API level (e.g. 33) 34 self.version_map = version_map # path to API level map (e.g. Q-->29) 35 self.api = api # path to map.txt 36 self.additional_args = additional_args # additional args to ndkstubgen (e.g. --llndk) 37 38class GenCcStubsOutput(NamedTuple): 39 stub: str 40 version_script: str 41 symbol_list: str 42 43class StubGenerator: 44 45 def __init__(self): 46 self._stubgen_rule = None 47 48 def _add_stubgen_rule(self, ninja: Ninja): 49 """This adds a ninja rule to run ndkstubgen 50 51 Running ndkstubgen creates C stubs from API .map.txt files 52 """ 53 # Create a variable name for the binary. 54 ninja.add_variable(Variable("ndkstubgen", NDKSTUBGEN)) 55 56 # Add a rule to the ninja file. 57 rule = Rule("genCcStubsRule") 58 rule.add_variable( 59 "description", 60 "Generate stub .c files from .map.txt API description files") 61 rule.add_variable( 62 "command", 63 "${ndkstubgen} --arch ${arch} --api ${apiLevel} --api-map ${apiMap} ${additionalArgs} ${in} ${out}" 64 ) 65 ninja.add_rule(rule) 66 self._stubgen_rule = rule 67 68 def add_stubgen_action(self, ninja: Ninja, stub_input: GenCcStubsInput, 69 work_dir: str) -> GenCcStubsOutput: 70 """This adds a ninja build action to generate stubs using `genCcStubsRule`""" 71 # Add stubgen rule if it has not been added yet. 72 if not self._stubgen_rule: 73 self._add_stubgen_rule(ninja) 74 75 outputs = GenCcStubsOutput( 76 stub=os.path.join(work_dir, stub_input.arch, "stub.c"), 77 version_script=os.path.join(work_dir, stub_input.arch, "stub.map"), 78 symbol_list=os.path.join(work_dir, stub_input.arch, 79 "abi_symbol_list.txt") 80 ) 81 82 # Create the ninja build action. 83 stubgen_action = BuildAction( 84 output=list(outputs), 85 inputs=stub_input.api, 86 rule=self._stubgen_rule.name, 87 implicits=[ 88 NDKSTUBGEN, 89 stub_input.version_map, 90 ], 91 ) 92 stubgen_action.add_variable("arch", stub_input.arch) 93 stubgen_action.add_variable("apiLevel", stub_input.version) 94 stubgen_action.add_variable("apiMap", stub_input.version_map) 95 stubgen_action.add_variable("additionalArgs", 96 stub_input.additional_args) 97 98 # Add the build action to the ninja file. 99 ninja.add_build_action(stubgen_action) 100 return outputs 101