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