Commit 55fd8528 authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[Fuchsia] Modify installation scripts to deploy to Fuchsia Amber repos.

Changes the OUTDIR/bin/install_foo scripts to run "pm install"
on existing Fuchsia Amber repositories. This better suits the common
workflow of deploying to existing paved devices.

Adds a GN arg "default_fuchsia_build_dir_for_installation" to enable
super EZ zero-arg invocations of the install script.

Bug: 973159
Change-Id: I5d4456fd74f7000a576749d2c427051f24d216b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1815838Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarJohn Budorick <jbudorick@chromium.org>
Reviewed-by: default avatarDavid Dorwin <ddorwin@chromium.org>
Reviewed-by: default avatarMichael Spang <spang@chromium.org>
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Auto-Submit: Kevin Marshall <kmarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#703075}
parent 38db9a14
......@@ -3,7 +3,7 @@
# found in the LICENSE file.
import("//build/config/fuchsia/config.gni")
import("//build/config/fuchsia/rules.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
import("//build/config/sysroot.gni")
assert(is_fuchsia)
......
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
assert(is_fuchsia)
import("//build/config/chromecast_build.gni")
import("//build/config/fuchsia/config.gni")
import("//build/config/fuchsia/package.gni")
import("//build/config/sysroot.gni")
import("//build/util/generate_wrapper.gni")
declare_args() {
# Sets the Fuchsia Amber repository which will be used by default by the
# generated installation scripts. If not specified, then no default directory
# will be used.
default_fuchsia_build_dir_for_installation = ""
}
# Generates a script which deploys and optionally executes a package on a
# device.
#
# Parameters:
# package: The package() target which will be run.
# package_name_override: Specifies the name of the generated package, if its
# name is different than the |package| target name. This value must match
# package_name_override in the |package| target.
# package_deps: An array of [package, package_name_override] array pairs
# which specify additional dependency packages to be installed
# prior to execution.
# runner_script: The runner script implementation to use, relative to
# "build/fuchsia". Defaults to "test_runner.py".
# install_only: If true, executing the script will only install the package
# on the device, but not run it.
template("fuchsia_package_runner") {
forward_variables_from(invoker, [ "runner_script" ])
if (defined(invoker.package_name_override)) {
_pkg_shortname = invoker.package_name_override
} else {
_pkg_shortname = get_label_info(invoker.package, "name")
}
_pkg_dir = "$root_out_dir/gen/" + get_label_info(invoker.package, "dir") +
"/" + _pkg_shortname
_manifest_path = "$_pkg_dir/${_pkg_shortname}.archive_manifest"
_package_path = "$_pkg_dir/${_pkg_shortname}.far"
generated_run_pkg_script_path = "$root_build_dir/bin/run_${_pkg_shortname}"
generated_install_pkg_script_path =
"$root_build_dir/bin/install_$_pkg_shortname"
_generate_runner_target = "${target_name}__generate_runner"
_generate_installer_target = "${target_name}__generate_installer"
# Generates a script which installs and runs a test.
generate_wrapper(_generate_runner_target) {
forward_variables_from(invoker,
[
"target",
"testonly",
])
if (defined(runner_script)) {
executable = rebase_path(runner_script)
} else {
executable = rebase_path("//build/fuchsia/test_runner.py")
}
wrapper_script = generated_run_pkg_script_path
deps = [
invoker.package,
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
data_deps = [
invoker.package,
]
# Declares the files that are needed for test execution on the
# swarming test client.
data = [
_manifest_path,
"//build/fuchsia/",
"//build/util/lib/",
"//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer",
"${qemu_root}/",
"${fuchsia_sdk}/tools/fvm",
"${fuchsia_sdk}/tools/pm",
"${fuchsia_sdk}/tools/symbolize",
"${fuchsia_sdk}/tools/zbi",
"${fuchsia_sdk}/.build-id/",
"${boot_image_root}/qemu/qemu-kernel.kernel",
"${boot_image_root}/qemu/storage-full.blk",
"${boot_image_root}/qemu/zircon-a.zbi",
]
executable_args = []
package_paths = [ rebase_path(_package_path, root_build_dir) ]
if (defined(invoker.package_deps)) {
foreach(package_dep, invoker.package_deps) {
package_dep_target = package_dep[0]
package_dep_name = package_dep[1]
deps += [ package_dep_target ]
package_dep_path = rebase_path(
get_label_info(package_dep_target, "target_gen_dir") + "/" +
package_dep_name + "/" + package_dep_name + ".far",
root_build_dir)
package_paths += [ package_dep_path ]
}
}
foreach(package_path, package_paths) {
executable_args += [
"--package",
"@WrappedPath(${package_path})",
]
}
executable_args += [
"--output-directory",
"@WrappedPath(.)",
"--target-cpu",
target_cpu,
"--package-name",
_pkg_shortname,
]
if (defined(invoker.use_test_server) && invoker.use_test_server) {
executable_args += [ "--enable-test-server" ]
}
}
# Produces a script which installs a package and its dependencies into the
# Amber repository of a pre-existing Fuchsia build directory.
generate_wrapper(_generate_installer_target) {
forward_variables_from(invoker, [ "testonly" ])
executable = rebase_path("//build/fuchsia/deploy_to_amber_repo.py")
wrapper_script = generated_install_pkg_script_path
deps = [
invoker.package,
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
# Build a list of all packages to install, and pass the list to the runner
# script.
package_paths = [ rebase_path(_package_path, root_build_dir) ]
if (defined(invoker.package_deps)) {
foreach(package_dep, invoker.package_deps) {
package_dep_target = package_dep[0]
package_dep_name = package_dep[1]
deps += [ package_dep_target ]
package_dep_path = rebase_path(
get_label_info(package_dep_target, "target_gen_dir") + "/" +
package_dep_name + "/" + package_dep_name + ".far",
root_build_dir)
package_paths += [ package_dep_path ]
}
}
executable_args = []
foreach(package_path, package_paths) {
executable_args += [
"--package",
"@WrappedPath(${package_path})",
]
if (default_fuchsia_build_dir_for_installation != "") {
executable_args += [
"--fuchsia-out-dir",
default_fuchsia_build_dir_for_installation,
]
}
}
}
group(target_name) {
forward_variables_from(invoker, [ "testonly" ])
deps = [
":${_generate_installer_target}",
]
if (!defined(invoker.install_only) || invoker.install_only == false) {
deps += [ ":${_generate_runner_target}" ]
}
}
}
# Copyright 2018 The Chromium Authors. All rights reserved.
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
assert(is_fuchsia)
import("//build/config/chromecast_build.gni")
import("//build/config/fuchsia/config.gni")
import("//build/config/fuchsia/package.gni")
import("//build/config/sysroot.gni")
import("//build/util/generate_wrapper.gni")
# Generates a script which deploys and executes a package on a device.
#
# Parameters:
# package: The package() target which will be run.
# package_name_override: Specifies the name of the generated package, if its
# name is different than the |package| target name. This value must match
# package_name_override in the |package| target.
# package_deps: An array of [package, package_name_override] array pairs
# which specify additional dependency packages to be installed
# prior to execution.
# runner_script: The runner script implementation to use, relative to
# "build/fuchsia". Defaults to "exe_runner.py".
# install_only: If true, executing the script will only install the package
# on the device, but not run it.
template("fuchsia_package_runner") {
forward_variables_from(invoker, [ "runner_script" ])
if (defined(invoker.package_name_override)) {
_pkg_shortname = invoker.package_name_override
} else {
_pkg_shortname = get_label_info(invoker.package, "name")
}
_pkg_dir = "$root_out_dir/gen/" + get_label_info(invoker.package, "dir") +
"/" + _pkg_shortname
_manifest_path = "$_pkg_dir/${_pkg_shortname}.archive_manifest"
_package_path = "$_pkg_dir/${_pkg_shortname}.far"
if (!defined(runner_script)) {
runner_script = "//build/fuchsia/exe_runner.py"
}
generated_run_pkg_script_path = "$root_build_dir/bin/run_${_pkg_shortname}"
generated_install_pkg_script_path =
"$root_build_dir/bin/install_$_pkg_shortname"
_generate_runner_target = "${target_name}__generate_runner"
_generate_installer_target = "${target_name}__generate_installer"
_generate_template = "${target_name}__generate_template"
# Generates a script to install and optionally run a package.
#
# Parameters:
# |install_only|: If true, builds a script that only installs a package.
# |script_path|: The path of the script to generate.
template(_generate_template) {
generate_wrapper(target_name) {
forward_variables_from(invoker,
[
"install_only",
"script_path",
"target",
"testonly",
])
executable = runner_script
wrapper_script = script_path
deps = [
invoker.package,
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
# Declares the files that are needed for test execution on the
# swarming test client.
data = [
_manifest_path,
"//build/fuchsia/",
"//build/util/lib/",
"//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer",
"${qemu_root}/",
"${fuchsia_sdk}/tools/fvm",
"${fuchsia_sdk}/tools/pm",
"${fuchsia_sdk}/tools/symbolize",
"${fuchsia_sdk}/tools/zbi",
"${fuchsia_sdk}/.build-id/",
"${boot_image_root}/qemu/qemu-kernel.kernel",
"${boot_image_root}/qemu/storage-full.blk",
"${boot_image_root}/qemu/zircon-a.zbi",
]
data_deps = [
invoker.package,
]
executable_args = []
if (defined(invoker.package_deps)) {
foreach(cur_package, invoker.package_deps) {
deps += [ cur_package[0] ]
dep_package_path =
get_label_info(cur_package[0], "target_gen_dir") + "/" +
cur_package[1] + "/" + cur_package[1] + ".far"
_rebased_dep_package_path =
rebase_path(dep_package_path, root_build_dir)
executable_args += [
"--package-dep",
"@WrappedPath(${_rebased_dep_package_path})",
]
}
}
_rebased_package_path = rebase_path(_package_path, root_build_dir)
executable_args += [
"--output-directory",
"@WrappedPath(.)",
"--target-cpu",
target_cpu,
"--package",
"@WrappedPath(${_rebased_package_path})",
"--package-name",
_pkg_shortname,
]
if (defined(invoker.use_test_server) && invoker.use_test_server) {
executable_args += [ "--enable-test-server" ]
}
if (defined(install_only) && install_only) {
executable_args += [ "--install-only" ]
}
}
}
target(_generate_template, _generate_runner_target) {
forward_variables_from(invoker, "*")
script_path = generated_run_pkg_script_path
}
target(_generate_template, _generate_installer_target) {
forward_variables_from(invoker, "*")
script_path = generated_install_pkg_script_path
install_only = true
}
# Build the installer script, and the runner for non-|install_only| targets.
group(target_name) {
forward_variables_from(invoker, [ "testonly" ])
deps = [
":${_generate_installer_target}",
]
# Generate a runner script if the target is not install-only.
if (!defined(invoker.install_only)) {
deps += [ ":${_generate_runner_target}" ]
}
}
}
import("//build/config/fuchsia/generate_runner_scripts.gni")
......@@ -15,6 +15,8 @@ SDK_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'fuchsia-sdk', 'sdk')
IMAGES_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'fuchsia-sdk',
'images')
_PM = os.path.join(SDK_ROOT, 'tools', 'pm')
def EnsurePathExists(path):
"""Checks that the file |path| exists on the filesystem and returns the path
if it does, raising an exception otherwise."""
......@@ -86,3 +88,11 @@ def GetAvailableTcpPort():
port = sock.getsockname()[1]
sock.close()
return port
def PublishPackage(package_path, tuf_root):
"""Publishes a combined FAR package to a TUF repository root."""
subprocess.check_call(
[_PM, 'publish', '-a', '-f', package_path, '-r', tuf_root, '-vt', '-v'],
stderr=subprocess.STDOUT)
......@@ -15,16 +15,12 @@ def AddCommonArgs(arg_parser):
across test and executable target types."""
common_args = arg_parser.add_argument_group('common', 'Common arguments')
common_args.add_argument('--package',
type=os.path.realpath, required=True,
help='Path to the package to execute.')
common_args.add_argument('--package', action='append', required=True,
help='Paths of the packages to install, including '
'all dependencies.')
common_args.add_argument('--package-name', required=True,
help='Name of the package to execute, defined in ' +
'package metadata.')
common_args.add_argument('--package-dep', action='append', default=[],
help='Path to an additional package to install.')
common_args.add_argument('--install-only', action='store_true', default=False,
help='Install the packages but do not run them.')
common_args.add_argument('--output-directory',
type=os.path.realpath, required=True,
help=('Path to the directory in which build files '
......
#!/usr/bin/env python
#
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Deploys Fuchsia packages to an Amber repository in a Fuchsia
build output directory."""
import argparse
import os
import sys
from common import PublishPackage
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--package', action='append', required=True,
help='Paths to packages to install.')
parser.add_argument('--fuchsia-out-dir', nargs='+',
help='Path to a Fuchsia build output directory. '
'If more than one outdir is supplied, the last one '
'in the sequence will be used.')
args = parser.parse_args()
assert args.package
if not args.fuchsia_out_dir or len(args.fuchsia_out_dir) == 0:
sys.stderr.write('No Fuchsia build output directory was specified.\n' +
'To resolve this, Use the commandline argument ' +
'--fuchsia-out-dir\nor set the GN arg ' +
'"default_fuchsia_build_dir_for_installation".\n')
return 1
fuchsia_out_dir = args.fuchsia_out_dir.pop()
tuf_root = os.path.join(fuchsia_out_dir, 'amber-files')
print('Installing packages in Amber repo %s...' % tuf_root)
for package in args.package:
PublishPackage(package, os.path.expanduser(tuf_root))
print('Installation success.')
return 0
if __name__ == '__main__':
sys.exit(main())
......@@ -117,7 +117,6 @@ def _GetComponentUri(package_name):
class RunPackageArgs:
"""RunPackage() configuration arguments structure.
install_only: If set, skips the package execution step.
symbolizer_config: A newline delimited list of source files contained
in the package. Omitting this parameter will disable symbolization.
system_logging: If set, connects a system log reader to the target.
......@@ -125,7 +124,6 @@ class RunPackageArgs:
installation. Defaults to staging into '/data'.
"""
def __init__(self):
self.install_only = False
self.symbolizer_config = None
self.system_logging = False
self.target_staging_path = '/data'
......@@ -133,7 +131,6 @@ class RunPackageArgs:
@staticmethod
def FromCommonArgs(args):
run_package_args = RunPackageArgs()
run_package_args.install_only = args.install_only
run_package_args.system_logging = args.include_system_logs
run_package_args.target_staging_path = args.target_staging_path
return run_package_args
......@@ -151,15 +148,15 @@ def _DrainStreamToStdout(stream, quit_event):
print(line.rstrip())
def RunPackage(output_dir, target, package_path, package_name,
package_deps, package_args, args):
def RunPackage(output_dir, target, package_paths, package_name,
package_args, args):
"""Installs the Fuchsia package at |package_path| on the target,
executes it with |package_args|, and symbolizes its output.
output_dir: The path containing the build output files.
target: The deployment Target object that will run the package.
package_path: The path to the .far package file.
package_name: The name of app specified by package metadata.
package_paths: The paths to the .far packages to be installed.
package_name: The name of the primary package to run.
package_args: The arguments which will be passed to the Fuchsia process.
args: Structure of arguments to configure how the package will be run.
......@@ -178,16 +175,12 @@ def RunPackage(output_dir, target, package_path, package_name,
log_output_thread.daemon = True
log_output_thread.start()
target.InstallPackage(package_path, package_name, package_deps)
target.InstallPackage(package_paths)
if system_logger:
log_output_quit_event.set()
log_output_thread.join(timeout=_JOIN_TIMEOUT_SECS)
if args.install_only:
logging.info('Installation complete.')
return
logging.info('Running application.')
command = ['run', _GetComponentUri(package_name)] + package_args
process = target.RunCommandPiped(command,
......@@ -205,7 +198,7 @@ def RunPackage(output_dir, target, package_path, package_name,
build_ids_paths = map(
lambda package_path: os.path.join(
os.path.dirname(package_path), 'ids.txt'),
[package_path] + package_deps)
package_paths)
output_stream = SymbolizerFilter(output_stream, build_ids_paths)
for next_line in output_stream:
......
......@@ -40,14 +40,6 @@ def _GetPackageInfo(package_path):
return (package_info['name'], package_info['version'])
def _PublishPackage(tuf_root, package_path):
"""Publishes a combined FAR package to a TUF repository root."""
subprocess.check_call(
[_PM, 'publish', '-a', '-f', package_path, '-r', tuf_root, '-vt', '-v'],
stderr=subprocess.STDOUT)
class _MapIsolatedPathsForPackage:
"""Callable object which remaps /data and /tmp paths to their package-specific
locations."""
......@@ -266,15 +258,12 @@ class Target(object):
return 'x86_64'
raise Exception('Unknown target_cpu %s:' % self._target_cpu)
def InstallPackage(self, package_path, package_name, package_deps):
def InstallPackage(self, package_paths):
"""Installs a package and it's dependencies on the device. If the package is
already installed then it will be updated to the new version.
package_path: Path to the .far file to be installed.
package_name: Package name.
package_deps: List of .far files with the packages that the main package
depends on. These packages are installed or updated as well.
"""
package_paths: Paths to the .far files to install."""
try:
tuf_root = tempfile.mkdtemp()
pm_serve_task = None
......@@ -289,9 +278,8 @@ class Target(object):
':%d' % serve_port, '-q'])
# Publish all packages to the serving TUF repository under |tuf_root|.
all_packages = [package_path] + package_deps
for next_package_path in all_packages:
_PublishPackage(tuf_root, next_package_path)
for next_package_path in package_paths:
common.PublishPackage(next_package_path, tuf_root)
_WaitForPmServeToBeReady(serve_port)
......@@ -299,7 +287,7 @@ class Target(object):
self._RegisterAmberRepository(tuf_root, remote_port)
# Install all packages.
for next_package_path in all_packages:
for next_package_path in package_paths:
install_package_name, package_version = \
_GetPackageInfo(next_package_path)
logging.info('Installing %s version %s.' %
......
......@@ -123,7 +123,7 @@ def main():
run_package_args = RunPackageArgs.FromCommonArgs(args)
returncode = RunPackage(
args.output_directory, target, args.package, args.package_name,
args.package_dep, child_args, run_package_args)
child_args, run_package_args)
if test_server:
test_server.Stop()
......
......@@ -5,7 +5,7 @@
import("//tools/grit/grit_rule.gni")
if (is_fuchsia) {
import("//build/config/fuchsia/rules.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
}
source_set("named_message_port_connector_resources") {
......
......@@ -5,7 +5,7 @@
assert(is_fuchsia)
import("//build/config/fuchsia/fidl_library.gni")
import("//build/config/fuchsia/rules.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
import("//testing/test.gni")
# Integration helpers for commonly used fuchsia.* APIs.
......
......@@ -4,7 +4,7 @@
assert(is_fuchsia)
import("//build/config/fuchsia/rules.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
import("//build/config/fuchsia/symbol_archive.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//testing/test.gni")
......
......@@ -5,7 +5,7 @@
assert(is_fuchsia)
import("//build/config/fuchsia/fidl_library.gni")
import("//build/config/fuchsia/rules.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
import("//build/config/fuchsia/symbol_archive.gni")
import("//build/util/process_version.gni")
import("//testing/test.gni")
......
......@@ -5,7 +5,7 @@
assert(is_fuchsia)
import("//build/buildflag_header.gni")
import("//build/config/fuchsia/rules.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
import("//build/config/fuchsia/symbol_archive.gni")
import("//testing/test.gni")
......
......@@ -15,8 +15,8 @@ if (is_android) {
if (is_fuchsia) {
import("//build/config/chromecast_build.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
import("//build/config/fuchsia/package.gni")
import("//build/config/fuchsia/rules.gni")
}
if (is_chromeos) {
......
......@@ -160,8 +160,7 @@ class _TargetHost(object):
stderr=subprocess.PIPE)
package_path = os.path.join(build_path, CONTENT_SHELL_PACKAGE_PATH)
self._target.InstallPackage(package_path, "content_shell",
package_deps=[])
self._target.InstallPackage([package_path])
# Process will be forked for each worker, which may make QemuTarget
# unusable (e.g. waitpid() for qemu process returns ECHILD after
......
......@@ -4,7 +4,7 @@
import("//gpu/vulkan/features.gni")
if (is_fuchsia) {
import("//build/config/fuchsia/rules.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
}
group("demo") {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment