blob: 9386e66da3cea2600a73c19a1a5a8e519a988ed6 [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 json
import os
import sys
import ninja_tools
import ninja_syntax # Has to be after ninja_tools because of the path hack
def final_packaging(context, inner_trees):
"""Pull together all of the previously defined rules into the final build stems."""
with open(context.out.outer_ninja_file(), "w",
encoding='iso-8859-1') as ninja_file:
ninja = ninja_tools.Ninja(context, ninja_file)
# Add the api surfaces file
ninja.add_subninja(
ninja_syntax.Subninja(
context.out.api_ninja_file(base=context.out.Base.OUTER)))
# For each inner tree
for tree in inner_trees.keys():
# TODO: Verify that inner_tree.ninja was generated
# Read and verify file
build_targets = read_build_targets_json(context, tree)
if not build_targets:
continue
# Generate the ninja and build files for this inner tree
generate_cross_domain_build_rules(context, ninja, tree,
build_targets)
# Finish writing the ninja file
ninja.write()
def read_build_targets_json(context, tree):
"""Read and validate the build_targets.json file for the given tree."""
try:
f = open(tree.out.build_targets_file(), encoding='iso-8859-1')
except FileNotFoundError:
# It's allowed not to have any artifacts (e.g. if a tree is a light tree with only APIs)
return None
data = None
with f:
try:
data = json.load(f)
except json.decoder.JSONDecodeError as ex:
sys.stderr.write("Error parsing file: %s\n" %
tree.out.build_targets_file())
# TODO: Error reporting
raise ex
# TODO: Better error handling
# TODO: Validate json schema
return data
def generate_cross_domain_build_rules(context, ninja, tree, build_targets):
"Generate the ninja and build files for the inner tree."
# Include the inner tree's inner_tree.ninja
ninja.add_subninja(
ninja_syntax.Subninja(
tree.out.main_ninja_file(base=tree.out.Base.OUTER),
chdir=tree.root,
env_vars=tree.env_used))
# Generate module rules and files
for module in build_targets.get("modules", []):
generate_shared_module(context, ninja, tree, module)
# Generate staging rules
staging_dir = context.out.staging_dir(base=context.out.Base.OUTER)
for staged in build_targets.get("staging", []):
# TODO: Enforce that dest isn't in disallowed subdir of out or absolute
dest = staged["dest"]
dest = os.path.join(staging_dir, dest)
if "src" in staged and "obj" in staged:
context.errors.error(
"Can't have both \"src\" and \"obj\" tags in \"staging\" entry."
) # TODO: Filename and line if possible
if "src" in staged:
ninja.add_copy_file(dest, os.path.join(tree.root, staged["src"]))
elif "obj" in staged:
ninja.add_copy_file(
dest,
os.path.join(tree.out.root(base=tree.out.Base.OUTER),
staged["obj"]))
ninja.add_global_phony("staging", [dest])
# Generate dist rules
dist_dir = context.out.dist_dir(base=context.out.Base.OUTER)
for disted in build_targets.get("dist", []):
# TODO: Enforce that dest absolute
dest = disted["dest"]
dest = os.path.join(dist_dir, dest)
ninja.add_copy_file(dest, os.path.join(tree.root, disted["src"]))
ninja.add_global_phony("dist", [dest])
def generate_shared_module(context, ninja, tree, module):
"""Generate ninja rules for the given build_targets.json defined module."""
module_name = module["name"]
module_type = module["type"]
share_dir = context.out.module_share_dir(module_type,
module_name,
base=context.out.Base.OUTER)
src_file = os.path.join(tree.root, module["file"])
if module_type == "apex":
ninja.add_copy_file(os.path.join(share_dir, module_name + ".apex"),
src_file)
# TODO: Generate build file
else:
# TODO: Better error handling
raise Exception("Invalid module type: %s" % module)