You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
6.8 KiB
213 lines
6.8 KiB
# Copyright 2020 Google LLC
|
|
#
|
|
# 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
|
|
#
|
|
# https://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.
|
|
"""Builds an Android target in a secure sandbox."""
|
|
|
|
import argparse
|
|
import os
|
|
from . import config
|
|
from . import nsjail
|
|
from . import rbe
|
|
|
|
_DEFAULT_COMMAND_WRAPPER = \
|
|
'/src/tools/treble/build/sandbox/build_android_target.sh'
|
|
|
|
|
|
def build(build_target, variant, nsjail_bin, chroot, dist_dir, build_id,
|
|
max_cpus, build_goals, config_file=None,
|
|
command_wrapper=_DEFAULT_COMMAND_WRAPPER, use_rbe=False,
|
|
readonly_bind_mount=None, env=[]):
|
|
"""Builds an Android target in a secure sandbox.
|
|
|
|
Args:
|
|
build_target: A string with the name of the build target.
|
|
variant: A string with the build variant.
|
|
nsjail_bin: A string with the path to the nsjail binary.
|
|
chroot: A string with the path to the chroot of the NsJail sandbox.
|
|
dist_dir: A string with the path to the Android dist directory.
|
|
build_id: A string with the Android build identifier.
|
|
max_cpus: An integer with maximum number of CPUs.
|
|
build_goals: A list of strings with the goals and options to provide to the
|
|
build command.
|
|
config_file: A string path to an overlay configuration file.
|
|
command_wrapper: A string path to the command wrapper.
|
|
use_rbe: If true, will attempt to use RBE for the build.
|
|
readonly_bind_mount: A string path to a path to be mounted as read-only.
|
|
env: An array of environment variables to define in the NsJail sandbox in the
|
|
`var=val` syntax.
|
|
|
|
Returns:
|
|
A list of commands that were executed. Each command is a list of strings.
|
|
"""
|
|
if config_file:
|
|
cfg = config.Config(config_file)
|
|
android_target = cfg.get_build_config_android_target(build_target)
|
|
if cfg.has_tag(build_target, 'skip'):
|
|
print('Warning: skipping build_target "{}" due to tag being set'.format(build_target))
|
|
return []
|
|
else:
|
|
android_target = build_target
|
|
|
|
# All builds are required to run with the root of the
|
|
# Android source tree as the current directory.
|
|
source_dir = os.getcwd()
|
|
command = [
|
|
command_wrapper,
|
|
'%s-%s' % (android_target, variant),
|
|
'/src',
|
|
'make',
|
|
'-j',
|
|
] + build_goals
|
|
|
|
readonly_bind_mounts = []
|
|
if readonly_bind_mount:
|
|
readonly_bind_mounts = [readonly_bind_mount]
|
|
|
|
extra_nsjail_args = []
|
|
cleanup = lambda: None
|
|
nsjail_wrapper = []
|
|
if use_rbe:
|
|
cleanup = rbe.setup(env)
|
|
env = rbe.prepare_env(env)
|
|
extra_nsjail_args.extend(rbe.get_extra_nsjail_args())
|
|
readonly_bind_mounts.extend(rbe.get_readonlybind_mounts())
|
|
nsjail_wrapper = rbe.get_nsjail_bin_wrapper()
|
|
|
|
ret = nsjail.run(
|
|
nsjail_bin=nsjail_bin,
|
|
chroot=chroot,
|
|
overlay_config=config_file,
|
|
source_dir=source_dir,
|
|
command=command,
|
|
build_target=build_target,
|
|
dist_dir=dist_dir,
|
|
build_id=build_id,
|
|
max_cpus=max_cpus,
|
|
extra_nsjail_args=extra_nsjail_args,
|
|
readonly_bind_mounts=readonly_bind_mounts,
|
|
env=env,
|
|
nsjail_wrapper=nsjail_wrapper)
|
|
|
|
cleanup()
|
|
|
|
return ret
|
|
|
|
|
|
def arg_parser():
|
|
"""Returns an ArgumentParser for sanboxed android builds."""
|
|
# Use the top level module docstring for the help description
|
|
parser = argparse.ArgumentParser(
|
|
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument(
|
|
'--build_target',
|
|
help='The build target.')
|
|
parser.add_argument(
|
|
'--variant', default='userdebug', help='The Android build variant.')
|
|
parser.add_argument(
|
|
'--nsjail_bin',
|
|
required=True,
|
|
help='Path to NsJail binary.')
|
|
parser.add_argument(
|
|
'--chroot',
|
|
required=True,
|
|
help='Path to the chroot to be used for building the Android '
|
|
'platform. This will be mounted as the root filesystem in the '
|
|
'NsJail sandbox.')
|
|
parser.add_argument(
|
|
'--config_file',
|
|
required=True,
|
|
help='Path to the overlay configuration file.')
|
|
parser.add_argument(
|
|
'--command_wrapper',
|
|
default=_DEFAULT_COMMAND_WRAPPER,
|
|
help='Path to the command wrapper. '
|
|
'Defaults to \'%s\'.' % _DEFAULT_COMMAND_WRAPPER)
|
|
parser.add_argument(
|
|
'--readonly_bind_mount',
|
|
help='Path to the a path to be mounted as readonly inside the secure '
|
|
'build sandbox.')
|
|
parser.add_argument(
|
|
'--env', '-e',
|
|
type=str,
|
|
default=[],
|
|
action='append',
|
|
help='Specify an environment variable to the NSJail sandbox. Can be specified '
|
|
'muliple times. Syntax: var_name=value')
|
|
parser.add_argument(
|
|
'--dist_dir',
|
|
help='Path to the Android dist directory. This is where '
|
|
'Android platform release artifacts will be written.')
|
|
parser.add_argument(
|
|
'--build_id',
|
|
help='Build identifier what will label the Android platform '
|
|
'release artifacts.')
|
|
parser.add_argument(
|
|
'--max_cpus',
|
|
type=int,
|
|
help='Limit of concurrent CPU cores that the NsJail sanbox '
|
|
'can use.')
|
|
parser.add_argument(
|
|
'--context',
|
|
action='append',
|
|
default=[],
|
|
help='One or more contexts used to select build goals from the '
|
|
'configuration.')
|
|
parser.add_argument(
|
|
'--use_rbe',
|
|
action='store_true',
|
|
help='Executes the build on RBE')
|
|
return parser
|
|
|
|
|
|
def parse_args(parser):
|
|
"""Parses command line arguments.
|
|
|
|
Returns:
|
|
A dict of all the arguments parsed.
|
|
"""
|
|
# Convert the Namespace object to a dict
|
|
return vars(parser.parse_args())
|
|
|
|
|
|
def main():
|
|
args = parse_args(arg_parser())
|
|
|
|
# The --build_target argument could not be required
|
|
# using the standard 'required' argparse option because
|
|
# the argparser is reused by merge_android_sandboxed.py which
|
|
# does not require --build_target.
|
|
if args['build_target'] is None:
|
|
raise ValueError('--build_target is required.')
|
|
|
|
cfg = config.Config(args['config_file'])
|
|
build_goals = cfg.get_build_goals(args['build_target'], set(args['context']))
|
|
|
|
build(
|
|
build_target=args['build_target'],
|
|
variant=args['variant'],
|
|
nsjail_bin=args['nsjail_bin'],
|
|
chroot=args['chroot'],
|
|
config_file=args['config_file'],
|
|
command_wrapper=args['command_wrapper'],
|
|
readonly_bind_mount=args['readonly_bind_mount'],
|
|
env=args['env'],
|
|
dist_dir=args['dist_dir'],
|
|
build_id=args['build_id'],
|
|
max_cpus=args['max_cpus'],
|
|
use_rbe=args['use_rbe'],
|
|
build_goals=build_goals)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|