diff options
Diffstat (limited to 'chromium/build/fuchsia')
-rw-r--r-- | chromium/build/fuchsia/aemu_target.py | 72 | ||||
-rw-r--r-- | chromium/build/fuchsia/common.py | 14 | ||||
-rw-r--r-- | chromium/build/fuchsia/common_args.py | 64 | ||||
-rwxr-xr-x | chromium/build/fuchsia/deploy_to_amber_repo.py | 47 | ||||
-rw-r--r-- | chromium/build/fuchsia/emu_target.py | 92 | ||||
-rw-r--r-- | chromium/build/fuchsia/fidlgen_js/fidl.py | 10 | ||||
-rwxr-xr-x | chromium/build/fuchsia/fidlgen_js/gen.py | 3 | ||||
-rw-r--r-- | chromium/build/fuchsia/fidlgen_js/runtime/fidl.mjs | 6 | ||||
-rw-r--r-- | chromium/build/fuchsia/linux.sdk.sha1 | 2 | ||||
-rw-r--r-- | chromium/build/fuchsia/mac.sdk.sha1 | 2 | ||||
-rw-r--r-- | chromium/build/fuchsia/qemu_target.py | 182 | ||||
-rw-r--r-- | chromium/build/fuchsia/run_package.py | 19 | ||||
-rw-r--r-- | chromium/build/fuchsia/target.py | 24 | ||||
-rwxr-xr-x | chromium/build/fuchsia/test_runner.py | 2 |
14 files changed, 352 insertions, 187 deletions
diff --git a/chromium/build/fuchsia/aemu_target.py b/chromium/build/fuchsia/aemu_target.py new file mode 100644 index 00000000000..94c590bd78e --- /dev/null +++ b/chromium/build/fuchsia/aemu_target.py @@ -0,0 +1,72 @@ +# 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. + +"""Implements commands for running and interacting with Fuchsia on AEMU.""" + +import os +import platform +import qemu_target +import logging + +from common import GetEmuRootForPlatform + +class AemuTarget(qemu_target.QemuTarget): + def __init__(self, output_dir, target_cpu, system_log_file, emu_type, + cpu_cores, require_kvm, ram_size_mb): + super(AemuTarget, self).__init__(output_dir, target_cpu, system_log_file, + emu_type, cpu_cores, require_kvm, + ram_size_mb) + + # TODO(crbug.com/1000907): Enable AEMU for arm64. + if platform.machine() == 'aarch64': + raise Exception('AEMU does not support arm64 hosts.') + + # TODO(bugs.fuchsia.dev/p/fuchsia/issues/detail?id=37301): Remove + # once aemu is part of default fuchsia build + def _EnsureEmulatorExists(self, path): + assert os.path.exists(path), \ + 'This checkout is missing %s. To check out the files, add this\n' \ + 'entry to the "custon_vars" section of your .gclient file:\n\n' \ + ' "checkout_aemu": True\n\n' % (self._emu_type) + + def _BuildCommand(self): + aemu_exec = 'emulator-headless' + + aemu_folder = GetEmuRootForPlatform(self._emu_type) + + self._EnsureEmulatorExists(aemu_folder) + aemu_path = os.path.join(aemu_folder, aemu_exec) + + # `VirtioInput` is needed for touch input device support on Fuchsia. + # `RefCountPipe` is needed for proper cleanup of resources when a process + # that uses Vulkan dies inside the guest + aemu_features = 'VirtioInput,RefCountPipe' + + # Configure the CPU to emulate. + # On Linux, we can enable lightweight virtualization (KVM) if the host and + # guest architectures are the same. + if self._IsKvmEnabled(): + aemu_features += ',KVM,GLDirectMem,Vulkan' + else: + if self._target_cpu != 'arm64': + aemu_features += ',-GLDirectMem' + + # All args after -fuchsia flag gets passed to QEMU + aemu_command = [aemu_path, + '-feature', aemu_features, + '-window-size', '1024x600', + '-gpu', 'swiftshader_indirect', + '-fuchsia' + ] + + aemu_command.extend(self._BuildQemuConfig()) + + aemu_command.extend([ + '-vga', 'none', + '-device', 'isa-debug-exit,iobase=0xf4,iosize=0x04', + '-device', 'virtio-keyboard-pci', + '-device', 'virtio_input_multi_touch_pci_1', + '-device', 'ich9-ahci,id=ahci']) + logging.info(' '.join(aemu_command)) + return aemu_command diff --git a/chromium/build/fuchsia/common.py b/chromium/build/fuchsia/common.py index 3ec1e67aa64..7dd3d52cac8 100644 --- a/chromium/build/fuchsia/common.py +++ b/chromium/build/fuchsia/common.py @@ -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.""" @@ -40,9 +42,9 @@ def GetHostArchFromPlatform(): return 'arm64' raise Exception('Unsupported host architecture: %s' % host_arch) -def GetQemuRootForPlatform(): +def GetEmuRootForPlatform(emulator): return os.path.join(DIR_SOURCE_ROOT, 'third_party', - 'qemu-' + GetHostOsFromPlatform() + '-' + + emulator + '-' + GetHostOsFromPlatform() + '-' + GetHostArchFromPlatform()) def ConnectPortForwardingTask(target, local_port, remote_port = 0): @@ -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) diff --git a/chromium/build/fuchsia/common_args.py b/chromium/build/fuchsia/common_args.py index a897a3072d7..7716771009c 100644 --- a/chromium/build/fuchsia/common_args.py +++ b/chromium/build/fuchsia/common_args.py @@ -6,25 +6,21 @@ import logging import os import sys +from aemu_target import AemuTarget from device_target import DeviceTarget from qemu_target import QemuTarget - def AddCommonArgs(arg_parser): """Adds command line arguments to |arg_parser| for options which are shared 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 ' @@ -34,8 +30,13 @@ def AddCommonArgs(arg_parser): common_args.add_argument('--target-staging-path', help='target path under which to stage packages ' 'during deployment.', default='/data') - common_args.add_argument('--device', '-d', action='store_true', default=False, - help='Run on hardware device instead of QEMU.') + common_args.add_argument('--device', default=None, + choices=['aemu','qemu','device'], + help='Choose to run on aemu|qemu|device. ' + + 'By default, Fuchsia will run in QEMU.') + common_args.add_argument('-d', action='store_const', dest='device', + const='device', + help='Run on device instead of emulator.') common_args.add_argument('--host', help='The IP of the target device. ' + 'Optional.') common_args.add_argument('--node-name', @@ -64,7 +65,11 @@ def AddCommonArgs(arg_parser): help='Enable debug-level logging.') common_args.add_argument('--qemu-cpu-cores', type=int, default=4, help='Sets the number of CPU cores to provide if ' - 'launching in a VM with QEMU.'), + 'launching in a VM.'), + common_args.add_argument('--memory', type=int, default=2048, + help='Sets the RAM size (MB) if launching in a VM'), + common_args.add_argument('--no-kvm', action='store_true', default=False, + help='Disable KVM virtualization'), common_args.add_argument( '--os_check', choices=['check', 'update', 'ignore'], default='update', @@ -94,7 +99,6 @@ def ConfigureLogging(args): def GetDeploymentTargetForArgs(args, require_kvm=False): """Constructs a deployment target object using parameters taken from command line arguments.""" - if args.system_log_file == '-': system_log_file = sys.stdout elif args.system_log_file: @@ -102,19 +106,27 @@ def GetDeploymentTargetForArgs(args, require_kvm=False): else: system_log_file = None + # Allow fuchsia to run on qemu if device not explicitly chosen. if not args.device: - return QemuTarget(output_dir=args.output_directory, - target_cpu=args.target_cpu, - cpu_cores=args.qemu_cpu_cores, - system_log_file=system_log_file, - require_kvm=require_kvm) + args.device = 'qemu' + + target_args = { 'output_dir':args.output_directory, + 'target_cpu':args.target_cpu, + 'system_log_file':system_log_file } + if args.device == 'device': + target_args.update({ 'host':args.host, + 'node_name':args.node_name, + 'port':args.port, + 'ssh_config':args.ssh_config, + 'fuchsia_out_dir':args.fuchsia_out_dir, + 'os_check':args.os_check }) + return DeviceTarget(**target_args) else: - return DeviceTarget(output_dir=args.output_directory, - target_cpu=args.target_cpu, - host=args.host, - node_name=args.node_name, - port=args.port, - ssh_config=args.ssh_config, - fuchsia_out_dir=args.fuchsia_out_dir, - system_log_file=system_log_file, - os_check=args.os_check) + target_args.update({ 'cpu_cores':args.qemu_cpu_cores, + 'require_kvm':not args.no_kvm, + 'emu_type':args.device, + 'ram_size_mb':args.memory }) + if args.device == 'qemu': + return QemuTarget(**target_args) + else: + return AemuTarget(**target_args) diff --git a/chromium/build/fuchsia/deploy_to_amber_repo.py b/chromium/build/fuchsia/deploy_to_amber_repo.py new file mode 100755 index 00000000000..6f36e0a625c --- /dev/null +++ b/chromium/build/fuchsia/deploy_to_amber_repo.py @@ -0,0 +1,47 @@ +#!/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()) diff --git a/chromium/build/fuchsia/emu_target.py b/chromium/build/fuchsia/emu_target.py new file mode 100644 index 00000000000..1aa6e420d05 --- /dev/null +++ b/chromium/build/fuchsia/emu_target.py @@ -0,0 +1,92 @@ +# 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. + +"""Implements commands for running/interacting with Fuchsia on an emulator.""" + +import boot_data +import logging +import os +import subprocess +import sys +import target +import tempfile + +class EmuTarget(target.Target): + def __init__(self, output_dir, target_cpu, system_log_file): + """output_dir: The directory which will contain the files that are + generated to support the emulator deployment. + target_cpu: The emulated target CPU architecture. + Can be 'x64' or 'arm64'.""" + super(EmuTarget, self).__init__(output_dir, target_cpu) + self._emu_process = None + self._system_log_file = system_log_file + + def __enter__(self): + return self + + def _GetEmulatorName(self): + pass + + def _BuildCommand(self): + """Build the command that will be run to start Fuchsia in the emulator.""" + pass + + # Used by the context manager to ensure that the emulator is killed when + # the Python process exits. + def __exit__(self, exc_type, exc_val, exc_tb): + self.Shutdown(); + + def Start(self): + emu_command = self._BuildCommand() + + # We pass a separate stdin stream. Sharing stdin across processes + # leads to flakiness due to the OS prematurely killing the stream and the + # Python script panicking and aborting. + # The precise root cause is still nebulous, but this fix works. + # See crbug.com/741194. + logging.debug('Launching %s.' % (self._GetEmulatorName())) + logging.debug(' '.join(emu_command)) + + # Zircon sends debug logs to serial port (see kernel.serial=legacy flag + # above). Serial port is redirected to a file through emulator stdout. + # Unless a |_system_log_file| is explicitly set, we output the kernel serial + # log to a temporary file, and print that out if we are unable to connect to + # the emulator guest, to make it easier to diagnose connectivity issues. + temporary_system_log_file = None + if self._system_log_file: + stdout = self._system_log_file + stderr = subprocess.STDOUT + else: + temporary_system_log_file = tempfile.NamedTemporaryFile('w') + stdout = temporary_system_log_file + stderr = sys.stderr + + self._emu_process = subprocess.Popen(emu_command, stdin=open(os.devnull), + stdout=stdout, stderr=stderr) + + try: + self._WaitUntilReady(); + except target.FuchsiaTargetException: + if temporary_system_log_file: + logging.info('Kernel logs:\n' + + open(temporary_system_log_file.name, 'r').read()) + raise + + def Shutdown(self): + if self._IsEmuStillRunning(): + logging.info('Shutting down %s' % (self._GetEmulatorName())) + self._emu_process.kill() + + def _IsEmuStillRunning(self): + if not self._emu_process: + return False + return os.waitpid(self._emu_process.pid, os.WNOHANG)[0] == 0 + + def _GetEndpoint(self): + if not self._IsEmuStillRunning(): + raise Exception('%s quit unexpectedly.' % (self._GetEmulatorName())) + return ('localhost', self._host_ssh_port) + + def _GetSshConfigPath(self): + return boot_data.GetSSHConfigPath(self._output_dir)
\ No newline at end of file diff --git a/chromium/build/fuchsia/fidlgen_js/fidl.py b/chromium/build/fuchsia/fidlgen_js/fidl.py index d66ba033050..fb024642767 100644 --- a/chromium/build/fuchsia/fidlgen_js/fidl.py +++ b/chromium/build/fuchsia/fidlgen_js/fidl.py @@ -293,7 +293,7 @@ class InterfaceMethodParameter: class InterfaceMethod: - def __init__(self, has_request, has_response, maybe_attributes, maybe_request, maybe_request_alignment, maybe_request_size, maybe_response, maybe_response_alignment, maybe_response_size, name, ordinal, generated_ordinal): + def __init__(self, has_request, has_response, maybe_attributes, maybe_request, maybe_request_alignment, maybe_request_size, maybe_response, maybe_response_alignment, maybe_response_size, name, ordinal): self.has_request = has_request self.has_response = has_response self.maybe_attributes = maybe_attributes @@ -305,8 +305,6 @@ class InterfaceMethod: self.maybe_response_size = maybe_response_size self.name = name self.ordinal = ordinal - # TODO(https://crbug.com/991300): Remove once |ordinal| is 64-bit. - self.generated_ordinal = generated_ordinal @staticmethod def from_dict(obj): @@ -322,9 +320,7 @@ class InterfaceMethod: maybe_response_size = from_union([from_int, from_none], obj.get(u"maybe_response_size")) name = from_str(obj.get(u"name")) ordinal = from_int(obj.get(u"ordinal")) - # TODO(https://crbug.com/991300): Remove once |ordinal| is 64-bit. - generated_ordinal = from_int(obj.get(u"generated_ordinal")) - return InterfaceMethod(has_request, has_response, maybe_attributes, maybe_request, maybe_request_alignment, maybe_request_size, maybe_response, maybe_response_alignment, maybe_response_size, name, ordinal, generated_ordinal) + return InterfaceMethod(has_request, has_response, maybe_attributes, maybe_request, maybe_request_alignment, maybe_request_size, maybe_response, maybe_response_alignment, maybe_response_size, name, ordinal) def to_dict(self): result = {} @@ -339,8 +335,6 @@ class InterfaceMethod: result[u"maybe_response_size"] = from_union([from_int, from_none], self.maybe_response_size) result[u"name"] = from_str(self.name) result[u"ordinal"] = from_int(self.ordinal) - # TODO(https://crbug.com/991300): Remove once |ordinal| is 64-bit. - result[u"generated_ordinal"] = from_int(self.generated_ordinal) return result diff --git a/chromium/build/fuchsia/fidlgen_js/gen.py b/chromium/build/fuchsia/fidlgen_js/gen.py index 005101988c2..9830fdbff51 100755 --- a/chromium/build/fuchsia/fidlgen_js/gen.py +++ b/chromium/build/fuchsia/fidlgen_js/gen.py @@ -525,8 +525,7 @@ function %(name)s() {} 'const _k%(name)s_%(method_name)s_Ordinal = %(ordinal)sn;\n' % { 'name': name, 'method_name': method_name, - # TODO(https://crbug.com/991300): Use |ordinal| once it is 64-bit. - 'ordinal': method.generated_ordinal + 'ordinal': method.ordinal }) self.f.write('\n') diff --git a/chromium/build/fuchsia/fidlgen_js/runtime/fidl.mjs b/chromium/build/fuchsia/fidlgen_js/runtime/fidl.mjs index d7ce381f433..d611e61aa51 100644 --- a/chromium/build/fuchsia/fidlgen_js/runtime/fidl.mjs +++ b/chromium/build/fuchsia/fidlgen_js/runtime/fidl.mjs @@ -10,7 +10,7 @@ const $fidl_kInitialBufferSize = 1024; const $fidl_kMessageHeaderSize = 16; const $fidl_kMessageTxidOffset = 0; -const $fidl_kMessageOrdinalOffset = 12; +const $fidl_kMessageOrdinalOffset = 8; const $fidl__kAlignment = 8; const $fidl__kAlignmentMask = 0x7; @@ -30,8 +30,8 @@ function $fidl__align(size) { function $fidl__setUint64LE(dataView, offset, value) { var high_bits = Number(BigInt.asUintN(32, value >> 32n)) var low_bits = Number(BigInt.asUintN(32, value)) - dataView.setUint32(offset+0, high_bits, $fidl__kLE); - dataView.setUint32(offset+4, low_bits, $fidl__kLE); + dataView.setUint32(offset+4, high_bits, $fidl__kLE); + dataView.setUint32(offset+0, low_bits, $fidl__kLE); } diff --git a/chromium/build/fuchsia/linux.sdk.sha1 b/chromium/build/fuchsia/linux.sdk.sha1 index 9f0cf4b7493..6ea1b65663a 100644 --- a/chromium/build/fuchsia/linux.sdk.sha1 +++ b/chromium/build/fuchsia/linux.sdk.sha1 @@ -1 +1 @@ -8903197588632695296
\ No newline at end of file +8899502756487089920
\ No newline at end of file diff --git a/chromium/build/fuchsia/mac.sdk.sha1 b/chromium/build/fuchsia/mac.sdk.sha1 index 872fcea6a9d..f17fc2b983b 100644 --- a/chromium/build/fuchsia/mac.sdk.sha1 +++ b/chromium/build/fuchsia/mac.sdk.sha1 @@ -1 +1 @@ -8903199652766737008
\ No newline at end of file +8899505638123521760
\ No newline at end of file diff --git a/chromium/build/fuchsia/qemu_target.py b/chromium/build/fuchsia/qemu_target.py index 4e6ff19b955..68c980a9664 100644 --- a/chromium/build/fuchsia/qemu_target.py +++ b/chromium/build/fuchsia/qemu_target.py @@ -6,19 +6,17 @@ import boot_data import common +import emu_target import logging import md5 import os import platform import shutil -import socket import subprocess import sys -import target import tempfile -import time -from common import GetQemuRootForPlatform, EnsurePathExists +from common import GetEmuRootForPlatform, EnsurePathExists # Virtual networking configuration data for QEMU. @@ -31,46 +29,33 @@ GUEST_MAC_ADDRESS = '52:54:00:63:5e:7b' EXTENDED_BLOBSTORE_SIZE = 1073741824 # 1GB -class QemuTarget(target.Target): - def __init__(self, output_dir, target_cpu, cpu_cores, system_log_file, - require_kvm, ram_size_mb=2048): - """output_dir: The directory which will contain the files that are - generated to support the QEMU deployment. - target_cpu: The emulated target CPU architecture. - Can be 'x64' or 'arm64'.""" - super(QemuTarget, self).__init__(output_dir, target_cpu) - self._qemu_process = None - self._ram_size_mb = ram_size_mb - self._system_log_file = system_log_file - self._cpu_cores = cpu_cores - self._require_kvm = require_kvm - - def __enter__(self): - return self - - # Used by the context manager to ensure that QEMU is killed when the Python - # process exits. - def __exit__(self, exc_type, exc_val, exc_tb): - self.Shutdown(); - - def Start(self): +class QemuTarget(emu_target.EmuTarget): + def __init__(self, output_dir, target_cpu, system_log_file, + emu_type, cpu_cores, require_kvm, ram_size_mb): + super(QemuTarget, self).__init__(output_dir, target_cpu, + system_log_file) + self._emu_type=emu_type + self._cpu_cores=cpu_cores + self._require_kvm=require_kvm + self._ram_size_mb=ram_size_mb + + def _GetEmulatorName(self): + return self._emu_type + + def _IsKvmEnabled(self): + if self._require_kvm: + if (sys.platform.startswith('linux') and + os.access('/dev/kvm', os.R_OK | os.W_OK)): + if self._target_cpu == 'arm64' and platform.machine() == 'aarch64': + return True + if self._target_cpu == 'x64' and platform.machine() == 'x86_64': + return True + return False + + def _BuildQemuConfig(self): boot_data.AssertBootImagesExist(self._GetTargetSdkArch(), 'qemu') - qemu_path = os.path.join(GetQemuRootForPlatform(), 'bin', - 'qemu-system-' + self._GetTargetSdkLegacyArch()) - kernel_args = boot_data.GetKernelArgs(self._output_dir) - - # TERM=dumb tells the guest OS to not emit ANSI commands that trigger - # noisy ANSI spew from the user's terminal emulator. - kernel_args.append('TERM=dumb') - - # Enable logging to the serial port. This is a temporary fix to investigate - # the root cause for https://crbug.com/869753 . - kernel_args.append('kernel.serial=legacy') - - qemu_command = [qemu_path, - '-m', str(self._ram_size_mb), - '-nographic', + emu_command = [ '-kernel', EnsurePathExists( boot_data.GetTargetFile('qemu-kernel.kernel', self._GetTargetSdkArch(), @@ -78,6 +63,7 @@ class QemuTarget(target.Target): '-initrd', EnsurePathExists( boot_data.GetBootImage(self._output_dir, self._GetTargetSdkArch(), boot_data.TARGET_TYPE_QEMU)), + '-m', str(self._ram_size_mb), '-smp', str(self._cpu_cores), # Attach the blobstore and data volumes. Use snapshot mode to discard @@ -92,38 +78,20 @@ class QemuTarget(target.Target): # monitor. '-serial', 'stdio', '-monitor', 'none', - - '-append', ' '.join(kernel_args) ] # Configure the machine to emulate, based on the target architecture. if self._target_cpu == 'arm64': - qemu_command.extend([ + emu_command.extend([ '-machine','virt', ]) netdev_type = 'virtio-net-pci' else: - qemu_command.extend([ + emu_command.extend([ '-machine', 'q35', ]) netdev_type = 'e1000' - # Configure the CPU to emulate. - # On Linux, we can enable lightweight virtualization (KVM) if the host and - # guest architectures are the same. - enable_kvm = self._require_kvm or (sys.platform.startswith('linux') and ( - (self._target_cpu == 'arm64' and platform.machine() == 'aarch64') or - (self._target_cpu == 'x64' and platform.machine() == 'x86_64')) and - os.access('/dev/kvm', os.R_OK | os.W_OK)) - if enable_kvm: - qemu_command.extend(['-enable-kvm', '-cpu', 'host,migratable=no']) - else: - logging.warning('Unable to launch QEMU with KVM acceleration.') - if self._target_cpu == 'arm64': - qemu_command.extend(['-cpu', 'cortex-a53']) - else: - qemu_command.extend(['-cpu', 'Haswell,+smap,-check,-fsgsbase']) - # Configure virtual network. It is used in the tests to connect to # testserver running on the host. netdev_config = 'user,id=net0,net=%s,dhcpstart=%s,host=%s' % \ @@ -131,61 +99,50 @@ class QemuTarget(target.Target): self._host_ssh_port = common.GetAvailableTcpPort() netdev_config += ",hostfwd=tcp::%s-:22" % self._host_ssh_port - qemu_command.extend([ + emu_command.extend([ '-netdev', netdev_config, '-device', '%s,netdev=net0,mac=%s' % (netdev_type, GUEST_MAC_ADDRESS), ]) - # We pass a separate stdin stream to qemu. Sharing stdin across processes - # leads to flakiness due to the OS prematurely killing the stream and the - # Python script panicking and aborting. - # The precise root cause is still nebulous, but this fix works. - # See crbug.com/741194. - logging.debug('Launching QEMU.') - logging.debug(' '.join(qemu_command)) - - # Zircon sends debug logs to serial port (see kernel.serial=legacy flag - # above). Serial port is redirected to a file through QEMU stdout. - # Unless a |_system_log_file| is explicitly set, we output the kernel serial - # log to a temporary file, and print that out if we are unable to connect to - # the QEMU guest, to make it easier to diagnose connectivity issues. - temporary_system_log_file = None - if self._system_log_file: - stdout = self._system_log_file - stderr = subprocess.STDOUT + # Configure the CPU to emulate. + # On Linux, we can enable lightweight virtualization (KVM) if the host and + # guest architectures are the same. + if self._IsKvmEnabled(): + kvm_command = ['-enable-kvm', '-cpu', 'host,migratable=no'] else: - temporary_system_log_file = tempfile.NamedTemporaryFile('w') - stdout = temporary_system_log_file - stderr = sys.stderr - - self._qemu_process = subprocess.Popen(qemu_command, stdin=open(os.devnull), - stdout=stdout, stderr=stderr) - try: - self._WaitUntilReady(); - except target.FuchsiaTargetException: - if temporary_system_log_file: - logging.info("Kernel logs:\n" + - open(temporary_system_log_file.name, 'r').read()) - raise - - def Shutdown(self): - if self._IsQemuStillRunning(): - logging.info('Shutting down QEMU.') - self._qemu_process.kill() - - def _IsQemuStillRunning(self): - if not self._qemu_process: - return False - return os.waitpid(self._qemu_process.pid, os.WNOHANG)[0] == 0 - - def _GetEndpoint(self): - if not self._IsQemuStillRunning(): - raise Exception('QEMU quit unexpectedly.') - return ('localhost', self._host_ssh_port) - - def _GetSshConfigPath(self): - return boot_data.GetSSHConfigPath(self._output_dir) + logging.warning('Unable to launch %s with KVM acceleration.' + % (self._emu_type) + + 'The guest VM will be slow.') + if self._target_cpu == 'arm64': + kvm_command = ['-cpu', 'cortex-a53'] + else: + kvm_command = ['-cpu', 'Haswell,+smap,-check,-fsgsbase'] + + emu_command.extend(kvm_command) + + kernel_args = boot_data.GetKernelArgs(self._output_dir) + + # TERM=dumb tells the guest OS to not emit ANSI commands that trigger + # noisy ANSI spew from the user's terminal emulator. + kernel_args.append('TERM=dumb') + + # Construct kernel cmd line + kernel_args.append('kernel.serial=legacy') + + # Don't 'reboot' the emulator if the kernel crashes + kernel_args.append('kernel.halt-on-panic=true') + + emu_command.extend(['-append', ' '.join(kernel_args)]) + + return emu_command + def _BuildCommand(self): + qemu_exec = 'qemu-system-'+self._GetTargetSdkLegacyArch() + qemu_command = [os.path.join(GetEmuRootForPlatform(self._emu_type), 'bin', + qemu_exec)] + qemu_command.extend(self._BuildQemuConfig()) + qemu_command.append('-nographic') + return qemu_command def _ComputeFileHash(filename): hasher = md5.new() @@ -202,7 +159,8 @@ def _EnsureBlobstoreQcowAndReturnPath(output_dir, target_arch): """Returns a file containing the Fuchsia blobstore in a QCOW format, with extra buffer space added for growth.""" - qimg_tool = os.path.join(common.GetQemuRootForPlatform(), 'bin', 'qemu-img') + qimg_tool = os.path.join(common.GetEmuRootForPlatform('qemu'), + 'bin', 'qemu-img') fvm_tool = os.path.join(common.SDK_ROOT, 'tools', 'fvm') blobstore_path = boot_data.GetTargetFile('storage-full.blk', target_arch, 'qemu') diff --git a/chromium/build/fuchsia/run_package.py b/chromium/build/fuchsia/run_package.py index 6e3a5d26364..2e0846da9cf 100644 --- a/chromium/build/fuchsia/run_package.py +++ b/chromium/build/fuchsia/run_package.py @@ -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: diff --git a/chromium/build/fuchsia/target.py b/chromium/build/fuchsia/target.py index 0d29cd1b7aa..b2e1505a5d8 100644 --- a/chromium/build/fuchsia/target.py +++ b/chromium/build/fuchsia/target.py @@ -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.' % diff --git a/chromium/build/fuchsia/test_runner.py b/chromium/build/fuchsia/test_runner.py index 669de83a95a..6efa46f224c 100755 --- a/chromium/build/fuchsia/test_runner.py +++ b/chromium/build/fuchsia/test_runner.py @@ -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() |