blob: 4abdd9e919f427e1f33a9f58eeb43f6f2394a13c [file] [log] [blame]
# 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.
import collections
import os
import sys
# Workaround for python include path
# TODO: restructure things so that we do not need this.
# pylint: disable=wrong-import-position,import-error
_ninja_dir = os.path.realpath(
os.path.join(os.path.dirname(__file__), "..", "ninja"))
if _ninja_dir not in sys.path:
sys.path.append(_ninja_dir)
import ninja_writer
from ninja_syntax import BuildAction, Rule
# pylint: enable=wrong-import-position,import-error
class Ninja(ninja_writer.Writer):
"""Some higher level constructs on top of raw ninja writing.
TODO: Not sure where these should be.
"""
def __init__(self, context, file, **kwargs):
super().__init__(
file,
builddir=context.out.root(base=context.out.Base.OUTER),
**kwargs)
self._context = context
self._did_copy_file = False
self._write_rule = None
self._phonies = collections.defaultdict(set)
self._acp = self._context.tools.acp()
def add_copy_file(self, copy_to, copy_from):
self.add_rule(
Rule("copy_file", [
("command",
f"mkdir -p ${{out_dir}} && {self._acp} -f ${{in}} ${{out}}")
]))
self.add_build_action(
BuildAction(output=copy_to,
rule="copy_file",
inputs=[copy_from],
implicits=[self._acp],
variables=[("out_dir", os.path.dirname(copy_to))]))
def add_global_phony(self, name, deps):
"""Add a global phony target.
This should be used when there are multiple places that will want to add
to the same phony, with possibly different dependencies. The resulting
dependency list will be the combined dependency list.
If you can, to save memory, use add_phony instead of this function.
"""
assert isinstance(deps, (set, list, tuple)), f"bad type: {type(deps)}"
self._phonies[name] |= set(deps)
def write(self, *args, **kwargs):
"""Write the file, including our global phonies."""
for phony, deps in self._phonies.items():
self.add_phony(phony, deps)
super().write(*args, **kwargs)
def add_write_file(self, filepath: str, content: str):
"""Writes the content as a string to filepath
The content is written as-is, special characters are not escaped
"""
self.add_rule(
Rule("write_file", [("description", "Writes content to out"),
("command", "printf '${content}' > ${out}")]))
self.add_build_action(
BuildAction(output=filepath,
rule="write_file",
variables=[("content", content)]))