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 compiling and linking cc artifacts.""" 18 19from ninja_tools import Ninja 20from ninja_syntax import BuildAction, Rule 21 22from functools import lru_cache 23from typing import List 24 25class CompileContext(): 26 27 def __init__(self, src: str, flags:str, out: str, frontend: str): 28 self.src = src 29 self.flags = flags 30 self.out = out 31 self.frontend = frontend 32 33class Compiler(): 34 35 @lru_cache(maxsize=None) 36 def _create_compile_rule(self, ninja: Ninja) -> Rule: 37 rule = Rule("cc") 38 rule.add_variable("description", "compile source to object file using clang/clang++") 39 rule.add_variable("command", "${cFrontend} -c ${cFlags} -o ${out} ${in}") 40 ninja.add_rule(rule) 41 return rule 42 43 def compile(self, ninja: Ninja, compile_context: CompileContext) -> None: 44 compile_rule = self._create_compile_rule(ninja) 45 46 compile_action = BuildAction(output=compile_context.out, 47 inputs=compile_context.src, 48 rule=compile_rule.name, 49 implicits=[compile_context.frontend] 50 ) 51 compile_action.add_variable("cFrontend", compile_context.frontend) 52 compile_action.add_variable("cFlags", compile_context.flags) 53 ninja.add_build_action(compile_action) 54 55class LinkContext(): 56 57 def __init__(self, objs: List[str], flags: str, out: str, frontend: str): 58 self.objs = objs 59 self.flags = flags 60 self.out = out 61 self.frontend = frontend 62 self.implicits = [frontend] 63 64 def add_implicits(self, implicits: List[str]): 65 self.implicits.extend(implicits) 66 67class Linker(): 68 69 @lru_cache(maxsize=None) 70 def _create_link_rule(self, ninja: Ninja) -> Rule: 71 rule = Rule("ld") 72 rule.add_variable("description", "link object files using clang/clang++") 73 rule.add_variable("command", "${ldFrontend} ${ldFlags} -o ${out} ${in}") 74 ninja.add_rule(rule) 75 return rule 76 77 def link(self, ninja: Ninja, link_context: LinkContext) -> None: 78 link_rule = self._create_link_rule(ninja) 79 80 link_action = BuildAction(output=link_context.out, 81 inputs=link_context.objs, 82 rule=link_rule.name, 83 implicits=link_context.implicits, 84 ) 85 link_action.add_variable("ldFrontend", link_context.frontend) 86 link_action.add_variable("ldFlags", link_context.flags) 87 ninja.add_build_action(link_action) 88