This reduces the scope of the demo to just building and installing a single .so, but it makes the demo actually build that single .so. Next up, writing some unit tests and fleshing out functionality. Test: see the README Change-Id: I560904b786fbf69d3a83dbb08d496dba5a3192ca
118 lines
4.3 KiB
Python
118 lines
4.3 KiB
Python
#
|
|
# 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") 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(), chDir=None))
|
|
|
|
# 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())
|
|
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(), chDir=tree.root))
|
|
|
|
# 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()
|
|
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(), staged["obj"]))
|
|
ninja.add_global_phony("staging", [dest])
|
|
|
|
# Generate dist rules
|
|
dist_dir = context.out.dist_dir()
|
|
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)
|
|
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)
|