diff --git a/packages/flutter_tools/lib/src/fuchsia/amber_ctl.dart b/packages/flutter_tools/lib/src/fuchsia/amber_ctl.dart deleted file mode 100644 index 89db609ffb8..00000000000 --- a/packages/flutter_tools/lib/src/fuchsia/amber_ctl.dart +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// @dart = 2.8 - -import '../base/process.dart'; - -import 'fuchsia_device.dart'; -import 'fuchsia_pm.dart'; - -// usage: amber_ctl [opts] -// Commands -// get_up - get an update for a package -// Options -// -n: name of the package -// -v: version of the package to retrieve, if none is supplied any -// package instance could match -// -m: merkle root of the package to retrieve, if none is supplied -// any package instance could match -// -// get_blob - get the specified content blob -// -i: content ID of the blob -// -// add_src - add a source to the list we can use -// -n: name of the update source (optional, with URL) -// -f: file path or url to a source config file -// -h: SHA256 hash of source config file (optional, with URL) -// -x: do not disable other active sources (if the provided source is -// enabled) -// -// add_repo_cfg - add a repository config to the set of known repositories, -// using a source config -// -n: name of the update source (optional, with URL) -// -f: file path or url to a source config file -// -h: SHA256 hash of source config file (optional, with URL) -// -// rm_src - remove a source, if it exists -// -n: name of the update source -// -// list_srcs - list the set of sources we can use -// -// enable_src -// -n: name of the update source -// -x: do not disable other active sources -// -// disable_src -// -n: name of the update source -// -// system_update - check for, download, and apply any available system -// update -// -// gc - trigger a garbage collection -// -// print_state - print go routine state of amber process - -/// Simple wrapper for interacting with the 'amber_ctl' tool running on the -/// Fuchsia device. -class FuchsiaAmberCtl { - /// Teaches the amber instance running on [device] about the Fuchsia package - /// server accessible via [configUrl]. - Future addSrc(FuchsiaDevice device, FuchsiaPackageServer server) async { - final String localIp = await device.hostAddress; - final String configUrl = 'http://[$localIp]:${server.port}/config.json'; - final RunResult result = await device.shell( - 'amber_ctl add_src -x -f $configUrl', - ); - return result.exitCode == 0; - } - - /// Instructs the amber instance running on [device] to forget about the - /// Fuchsia package server that it was accessing via [serverUrl]. - Future rmSrc(FuchsiaDevice device, FuchsiaPackageServer server) async { - final String localIp = await device.hostAddress; - final RunResult result = await device.shell( - 'amber_ctl rm_src -n http://[$localIp]:${server.port}/', - ); - return result.exitCode == 0; - } - - /// Instructs the amber instance running on [device] to prefetch the package - /// [packageName]. - Future getUp(FuchsiaDevice device, String packageName) async { - final RunResult result = await device.shell( - 'amber_ctl get_up -n $packageName', - ); - return result.exitCode == 0; - } - - /// Converts the amber source config created when [server] was set up to a - /// pkg_resolver repo config, and teaches the pkg_resolver instance running - /// on [device] about the [FuchsiaPackageServer]. - Future addRepoCfg(FuchsiaDevice device, FuchsiaPackageServer server) async { - final String localIp = await device.hostAddress; - final String configUrl = 'http://[$localIp]:${server.port}/config.json'; - final RunResult result = await device.shell( - 'amber_ctl add_repo_cfg -n ${server.name} -f $configUrl', - ); - return result.exitCode == 0; - } - - /// Instructs the pkg_resolver instance running on [device] to prefetch the - /// package [packageName]. - Future pkgCtlResolve( - FuchsiaDevice device, - FuchsiaPackageServer server, - String packageName, - ) async { - final String packageUrl = 'fuchsia-pkg://${server.name}/$packageName'; - final RunResult result = await device.shell('pkgctl resolve $packageUrl'); - return result.exitCode == 0; - } - - /// Instructs the pkg_resolver instance running on [device] to forget about - /// the Fuchsia package server that it was accessing via [serverUrl]. - Future pkgCtlRepoRemove( - FuchsiaDevice device, - FuchsiaPackageServer server, - ) async { - final String repoUrl = 'fuchsia-pkg://${server.name}'; - final RunResult result = await device.shell('pkgctl repo rm $repoUrl'); - return result.exitCode == 0; - } -} diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart index b0eac8a8eb5..b9d30896069 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart @@ -26,12 +26,12 @@ import '../globals.dart' as globals; import '../project.dart'; import '../vmservice.dart'; -import 'amber_ctl.dart'; import 'application_package.dart'; import 'fuchsia_build.dart'; import 'fuchsia_pm.dart'; import 'fuchsia_sdk.dart'; import 'fuchsia_workflow.dart'; +import 'pkgctl.dart'; import 'session_control.dart'; import 'tiles_ctl.dart'; @@ -40,14 +40,15 @@ FuchsiaDeviceTools get fuchsiaDeviceTools => context.get(); /// Fuchsia device-side tools. class FuchsiaDeviceTools { - FuchsiaAmberCtl _amberCtl; - FuchsiaAmberCtl get amberCtl => _amberCtl ??= FuchsiaAmberCtl(); + FuchsiaPkgctl _pkgctl; + FuchsiaPkgctl get pkgctl => _pkgctl ??= FuchsiaPkgctl(); FuchsiaTilesCtl _tilesCtl; FuchsiaTilesCtl get tilesCtl => _tilesCtl ??= FuchsiaTilesCtl(); FuchsiaSessionControl _sessionControl; - FuchsiaSessionControl get sessionControl => _sessionControl ??= FuchsiaSessionControl(); + FuchsiaSessionControl get sessionControl => + _sessionControl ??= FuchsiaSessionControl(); } final String _ipv4Loopback = InternetAddress.loopbackIPv4.address; @@ -369,56 +370,39 @@ class FuchsiaDevice extends Device { bool serverRegistered = false; String fuchsiaUrl; try { - if (await isSession) { - // Prefetch session_control - if (!await fuchsiaDeviceTools.amberCtl.getUp(this, 'session_control')) { - globals.printError('Failed to get amber to prefetch session_control'); - return LaunchResult.failed(); - } - } else { - // Ask amber to pre-fetch some things we'll need before setting up our own - // package server. This is to avoid relying on amber correctly using - // multiple package servers, support for which is in flux. - if (!await fuchsiaDeviceTools.amberCtl.getUp(this, 'tiles')) { - globals.printError('Failed to get amber to prefetch tiles'); - return LaunchResult.failed(); - } - if (!await fuchsiaDeviceTools.amberCtl.getUp(this, 'tiles_ctl')) { - globals.printError('Failed to get amber to prefetch tiles_ctl'); - return LaunchResult.failed(); - } - } - // Start up a package server. const String packageServerName = FuchsiaPackageServer.toolHost; - fuchsiaPackageServer = FuchsiaPackageServer( - packageRepo.path, packageServerName, '', port); + fuchsiaPackageServer = + FuchsiaPackageServer(packageRepo.path, packageServerName, '', port); if (!await fuchsiaPackageServer.start()) { globals.printError('Failed to start the Fuchsia package server'); return LaunchResult.failed(); } // Serve the application's package. - final File farArchive = package.farArchive( - debuggingOptions.buildInfo.mode); + final File farArchive = + package.farArchive(debuggingOptions.buildInfo.mode); if (!await fuchsiaPackageServer.addPackage(farArchive)) { globals.printError('Failed to add package to the package server'); return LaunchResult.failed(); } // Serve the flutter_runner. - final File flutterRunnerArchive = globals.fs.file(globals.artifacts.getArtifactPath( + final File flutterRunnerArchive = + globals.fs.file(globals.artifacts.getArtifactPath( Artifact.fuchsiaFlutterRunner, platform: await targetPlatform, mode: debuggingOptions.buildInfo.mode, )); if (!await fuchsiaPackageServer.addPackage(flutterRunnerArchive)) { - globals.printError('Failed to add flutter_runner package to the package server'); + globals.printError( + 'Failed to add flutter_runner package to the package server'); return LaunchResult.failed(); } // Teach the package controller about the package server. - if (!await fuchsiaDeviceTools.amberCtl.addRepoCfg(this, fuchsiaPackageServer)) { + if (!await fuchsiaDeviceTools.pkgctl + .addRepo(this, fuchsiaPackageServer)) { globals.printError('Failed to teach amber about the package server'); return LaunchResult.failed(); } @@ -439,20 +423,23 @@ class FuchsiaDevice extends Device { flutterRunnerName = 'flutter_jit_runner'; } } - if (!await fuchsiaDeviceTools.amberCtl.pkgCtlResolve( - this, fuchsiaPackageServer, flutterRunnerName)) { - globals.printError('Failed to get pkgctl to prefetch the flutter_runner'); + + if (!await fuchsiaDeviceTools.pkgctl + .resolve(this, fuchsiaPackageServer.name, flutterRunnerName)) { + globals + .printError('Failed to get pkgctl to prefetch the flutter_runner'); return LaunchResult.failed(); } // Tell the package controller to prefetch the app. - if (!await fuchsiaDeviceTools.amberCtl.pkgCtlResolve( - this, fuchsiaPackageServer, appName)) { + if (!await fuchsiaDeviceTools.pkgctl + .resolve(this, fuchsiaPackageServer.name, appName)) { globals.printError('Failed to get pkgctl to prefetch the package'); return LaunchResult.failed(); } - fuchsiaUrl = 'fuchsia-pkg://$packageServerName/$appName#meta/$appName.cmx'; + fuchsiaUrl = + 'fuchsia-pkg://$packageServerName/$appName#meta/$appName.cmx'; if (await isSession) { // Instruct session_control to start the app @@ -463,12 +450,14 @@ class FuchsiaDevice extends Device { } else { // Ensure tiles_ctl is started, and start the app. if (!await FuchsiaTilesCtl.ensureStarted(this)) { - globals.printError('Failed to ensure that tiles is started on the device'); + globals.printError( + 'Failed to ensure that tiles is started on the device'); return LaunchResult.failed(); } // Instruct tiles_ctl to start the app. - if (!await fuchsiaDeviceTools.tilesCtl.add(this, fuchsiaUrl, [])) { + if (!await fuchsiaDeviceTools.tilesCtl + .add(this, fuchsiaUrl, [])) { globals.printError('Failed to add the app to tiles'); return LaunchResult.failed(); } @@ -477,17 +466,18 @@ class FuchsiaDevice extends Device { // Try to un-teach the package controller about the package server if // needed. if (serverRegistered) { - await fuchsiaDeviceTools.amberCtl.pkgCtlRepoRemove(this, fuchsiaPackageServer); + await fuchsiaDeviceTools.pkgctl.rmRepo(this, fuchsiaPackageServer); } // Shutdown the package server and delete the package repo; globals.printTrace("Shutting down the tool's package server."); fuchsiaPackageServer?.stop(); - globals.printTrace("Removing the tool's package repo: at ${packageRepo.path}"); + globals.printTrace( + "Removing the tool's package repo: at ${packageRepo.path}"); try { packageRepo.deleteSync(recursive: true); } on Exception catch (e) { globals.printError('Failed to remove Fuchsia package repo directory ' - 'at ${packageRepo.path}: $e.'); + 'at ${packageRepo.path}: $e.'); } status.cancel(); } @@ -496,11 +486,12 @@ class FuchsiaDevice extends Device { globals.printTrace('App successfully started in a release mode.'); return LaunchResult.succeeded(); } - globals.printTrace('App started in a non-release mode. Setting up vmservice connection.'); + globals.printTrace( + 'App started in a non-release mode. Setting up vmservice connection.'); // In a debug or profile build, try to find the observatory uri. final FuchsiaIsolateDiscoveryProtocol discovery = - getIsolateDiscoveryProtocol(appName); + getIsolateDiscoveryProtocol(appName); try { final Uri observatoryUri = await discovery.uri; return LaunchResult.succeeded(observatoryUri: observatoryUri); @@ -535,14 +526,15 @@ class FuchsiaDevice extends Device { const TargetPlatform defaultTargetPlatform = TargetPlatform.fuchsia_arm64; if (!globals.fuchsiaArtifacts.hasSshConfig) { globals.printTrace('Could not determine Fuchsia target platform because ' - 'Fuchsia ssh configuration is missing.\n' - 'Defaulting to arm64.'); + 'Fuchsia ssh configuration is missing.\n' + 'Defaulting to arm64.'); return defaultTargetPlatform; } final RunResult result = await shell('uname -m'); if (result.exitCode != 0) { - globals.printError('Could not determine Fuchsia target platform type:\n$result\n' - 'Defaulting to arm64.'); + globals.printError( + 'Could not determine Fuchsia target platform type:\n$result\n' + 'Defaulting to arm64.'); return defaultTargetPlatform; } final String machine = result.stdout.trim(); @@ -553,7 +545,7 @@ class FuchsiaDevice extends Device { return TargetPlatform.fuchsia_x64; default: globals.printError('Unknown Fuchsia target platform "$machine". ' - 'Defaulting to arm64.'); + 'Defaulting to arm64.'); return defaultTargetPlatform; } } diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_kernel_compiler.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_kernel_compiler.dart index 0eb68bf0005..d8b0b45d778 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_kernel_compiler.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_kernel_compiler.dart @@ -41,20 +41,28 @@ class FuchsiaKernelCompiler { } final String? platformDill = globals.artifacts?.getArtifactPath( Artifact.platformKernelDill, - platform: TargetPlatform.fuchsia_arm64, // This file is not arch-specific. + platform: TargetPlatform.fuchsia_arm64, // This file is not arch-specific. mode: buildInfo.mode, ); if (platformDill == null || !globals.fs.isFileSync(platformDill)) { throwToolExit('Fuchsia platform file not found at "$platformDill"'); } List flags = [ - '--target', 'flutter_runner', - '--platform', platformDill, - '--filesystem-scheme', 'main-root', - '--filesystem-root', fsRoot, - '--packages', '$multiRootScheme:///$relativePackagesFile', - '--output', globals.fs.path.join(outDir, '$appName.dil'), - '--component-name', appName, + '--no-sound-null-safety', + '--target', + 'flutter_runner', + '--platform', + platformDill, + '--filesystem-scheme', + 'main-root', + '--filesystem-root', + fsRoot, + '--packages', + '$multiRootScheme:///$relativePackagesFile', + '--output', + globals.fs.path.join(outDir, '$appName.dil'), + '--component-name', + appName, ...getBuildInfoFlags(buildInfo: buildInfo, manifestPath: manifestPath) ]; diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart index 6447f38fa63..67d98543f04 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart @@ -104,6 +104,8 @@ class FuchsiaPM { repoPath, '-l', '$host:$port', + '-c', + '2', ]; final Process process = await globals.processUtils.start(command); process.stdout @@ -165,14 +167,15 @@ class FuchsiaPM { /// server.stop(); /// } class FuchsiaPackageServer { - factory FuchsiaPackageServer(String repo, String name, String host, int port) { + factory FuchsiaPackageServer( + String repo, String name, String host, int port) { return FuchsiaPackageServer._(repo, name, host, port); } FuchsiaPackageServer._(this._repo, this.name, this._host, this._port); static const String deviceHost = 'fuchsia.com'; - static const String toolHost = 'flutter_tool'; + static const String toolHost = 'flutter-tool'; final String _repo; final String _host; diff --git a/packages/flutter_tools/lib/src/fuchsia/pkgctl.dart b/packages/flutter_tools/lib/src/fuchsia/pkgctl.dart new file mode 100644 index 00000000000..26ff79ced0a --- /dev/null +++ b/packages/flutter_tools/lib/src/fuchsia/pkgctl.dart @@ -0,0 +1,46 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// @dart = 2.8 + +import '../base/process.dart'; + +import 'fuchsia_device.dart'; +import 'fuchsia_pm.dart'; + +/// Simple wrapper for interacting with the 'pkgctl' tool running on the +/// Fuchsia device. +class FuchsiaPkgctl { + /// Teaches pkgctl on [device] about the Fuchsia package server + Future addRepo( + FuchsiaDevice device, FuchsiaPackageServer server) async { + final String localIp = await device.hostAddress; + final String configUrl = 'http://[$localIp]:${server.port}/config.json'; + final RunResult result = + await device.shell('pkgctl repo add url -n ${server.name} $configUrl'); + return result.exitCode == 0; + } + + /// Instructs pkgctl instance running on [device] to forget about the + /// Fuchsia package server with the given name + /// pkgctl repo rm fuchsia-pkg://mycorp.com + Future rmRepo(FuchsiaDevice device, FuchsiaPackageServer server) async { + final RunResult result = await device.shell( + 'pkgctl repo rm fuchsia-pkg://${server.name}', + ); + return result.exitCode == 0; + } + + /// Instructs the pkgctl instance running on [device] to prefetch the package + /// with the given [packageUrl] hosted in the given [serverName]. + Future resolve( + FuchsiaDevice device, + String serverName, + String packageName, + ) async { + final String packageUrl = 'fuchsia-pkg://$serverName/$packageName'; + final RunResult result = await device.shell('pkgctl resolve $packageUrl'); + return result.exitCode == 0; + } +} diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart index 302e2192479..efcc9b704e5 100644 --- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart +++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart @@ -16,7 +16,6 @@ import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/device.dart'; -import 'package:flutter_tools/src/fuchsia/amber_ctl.dart'; import 'package:flutter_tools/src/fuchsia/application_package.dart'; import 'package:flutter_tools/src/fuchsia/fuchsia_dev_finder.dart'; import 'package:flutter_tools/src/fuchsia/fuchsia_device.dart'; @@ -24,6 +23,7 @@ import 'package:flutter_tools/src/fuchsia/fuchsia_ffx.dart'; import 'package:flutter_tools/src/fuchsia/fuchsia_kernel_compiler.dart'; import 'package:flutter_tools/src/fuchsia/fuchsia_pm.dart'; import 'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart'; +import 'package:flutter_tools/src/fuchsia/pkgctl.dart'; import 'package:flutter_tools/src/fuchsia/session_control.dart'; import 'package:flutter_tools/src/fuchsia/tiles_ctl.dart'; import 'package:flutter_tools/src/globals_null_migrated.dart' as globals; @@ -389,7 +389,8 @@ void main() { OperatingSystemUtils: () => osUtils, }); - testUsingContext('fail with correct LaunchResult when amber fails', () async { + testUsingContext('fail with correct LaunchResult when pkgctl fails', + () async { final LaunchResult launchResult = await setupAndStartApp(prebuilt: true, mode: BuildMode.release); expect(launchResult.started, isFalse); @@ -398,7 +399,7 @@ void main() { Artifacts: () => artifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => fakeSuccessfulProcessManager, - FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(amber: FailingAmberCtl()), + FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(pkgctl: FailingPkgctl()), FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), FuchsiaSdk: () => fuchsiaSdk, OperatingSystemUtils: () => osUtils, @@ -478,66 +479,40 @@ class FakeFuchsiaIsolateDiscoveryProtocol implements FuchsiaIsolateDiscoveryProt void dispose() {} } -class FakeFuchsiaAmberCtl implements FuchsiaAmberCtl { +class FakeFuchsiaPkgctl implements FuchsiaPkgctl { @override - Future addSrc(FuchsiaDevice device, FuchsiaPackageServer server) async { + Future addRepo( + FuchsiaDevice device, FuchsiaPackageServer server) async { return true; } @override - Future rmSrc(FuchsiaDevice device, FuchsiaPackageServer server) async { + Future resolve( + FuchsiaDevice device, String serverName, String packageName) async { return true; } @override - Future getUp(FuchsiaDevice device, String packageName) async { - return true; - } - - @override - Future addRepoCfg(FuchsiaDevice device, FuchsiaPackageServer server) async { - return true; - } - - @override - Future pkgCtlResolve(FuchsiaDevice device, FuchsiaPackageServer server, String packageName) async { - return true; - } - - @override - Future pkgCtlRepoRemove(FuchsiaDevice device, FuchsiaPackageServer server) async { + Future rmRepo(FuchsiaDevice device, FuchsiaPackageServer server) async { return true; } } -class FailingAmberCtl implements FuchsiaAmberCtl { +class FailingPkgctl implements FuchsiaPkgctl { @override - Future addSrc(FuchsiaDevice device, FuchsiaPackageServer server) async { + Future addRepo( + FuchsiaDevice device, FuchsiaPackageServer server) async { return false; } @override - Future rmSrc(FuchsiaDevice device, FuchsiaPackageServer server) async { + Future resolve( + FuchsiaDevice device, String serverName, String packageName) async { return false; } @override - Future getUp(FuchsiaDevice device, String packageName) async { - return false; - } - - @override - Future addRepoCfg(FuchsiaDevice device, FuchsiaPackageServer server) async { - return false; - } - - @override - Future pkgCtlResolve(FuchsiaDevice device, FuchsiaPackageServer server, String packageName) async { - return false; - } - - @override - Future pkgCtlRepoRemove(FuchsiaDevice device, FuchsiaPackageServer server) async { + Future rmRepo(FuchsiaDevice device, FuchsiaPackageServer server) async { return false; } } @@ -633,15 +608,15 @@ class FailingFuchsiaSessionControl implements FuchsiaSessionControl { class FakeFuchsiaDeviceTools implements FuchsiaDeviceTools { FakeFuchsiaDeviceTools({ - FuchsiaAmberCtl amber, + FuchsiaPkgctl pkgctl, FuchsiaTilesCtl tiles, FuchsiaSessionControl sessionControl, - }) : amberCtl = amber ?? FakeFuchsiaAmberCtl(), - tilesCtl = tiles ?? FakeFuchsiaTilesCtl(), - sessionControl = sessionControl ?? FakeFuchsiaSessionControl(); + }) : pkgctl = pkgctl ?? FakeFuchsiaPkgctl(), + tilesCtl = tiles ?? FakeFuchsiaTilesCtl(), + sessionControl = sessionControl ?? FakeFuchsiaSessionControl(); @override - final FuchsiaAmberCtl amberCtl; + final FuchsiaPkgctl pkgctl; @override final FuchsiaTilesCtl tilesCtl; diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_pm_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_pm_test.dart index 208f1079864..26cba71d676 100644 --- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_pm_test.dart +++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_pm_test.dart @@ -35,6 +35,8 @@ void main() { '', '-l', '127.0.0.1:43819', + '-c', + '2', ])); await FuchsiaPM().serve('', '127.0.0.1', 43819); @@ -52,6 +54,8 @@ void main() { '', '-l', '[fe80::ec4:7aff:fecc:ea8f%eno2]:43819', + '-c', + '2' ])); await FuchsiaPM().serve('', 'fe80::ec4:7aff:fecc:ea8f%eno2', 43819);