summaryrefslogtreecommitdiffstats
path: root/chromium/build/fuchsia
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/build/fuchsia')
-rw-r--r--chromium/build/fuchsia/aemu_target.py72
-rw-r--r--chromium/build/fuchsia/common.py14
-rw-r--r--chromium/build/fuchsia/common_args.py64
-rwxr-xr-xchromium/build/fuchsia/deploy_to_amber_repo.py47
-rw-r--r--chromium/build/fuchsia/emu_target.py92
-rw-r--r--chromium/build/fuchsia/fidlgen_js/fidl.py10
-rwxr-xr-xchromium/build/fuchsia/fidlgen_js/gen.py3
-rw-r--r--chromium/build/fuchsia/fidlgen_js/runtime/fidl.mjs6
-rw-r--r--chromium/build/fuchsia/linux.sdk.sha12
-rw-r--r--chromium/build/fuchsia/mac.sdk.sha12
-rw-r--r--chromium/build/fuchsia/qemu_target.py182
-rw-r--r--chromium/build/fuchsia/run_package.py19
-rw-r--r--chromium/build/fuchsia/target.py24
-rwxr-xr-xchromium/build/fuchsia/test_runner.py2
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()