diff --git a/examples/stocks/fuchsia/meta/stocks.cmx b/examples/stocks/fuchsia/meta/stocks.cmx new file mode 100644 index 00000000000..6a1acee575b --- /dev/null +++ b/examples/stocks/fuchsia/meta/stocks.cmx @@ -0,0 +1,22 @@ +{ + "program": { + "data": "data/stocks" + }, + "sandbox": { + "services": [ + "fuchsia.cobalt.LoggerFactory", + "fuchsia.fonts.Provider", + "fuchsia.logger.LogSink", + "fuchsia.modular.Clipboard", + "fuchsia.modular.ContextWriter", + "fuchsia.modular.DeviceMap", + "fuchsia.modular.ModuleContext", + "fuchsia.sys.Environment", + "fuchsia.sys.Launcher", + "fuchsia.testing.runner.TestRunner", + "fuchsia.ui.input.ImeService", + "fuchsia.ui.policy.Presenter", + "fuchsia.ui.scenic.Scenic" + ] + } +} diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index 68f028ccffb..76c1d9b2fc0 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart @@ -69,7 +69,8 @@ class ApplicationPackageFactory { return applicationBinary == null ? WindowsApp.fromWindowsProject(FlutterProject.current().windows) : WindowsApp.fromPrebuiltApp(applicationBinary); - case TargetPlatform.fuchsia: + case TargetPlatform.fuchsia_arm64: + case TargetPlatform.fuchsia_x64: return applicationBinary == null ? FuchsiaApp.fromFuchsiaProject(FlutterProject.current().fuchsia) : FuchsiaApp.fromPrebuiltApp(applicationBinary); @@ -424,7 +425,8 @@ class ApplicationPackageStore { case TargetPlatform.ios: iOS ??= await IOSApp.fromIosProject(FlutterProject.current().ios); return iOS; - case TargetPlatform.fuchsia: + case TargetPlatform.fuchsia_arm64: + case TargetPlatform.fuchsia_x64: fuchsia ??= FuchsiaApp.fromFuchsiaProject(FlutterProject.current().fuchsia); return fuchsia; case TargetPlatform.darwin_x64: diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index c9892367765..fa12f561a74 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -58,6 +58,12 @@ enum Artifact { skyEnginePath, /// The location of the macOS engine podspec file. flutterMacOSPodspec, + + // Fuchsia artifacts from the engine prebuilts. + fuchsiaKernelCompiler, + fuchsiaPlatformDill, + fuchsiaPatchedSdk, + fuchsiaFlutterJitRunner, } String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMode mode ]) { @@ -130,6 +136,17 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo return 'FlutterMacOS.podspec'; case Artifact.webPlatformKernelDill: return 'flutter_ddc_sdk.dill'; + case Artifact.fuchsiaKernelCompiler: + return 'kernel_compiler.snapshot'; + case Artifact.fuchsiaPlatformDill: + return 'platform_strong.dill'; + case Artifact.fuchsiaPatchedSdk: + return 'flutter_runner_patched_sdk'; + case Artifact.fuchsiaFlutterJitRunner: + if (mode == BuildMode.debug || mode == BuildMode.profile) { + return 'flutter_jit_runner-0.far'; + } + return 'flutter_jit_product_runner-0.far'; } assert(false, 'Invalid artifact $artifact.'); return null; @@ -190,8 +207,10 @@ class CachedArtifacts extends Artifacts { return _getIosArtifactPath(artifact, platform, mode); case TargetPlatform.darwin_x64: return _getDarwinArtifactPath(artifact, platform, mode); + case TargetPlatform.fuchsia_arm64: + case TargetPlatform.fuchsia_x64: + return _getFuchsiaArtifactPath(artifact, platform, mode); case TargetPlatform.linux_x64: - case TargetPlatform.fuchsia: case TargetPlatform.windows_x64: case TargetPlatform.tester: case TargetPlatform.web_javascript: @@ -258,6 +277,28 @@ class CachedArtifacts extends Artifacts { } } + String _getFuchsiaArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) { + final String artifactFileName = _artifactToFileName(artifact, platform, mode); + final String root = fs.path.join( + cache.getArtifactDirectory('flutter_runner').path, + 'flutter', + fuchsiaArchForTargetPlatform(platform), + getNameForBuildMode(mode), + ); + switch (artifact) { + case Artifact.fuchsiaKernelCompiler: + return fs.path.join(root, 'jit', 'dart_binaries', artifactFileName); + case Artifact.fuchsiaPlatformDill: + return fs.path.join(root, 'jit', 'flutter_runner_patched_sdk', artifactFileName); + case Artifact.fuchsiaPatchedSdk: + case Artifact.fuchsiaFlutterJitRunner: + return fs.path.join(root, 'jit', artifactFileName); + default: + assert(false, 'Artifact $artifact not available for platform $platform.'); + return null; + } + } + String _getFlutterPatchedSdkPath(BuildMode mode) { final String engineArtifactsPath = cache.getArtifactDirectory('engine').path; return fs.path.join(engineArtifactsPath, 'common', @@ -339,7 +380,8 @@ class CachedArtifacts extends Artifacts { } final String suffix = mode != BuildMode.debug ? '-${snakeCase(getModeName(mode), '-')}' : ''; return fs.path.join(engineDir, platformName + suffix); - case TargetPlatform.fuchsia: + case TargetPlatform.fuchsia_arm64: + case TargetPlatform.fuchsia_x64: case TargetPlatform.tester: case TargetPlatform.web_javascript: assert(mode == null, 'Platform $platform does not support different build modes.'); @@ -430,6 +472,12 @@ class LocalEngineArtifacts extends Artifacts { return fs.path.join(_hostEngineOutPath, _artifactToFileName(artifact)); case Artifact.webPlatformKernelDill: return fs.path.join(_getFlutterWebSdkPath(), 'kernel', _artifactToFileName(artifact)); + case Artifact.fuchsiaKernelCompiler: + case Artifact.fuchsiaPlatformDill: + case Artifact.fuchsiaPatchedSdk: + case Artifact.fuchsiaFlutterJitRunner: + assert(false, 'Invalid local engine artifact $artifact.'); + return null; } assert(false, 'Invalid artifact $artifact.'); return null; diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart index fc6a8c8339e..56e7907e82c 100644 --- a/packages/flutter_tools/lib/src/build_info.dart +++ b/packages/flutter_tools/lib/src/build_info.dart @@ -314,7 +314,8 @@ enum TargetPlatform { darwin_x64, linux_x64, windows_x64, - fuchsia, + fuchsia_arm64, + fuchsia_x64, tester, web_javascript, } @@ -382,8 +383,10 @@ String getNameForTargetPlatform(TargetPlatform platform) { return 'linux-x64'; case TargetPlatform.windows_x64: return 'windows-x64'; - case TargetPlatform.fuchsia: - return 'fuchsia'; + case TargetPlatform.fuchsia_arm64: + return 'fuchsia-arm64'; + case TargetPlatform.fuchsia_x64: + return 'fuchsia-x64'; case TargetPlatform.tester: return 'flutter-tester'; case TargetPlatform.web_javascript: @@ -403,6 +406,10 @@ TargetPlatform getTargetPlatformForName(String platform) { return TargetPlatform.android_x64; case 'android-x86': return TargetPlatform.android_x86; + case 'fuchsia-arm64': + return TargetPlatform.fuchsia_arm64; + case 'fuchsia-x64': + return TargetPlatform.fuchsia_x64; case 'ios': return TargetPlatform.ios; case 'darwin-x64': @@ -463,6 +470,18 @@ String getPlatformNameForAndroidArch(AndroidArch arch) { return null; } +String fuchsiaArchForTargetPlatform(TargetPlatform targetPlatform) { + switch (targetPlatform) { + case TargetPlatform.fuchsia_arm64: + return 'arm64'; + case TargetPlatform.fuchsia_x64: + return 'x64'; + default: + assert(false); + return null; + } +} + HostPlatform getCurrentHostPlatform() { if (platform.isMacOS) { return HostPlatform.darwin_x64; diff --git a/packages/flutter_tools/lib/src/commands/build_fuchsia.dart b/packages/flutter_tools/lib/src/commands/build_fuchsia.dart index 39e0a8425d2..665fbc3208c 100644 --- a/packages/flutter_tools/lib/src/commands/build_fuchsia.dart +++ b/packages/flutter_tools/lib/src/commands/build_fuchsia.dart @@ -10,6 +10,7 @@ import '../base/platform.dart'; import '../build_info.dart'; import '../cache.dart'; import '../fuchsia/fuchsia_build.dart'; +import '../fuchsia/fuchsia_pm.dart'; import '../project.dart'; import '../runner/flutter_command.dart' show FlutterCommandResult; import 'build.dart'; @@ -19,6 +20,17 @@ class BuildFuchsiaCommand extends BuildSubCommand { BuildFuchsiaCommand({bool verboseHelp = false}) { usesTargetOption(); addBuildModeFlags(verboseHelp: verboseHelp); + argParser.addOption( + 'runner-source', + help: 'The package source to use for the flutter_runner. ' + '"${FuchsiaPackageServer.deviceHost}" implies using a runner already on the device. ' + '"${FuchsiaPackageServer.toolHost}" implies using a runner distributed with Flutter.', + allowed: [ + FuchsiaPackageServer.deviceHost, + FuchsiaPackageServer.toolHost, + ], + defaultsTo: FuchsiaPackageServer.toolHost, + ); } @override @@ -34,7 +46,7 @@ class BuildFuchsiaCommand extends BuildSubCommand { }; @override - String get description => 'build the Fuchsia target (Experimental).'; + String get description => 'Build the Fuchsia target (Experimental).'; @override Future runCommand() async { @@ -42,22 +54,24 @@ class BuildFuchsiaCommand extends BuildSubCommand { final BuildInfo buildInfo = getBuildInfo(); final FlutterProject flutterProject = FlutterProject.current(); if (!platform.isLinux && !platform.isMacOS) { - throwToolExit('"build Fuchsia" only supported on Linux and MacOS hosts.'); + throwToolExit('"build fuchsia" is only supported on Linux and MacOS hosts.'); } if (!flutterProject.fuchsia.existsSync()) { - throwToolExit('No Fuchsia project configured.'); + throwToolExit('No Fuchsia project is configured.'); } final String appName = flutterProject.fuchsia.project.manifest.appName; final String cmxPath = fs.path.join( flutterProject.fuchsia.meta.path, '$appName.cmx'); final File cmxFile = fs.file(cmxPath); if (!cmxFile.existsSync()) { - throwToolExit('Fuchsia build requires a .cmx file at $cmxPath for the app'); + throwToolExit('The Fuchsia build requires a .cmx file at $cmxPath for the app.'); } await buildFuchsia( - fuchsiaProject: flutterProject.fuchsia, - target: targetFile, - buildInfo: buildInfo); + fuchsiaProject: flutterProject.fuchsia, + target: targetFile, + buildInfo: buildInfo, + runnerPackageSource: argResults['runner-source'], + ); return null; } } diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 9fdd89939e8..f9ee5404741 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart @@ -178,7 +178,8 @@ class DeviceManager { if (hasSpecifiedAllDevices) { devices = [ for (Device device in devices) - if (await device.targetPlatform != TargetPlatform.fuchsia && + if (await device.targetPlatform != TargetPlatform.fuchsia_arm64 && + await device.targetPlatform != TargetPlatform.fuchsia_x64 && await device.targetPlatform != TargetPlatform.web_javascript) device, ]; @@ -339,7 +340,8 @@ abstract class Device { case TargetPlatform.darwin_x64: case TargetPlatform.linux_x64: case TargetPlatform.windows_x64: - case TargetPlatform.fuchsia: + case TargetPlatform.fuchsia_arm64: + case TargetPlatform.fuchsia_x64: default: return false; } diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_build.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_build.dart index c6bba280051..9c855d2779b 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_build.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_build.dart @@ -38,6 +38,7 @@ Future buildFuchsia({ @required FuchsiaProject fuchsiaProject, @required String target, // E.g., lib/main.dart BuildInfo buildInfo = BuildInfo.debug, + String runnerPackageSource = FuchsiaPackageServer.toolHost, }) async { final Directory outDir = fs.directory(getFuchsiaBuildDirectory()); if (!outDir.existsSync()) { @@ -50,7 +51,7 @@ Future buildFuchsia({ await _timedBuildStep('fuchsia-build-assets', () => _buildAssets(fuchsiaProject, target, buildInfo)); await _timedBuildStep('fuchsia-build-package', - () => _buildPackage(fuchsiaProject, target, buildInfo)); + () => _buildPackage(fuchsiaProject, target, buildInfo, runnerPackageSource)); } Future _buildAssets( @@ -85,7 +86,7 @@ Future _buildAssets( await outFile.close(); } -void _rewriteCmx(BuildMode mode, File src, File dst) { +void _rewriteCmx(BuildMode mode, String runnerPackageSource, File src, File dst) { final Map cmx = json.decode(src.readAsStringSync()); // If the app author has already specified the runner in the cmx file, then // do not override it with something else. @@ -106,7 +107,7 @@ void _rewriteCmx(BuildMode mode, File src, File dst) { throwToolExit('Fuchsia does not support build mode "$mode"'); break; } - cmx['runner'] = 'fuchsia-pkg://fuchsia.com/$runner#meta/$runner.cmx'; + cmx['runner'] = 'fuchsia-pkg://$runnerPackageSource/$runner#meta/$runner.cmx'; dst.writeAsStringSync(json.encode(cmx)); } @@ -115,6 +116,7 @@ Future _buildPackage( FuchsiaProject fuchsiaProject, String target, // lib/main.dart BuildInfo buildInfo, + String runnerPackageSource, ) async { final String outDir = getFuchsiaBuildDirectory(); final String pkgDir = fs.path.join(outDir, 'pkg'); @@ -132,7 +134,7 @@ Future _buildPackage( final File srcCmx = fs.file(fs.path.join(fuchsiaProject.meta.path, '$appName.cmx')); final File dstCmx = fs.file(fs.path.join(outDir, '$appName.cmx')); - _rewriteCmx(buildInfo.mode, srcCmx, dstCmx); + _rewriteCmx(buildInfo.mode, runnerPackageSource, srcCmx, dstCmx); // Concatenate dilpmanifest and pkgassets into package_manifest. final File manifestFile = fs.file(packageManifest); diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart index 3e10f902132..07be37c0363 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart @@ -272,13 +272,15 @@ class FuchsiaDevice extends Device { } // Start up a package server. - const String packageServerName = 'flutter_tool'; + const String packageServerName = FuchsiaPackageServer.toolHost; fuchsiaPackageServer = FuchsiaPackageServer( packageRepo.path, packageServerName, host, port); if (!await fuchsiaPackageServer.start()) { printError('Failed to start the Fuchsia package server'); return LaunchResult.failed(); } + + // Serve the application's package. final File farArchive = package.farArchive( debuggingOptions.buildInfo.mode); if (!await fuchsiaPackageServer.addPackage(farArchive)) { @@ -286,6 +288,17 @@ class FuchsiaDevice extends Device { return LaunchResult.failed(); } + // Serve the flutter_runner. + final File flutterRunnerArchive = fs.file(artifacts.getArtifactPath( + Artifact.fuchsiaFlutterJitRunner, + platform: await targetPlatform, + mode: debuggingOptions.buildInfo.mode, + )); + if (!await fuchsiaPackageServer.addPackage(flutterRunnerArchive)) { + 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)) { printError('Failed to teach amber about the package server'); @@ -293,6 +306,18 @@ class FuchsiaDevice extends Device { } serverRegistered = true; + // Tell the package controller to prefetch the flutter_runner. + String flutterRunnerName = 'flutter_jit_runner'; + if (!debuggingOptions.buildInfo.isDebug && + !debuggingOptions.buildInfo.isProfile) { + flutterRunnerName = 'flutter_jit_product_runner'; + } + if (!await fuchsiaDeviceTools.amberCtl.pkgCtlResolve( + this, fuchsiaPackageServer, flutterRunnerName)) { + 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)) { @@ -353,8 +378,30 @@ class FuchsiaDevice extends Device { return true; } + TargetPlatform _targetPlatform; + + Future _queryTargetPlatform() async { + final RunResult result = await shell('uname -m'); + if (result.exitCode != 0) { + printError('Could not determine Fuchsia target platform type:\n$result\n' + 'Defaulting to arm64.'); + return TargetPlatform.fuchsia_arm64; + } + final String machine = result.stdout.trim(); + switch (machine) { + case 'aarch64': + return TargetPlatform.fuchsia_arm64; + case 'x86_64': + return TargetPlatform.fuchsia_x64; + default: + printError('Unknown Fuchsia target platform "$machine". ' + 'Defaulting to arm64.'); + return TargetPlatform.fuchsia_arm64; + } + } + @override - Future get targetPlatform async => TargetPlatform.fuchsia; + Future get targetPlatform async => _targetPlatform ??= await _queryTargetPlatform(); @override Future get sdkNameAndVersion async { @@ -389,8 +436,16 @@ class FuchsiaDevice extends Device { OverrideArtifacts get artifactOverrides { return _artifactOverrides ??= OverrideArtifacts( parent: Artifacts.instance, - platformKernelDill: fuchsiaArtifacts.platformKernelDill, - flutterPatchedSdk: fuchsiaArtifacts.flutterPatchedSdk, + platformKernelDill: fs.file(artifacts.getArtifactPath( + Artifact.fuchsiaPlatformDill, + platform: TargetPlatform.fuchsia_x64, + mode: BuildMode.debug, + )), + flutterPatchedSdk: fs.file(artifacts.getArtifactPath( + Artifact.fuchsiaPatchedSdk, + platform: TargetPlatform.fuchsia_x64, + mode: BuildMode.debug, + )), ); } OverrideArtifacts _artifactOverrides; @@ -535,7 +590,7 @@ class FuchsiaIsolateDiscoveryProtocol { 'Waiting for a connection from $_isolateName on ${_device.name}...', timeout: null, // could take an arbitrary amount of time ); - _pollingTimer ??= Timer(_pollDuration, _findIsolate); + unawaited(_findIsolate()); // Completes the _foundUri Future. return _foundUri.future.then((Uri uri) { _uri = uri; return uri; 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 cccc8bbc651..aabe9a88d69 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_kernel_compiler.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_kernel_compiler.dart @@ -15,8 +15,6 @@ import '../convert.dart'; import '../globals.dart'; import '../project.dart'; -import 'fuchsia_sdk.dart'; - /// This is a simple wrapper around the custom kernel compiler from the Fuchsia /// SDK. class FuchsiaKernelCompiler { @@ -30,20 +28,32 @@ class FuchsiaKernelCompiler { BuildInfo buildInfo = BuildInfo.debug, }) async { // TODO(zra): Use filesystem root and scheme information from buildInfo. - if (fuchsiaArtifacts.kernelCompiler == null) { - throwToolExit('Fuchisa kernel compiler not found'); - } const String multiRootScheme = 'main-root'; final String packagesFile = fuchsiaProject.project.packagesFile.path; final String outDir = getFuchsiaBuildDirectory(); final String appName = fuchsiaProject.project.manifest.appName; final String fsRoot = fuchsiaProject.project.directory.path; - final String relativePackagesFile = - fs.path.relative(packagesFile, from: fsRoot); + final String relativePackagesFile = fs.path.relative(packagesFile, from: fsRoot); final String manifestPath = fs.path.join(outDir, '$appName.dilpmanifest'); + final String kernelCompiler = artifacts.getArtifactPath( + Artifact.fuchsiaKernelCompiler, + platform: TargetPlatform.fuchsia_x64, // This file is not arch-specific. + mode: BuildMode.debug, + ); + if (!fs.isFileSync(kernelCompiler)) { + throwToolExit('Fuchisa kernel compiler not found at "$kernelCompiler"'); + } + final String platformDill = artifacts.getArtifactPath( + Artifact.fuchsiaPlatformDill, + platform: TargetPlatform.fuchsia_x64, // This file is not arch-specific. + mode: buildInfo.mode, + ); + if (!fs.isFileSync(platformDill)) { + throwToolExit('Fuchisa platform file not found at "$platformDill"'); + } List flags = [ '--target', 'flutter_runner', - '--platform', fuchsiaArtifacts.platformKernelDill.path, + '--platform', platformDill, '--filesystem-scheme', 'main-root', '--filesystem-root', fsRoot, '--packages', '$multiRootScheme:///$relativePackagesFile', @@ -82,7 +92,7 @@ class FuchsiaKernelCompiler { final List command = [ artifacts.getArtifactPath(Artifact.engineDartBinary), - fuchsiaArtifacts.kernelCompiler.path, + artifacts.getArtifactPath(Artifact.fuchsiaKernelCompiler), ...flags, ]; final Process process = await processUtils.start(command); diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart index 5a0eda6dab6..80ad58ebc56 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart @@ -178,6 +178,9 @@ class FuchsiaPM { class FuchsiaPackageServer { FuchsiaPackageServer(this._repo, this.name, this._host, this._port); + static const String deviceHost = 'fuchsia.com'; + static const String toolHost = 'flutter_tool'; + final String _repo; final String _host; final int _port; diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart index 11cda6c49a1..0474c48380e 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart @@ -102,9 +102,6 @@ class FuchsiaArtifacts { FuchsiaArtifacts({ this.sshConfig, this.devFinder, - this.platformKernelDill, - this.flutterPatchedSdk, - this.kernelCompiler, this.pm, }); @@ -119,19 +116,6 @@ class FuchsiaArtifacts { // Don't try to find the artifacts on platforms that are not supported. return FuchsiaArtifacts(); } - final String fuchsia = Cache.instance.getArtifactDirectory('fuchsia').path; - final String tools = fs.path.join(fuchsia, 'tools'); - final String dartPrebuilts = fs.path.join(tools, 'dart_prebuilts'); - - final File devFinder = fs.file(fs.path.join(tools, 'dev_finder')); - final File platformDill = fs.file(fs.path.join( - dartPrebuilts, 'flutter_runner', 'platform_strong.dill')); - final File patchedSdk = fs.file(fs.path.join( - dartPrebuilts, 'flutter_runner')); - final File kernelCompiler = fs.file(fs.path.join( - dartPrebuilts, 'kernel_compiler.snapshot')); - final File pm = fs.file(fs.path.join(tools, 'pm')); - // If FUCHSIA_BUILD_DIR is defined, then look for the ssh_config dir // relative to it. Next, if FUCHSIA_SSH_CONFIG is defined, then use it. // TODO(zra): Consider passing the ssh config path in with a flag. @@ -142,12 +126,15 @@ class FuchsiaArtifacts { } else if (platform.environment.containsKey(_kFuchsiaSshConfig)) { sshConfig = fs.file(platform.environment[_kFuchsiaSshConfig]); } + + final String fuchsia = Cache.instance.getArtifactDirectory('fuchsia').path; + final String tools = fs.path.join(fuchsia, 'tools'); + final File devFinder = fs.file(fs.path.join(tools, 'dev_finder')); + final File pm = fs.file(fs.path.join(tools, 'pm')); + return FuchsiaArtifacts( sshConfig: sshConfig, devFinder: devFinder.existsSync() ? devFinder : null, - platformKernelDill: platformDill.existsSync() ? platformDill : null, - flutterPatchedSdk: patchedSdk.existsSync() ? patchedSdk : null, - kernelCompiler: kernelCompiler.existsSync() ? kernelCompiler : null, pm: pm.existsSync() ? pm : null, ); } @@ -163,15 +150,6 @@ class FuchsiaArtifacts { /// Fuchsia devices. final File devFinder; - /// The location of the Fuchsia-specific platform dill. - final File platformKernelDill; - - /// The directory containing [platformKernelDill]. - final File flutterPatchedSdk; - - /// The snapshot of the Fuchsia kernel compiler. - final File kernelCompiler; - /// The pm tool. final File pm; } diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 8eff88210ff..00087a1fd30 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -734,7 +734,8 @@ DevelopmentArtifact _artifactFromTargetPlatform(TargetPlatform targetPlatform) { return DevelopmentArtifact.linux; } return null; - case TargetPlatform.fuchsia: + case TargetPlatform.fuchsia_arm64: + case TargetPlatform.fuchsia_x64: case TargetPlatform.tester: // No artifacts currently supported. return null; diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart index 39924abe494..84930341ccf 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart @@ -27,23 +27,18 @@ void main() { MockPlatform linuxPlatform; MockPlatform windowsPlatform; MockFuchsiaSdk fuchsiaSdk; - MockFuchsiaArtifacts fuchsiaArtifacts; - MockFuchsiaArtifacts fuchsiaArtifactsNoCompiler; setUp(() { linuxPlatform = MockPlatform(); windowsPlatform = MockPlatform(); fuchsiaSdk = MockFuchsiaSdk(); - fuchsiaArtifacts = MockFuchsiaArtifacts(); - fuchsiaArtifactsNoCompiler = MockFuchsiaArtifacts(); when(linuxPlatform.isLinux).thenReturn(true); when(linuxPlatform.isWindows).thenReturn(false); + when(linuxPlatform.isMacOS).thenReturn(false); when(windowsPlatform.isWindows).thenReturn(true); when(windowsPlatform.isLinux).thenReturn(false); when(windowsPlatform.isMacOS).thenReturn(false); - when(fuchsiaArtifacts.kernelCompiler).thenReturn(MockFile()); - when(fuchsiaArtifactsNoCompiler.kernelCompiler).thenReturn(null); }); group('Fuchsia build fails gracefully when', () { @@ -58,7 +53,6 @@ void main() { Platform: () => linuxPlatform, FileSystem: () => MemoryFileSystem(), ProcessManager: () => FakeProcessManager.any(), - FuchsiaArtifacts: () => fuchsiaArtifacts, }); testUsingContext('there is no cmx file', () async { @@ -76,7 +70,6 @@ void main() { Platform: () => linuxPlatform, FileSystem: () => MemoryFileSystem(), ProcessManager: () => FakeProcessManager.any(), - FuchsiaArtifacts: () => fuchsiaArtifacts, }); testUsingContext('on Windows platform', () async { @@ -99,7 +92,6 @@ void main() { Platform: () => windowsPlatform, FileSystem: () => MemoryFileSystem(), ProcessManager: () => FakeProcessManager.any(), - FuchsiaArtifacts: () => fuchsiaArtifacts, }); testUsingContext('there is no Fuchsia kernel compiler', () async { @@ -122,7 +114,6 @@ void main() { Platform: () => linuxPlatform, FileSystem: () => MemoryFileSystem(), ProcessManager: () => FakeProcessManager.any(), - FuchsiaArtifacts: () => fuchsiaArtifactsNoCompiler, }); }); @@ -233,7 +224,3 @@ class MockFuchsiaSdk extends Mock implements FuchsiaSdk { final FuchsiaKernelCompiler fuchsiaKernelCompiler = MockFuchsiaKernelCompiler(); } - -class MockFile extends Mock implements File {} - -class MockFuchsiaArtifacts extends Mock implements FuchsiaArtifacts {} diff --git a/packages/flutter_tools/test/general.shard/device_test.dart b/packages/flutter_tools/test/general.shard/device_test.dart index f286c5ebe6e..3895079d695 100644 --- a/packages/flutter_tools/test/general.shard/device_test.dart +++ b/packages/flutter_tools/test/general.shard/device_test.dart @@ -57,7 +57,7 @@ void main() { webDevice = _MockDevice('webby', 'webby') ..targetPlatform = Future.value(TargetPlatform.web_javascript); fuchsiaDevice = _MockDevice('fuchsiay', 'fuchsiay') - ..targetPlatform = Future.value(TargetPlatform.fuchsia); + ..targetPlatform = Future.value(TargetPlatform.fuchsia_x64); }); testUsingContext('chooses ephemeral device', () async { diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart index c7e77e1bdc1..d94a8a27830 100644 --- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart +++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart @@ -12,6 +12,7 @@ import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/io.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/time.dart'; import 'package:flutter_tools/src/build_info.dart'; @@ -36,8 +37,13 @@ import '../../src/context.dart'; void main() { group('fuchsia device', () { MemoryFileSystem memoryFileSystem; + MockFile sshConfig; + MockProcessUtils mockProcessUtils; setUp(() { memoryFileSystem = MemoryFileSystem(); + sshConfig = MockFile(); + mockProcessUtils = MockProcessUtils(); + when(sshConfig.absolute).thenReturn(sshConfig); }); testUsingContext('stores the requested id and name', () { @@ -96,44 +102,78 @@ void main() { FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), }); + + testUsingContext('targetPlatform arm64 works', () async { + when(mockProcessUtils.run(any)).thenAnswer((Invocation _) { + return Future.value(RunResult(ProcessResult(1, 0, 'aarch64', ''), [''])); + }); + final FuchsiaDevice device = FuchsiaDevice('123'); + expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64); + }, overrides: { + FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), + ProcessUtils: () => mockProcessUtils, + }); + + testUsingContext('targetPlatform x64 works', () async { + when(mockProcessUtils.run(any)).thenAnswer((Invocation _) { + return Future.value(RunResult(ProcessResult(1, 0, 'x86_64', ''), [''])); + }); + final FuchsiaDevice device = FuchsiaDevice('123'); + expect(await device.targetPlatform, TargetPlatform.fuchsia_x64); + }, overrides: { + FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), + ProcessUtils: () => mockProcessUtils, + }); }); group('Fuchsia device artifact overrides', () { - MockFile devFinder; - MockFile sshConfig; - MockFile platformDill; - MockFile patchedSdk; + MemoryFileSystem memoryFileSystem; + File devFinder; + File sshConfig; + File platformDill; + File patchedSdk; + MockArtifacts mockArtifacts; setUp(() { - devFinder = MockFile(); - sshConfig = MockFile(); - platformDill = MockFile(); - patchedSdk = MockFile(); - when(devFinder.absolute).thenReturn(devFinder); - when(sshConfig.absolute).thenReturn(sshConfig); - when(platformDill.absolute).thenReturn(platformDill); - when(patchedSdk.absolute).thenReturn(patchedSdk); + memoryFileSystem = MemoryFileSystem(); + devFinder = memoryFileSystem.file('dev_finder'); + sshConfig = memoryFileSystem.file('ssh_config'); + platformDill = memoryFileSystem.file('platform_strong.dill'); + patchedSdk = memoryFileSystem.file('flutter_runner_patched_sdk'); + + mockArtifacts = MockArtifacts(); + when(mockArtifacts.getArtifactPath( + Artifact.fuchsiaPlatformDill, + platform: anyNamed('platform'), + mode: anyNamed('mode'), + )).thenReturn(platformDill.path); + when(mockArtifacts.getArtifactPath( + Artifact.fuchsiaPatchedSdk, + platform: anyNamed('platform'), + mode: anyNamed('mode'), + )).thenReturn(patchedSdk.path); }); testUsingContext('exist', () async { final FuchsiaDevice device = FuchsiaDevice('fuchsia-device'); expect(device.artifactOverrides, isNotNull); - expect(device.artifactOverrides.platformKernelDill, equals(platformDill)); - expect(device.artifactOverrides.flutterPatchedSdk, equals(patchedSdk)); + expect(device.artifactOverrides.platformKernelDill.path, equals(platformDill.path)); + expect(device.artifactOverrides.flutterPatchedSdk.path, equals(patchedSdk.path)); }, overrides: { + Artifacts: () => mockArtifacts, + FileSystem: () => memoryFileSystem, FuchsiaArtifacts: () => FuchsiaArtifacts( sshConfig: sshConfig, devFinder: devFinder, - platformKernelDill: platformDill, - flutterPatchedSdk: patchedSdk, ), + ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('are used', () async { final FuchsiaDevice device = FuchsiaDevice('fuchsia-device'); expect(device.artifactOverrides, isNotNull); - expect(device.artifactOverrides.platformKernelDill, equals(platformDill)); - expect(device.artifactOverrides.flutterPatchedSdk, equals(patchedSdk)); + expect(device.artifactOverrides.platformKernelDill.path, equals(platformDill.path)); + expect(device.artifactOverrides.flutterPatchedSdk.path, equals(patchedSdk.path)); await context.run( body: () { expect(Artifacts.instance.getArtifactPath(Artifact.platformKernelDill), @@ -146,12 +186,13 @@ void main() { }, ); }, overrides: { + Artifacts: () => mockArtifacts, + FileSystem: () => memoryFileSystem, FuchsiaArtifacts: () => FuchsiaArtifacts( sshConfig: sshConfig, devFinder: devFinder, - platformKernelDill: platformDill, - flutterPatchedSdk: patchedSdk, ), + ProcessManager: () => FakeProcessManager.any(), }); }); @@ -339,15 +380,23 @@ void main() { }); group(FuchsiaIsolateDiscoveryProtocol, () { + MockPortForwarder portForwarder; + MockVMService vmService; + MockVM vm; + + setUp(() { + portForwarder = MockPortForwarder(); + vmService = MockVMService(); + vm = MockVM(); + + when(vm.vmService).thenReturn(vmService); + when(vmService.vm).thenReturn(vm); + }); + Future findUri(List views, String expectedIsolateName) { - final MockPortForwarder portForwarder = MockPortForwarder(); - final MockVMService vmService = MockVMService(); - final MockVM vm = MockVM(); - vm.vmService = vmService; - vmService.vm = vm; - vm.views = views; + when(vm.views).thenReturn(views); for (MockFlutterView view in views) { - view.owner = vm; + when(view.owner).thenReturn(vm); } final MockFuchsiaDevice fuchsiaDevice = MockFuchsiaDevice('123', portForwarder, false); @@ -404,11 +453,47 @@ void main() { FakeOperatingSystemUtils osUtils; FakeFuchsiaDeviceTools fuchsiaDeviceTools; MockFuchsiaSdk fuchsiaSdk; + MockFuchsiaArtifacts fuchsiaArtifacts; + MockArtifacts mockArtifacts; + + File compilerSnapshot; + File platformDill; + File patchedSdk; + File runner; + setUp(() { memoryFileSystem = MemoryFileSystem(); osUtils = FakeOperatingSystemUtils(); fuchsiaDeviceTools = FakeFuchsiaDeviceTools(); fuchsiaSdk = MockFuchsiaSdk(); + fuchsiaArtifacts = MockFuchsiaArtifacts(); + + compilerSnapshot = memoryFileSystem.file('kernel_compiler.snapshot')..createSync(); + platformDill = memoryFileSystem.file('platform_strong.dill')..createSync(); + patchedSdk = memoryFileSystem.file('flutter_runner_patched_sdk')..createSync(); + runner = memoryFileSystem.file('flutter_jit_runner')..createSync(); + + mockArtifacts = MockArtifacts(); + when(mockArtifacts.getArtifactPath( + Artifact.fuchsiaKernelCompiler, + platform: anyNamed('platform'), + mode: anyNamed('mode'), + )).thenReturn(compilerSnapshot.path); + when(mockArtifacts.getArtifactPath( + Artifact.fuchsiaPlatformDill, + platform: anyNamed('platform'), + mode: anyNamed('mode'), + )).thenReturn(platformDill.path); + when(mockArtifacts.getArtifactPath( + Artifact.fuchsiaPatchedSdk, + platform: anyNamed('platform'), + mode: anyNamed('mode'), + )).thenReturn(patchedSdk.path); + when(mockArtifacts.getArtifactPath( + Artifact.fuchsiaFlutterJitRunner, + platform: anyNamed('platform'), + mode: anyNamed('mode'), + )).thenReturn(runner.path); }); Future setupAndStartApp({ @@ -434,11 +519,12 @@ void main() { app = BuildableFuchsiaApp(project: FlutterProject.current().fuchsia); } - final DebuggingOptions debuggingOptions = - DebuggingOptions.disabled(BuildInfo(mode, null)); - return await device.startApp(app, - prebuiltApplication: prebuilt, - debuggingOptions: debuggingOptions); + final DebuggingOptions debuggingOptions = DebuggingOptions.disabled(BuildInfo(mode, null)); + return await device.startApp( + app, + prebuiltApplication: prebuilt, + debuggingOptions: debuggingOptions, + ); } testUsingContext('start prebuilt in release mode', () async { @@ -447,9 +533,11 @@ void main() { expect(launchResult.started, isTrue); expect(launchResult.hasObservatory, isFalse); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => fuchsiaDeviceTools, + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => fuchsiaSdk, OperatingSystemUtils: () => osUtils, }); @@ -472,9 +560,11 @@ void main() { expect(launchResult.hasObservatory, isFalse); expect(await device.stopApp(app), isTrue); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => fuchsiaDeviceTools, + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => fuchsiaSdk, OperatingSystemUtils: () => osUtils, }); @@ -485,9 +575,11 @@ void main() { expect(launchResult.started, isTrue); expect(launchResult.hasObservatory, isTrue); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => fuchsiaDeviceTools, + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => fuchsiaSdk, OperatingSystemUtils: () => osUtils, }); @@ -498,9 +590,11 @@ void main() { expect(launchResult.started, isTrue); expect(launchResult.hasObservatory, isFalse); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => fuchsiaDeviceTools, + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => fuchsiaSdk, OperatingSystemUtils: () => osUtils, }); @@ -511,9 +605,11 @@ void main() { expect(launchResult.started, isTrue); expect(launchResult.hasObservatory, isTrue); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => fuchsiaDeviceTools, + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => fuchsiaSdk, OperatingSystemUtils: () => osUtils, }); @@ -524,9 +620,11 @@ void main() { expect(launchResult.started, isFalse); expect(launchResult.hasObservatory, isFalse); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => fuchsiaDeviceTools, + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => MockFuchsiaSdk(devFinder: FailingDevFinder()), OperatingSystemUtils: () => osUtils, }); @@ -537,9 +635,11 @@ void main() { expect(launchResult.started, isFalse); expect(launchResult.hasObservatory, isFalse); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => fuchsiaDeviceTools, + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => MockFuchsiaSdk(pm: FailingPM()), OperatingSystemUtils: () => osUtils, }); @@ -550,9 +650,11 @@ void main() { expect(launchResult.started, isFalse); expect(launchResult.hasObservatory, isFalse); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(amber: FailingAmberCtl()), + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => fuchsiaSdk, OperatingSystemUtils: () => osUtils, }); @@ -563,9 +665,11 @@ void main() { expect(launchResult.started, isFalse); expect(launchResult.hasObservatory, isFalse); }, overrides: { + Artifacts: () => mockArtifacts, FileSystem: () => memoryFileSystem, ProcessManager: () => FakeProcessManager.any(), FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(tiles: FailingTilesCtl()), + FuchsiaArtifacts: () => fuchsiaArtifacts, FuchsiaSdk: () => fuchsiaSdk, OperatingSystemUtils: () => osUtils, }); @@ -643,10 +747,16 @@ class FuchsiaModulePackage extends ApplicationPackage { final String name; } +class MockArtifacts extends Mock implements Artifacts {} + +class MockFuchsiaArtifacts extends Mock implements FuchsiaArtifacts {} + class MockProcessManager extends Mock implements ProcessManager {} class MockProcessResult extends Mock implements ProcessResult {} +class MockProcessUtils extends Mock implements ProcessUtils {} + class MockFile extends Mock implements File {} class MockProcess extends Mock implements Process {} @@ -690,31 +800,22 @@ class MockFuchsiaDevice extends Mock implements FuchsiaDevice { final String id; @override final DevicePortForwarder portForwarder; + + @override + Future get targetPlatform async => TargetPlatform.fuchsia_arm64; } class MockPortForwarder extends Mock implements DevicePortForwarder {} -class MockVMService extends Mock implements VMService { - @override - VM vm; -} +class MockVMService extends Mock implements VMService {} -class MockVM extends Mock implements VM { - @override - VMService vmService; - - @override - List views; -} +class MockVM extends Mock implements VM {} class MockFlutterView extends Mock implements FlutterView { MockFlutterView(this.uiIsolate); @override final Isolate uiIsolate; - - @override - ServiceObjectOwner owner; } class MockIsolate extends Mock implements Isolate { @@ -731,6 +832,9 @@ class FuchsiaDeviceWithFakeDiscovery extends FuchsiaDevice { FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(String isolateName) { return FakeFuchsiaIsolateDiscoveryProtocol(); } + + @override + Future get targetPlatform async => TargetPlatform.fuchsia_arm64; } class FakeFuchsiaIsolateDiscoveryProtocol implements FuchsiaIsolateDiscoveryProtocol {