| // 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. |
| |
| import 'package:file/file.dart'; |
| |
| import '../artifacts.dart'; |
| import '../base/common.dart'; |
| import '../base/io.dart'; |
| import '../base/process.dart'; |
| import '../build_info.dart'; |
| import '../cache.dart'; |
| import '../globals.dart' as globals; |
| import '../project.dart'; |
| import '../runner/flutter_command.dart' show FlutterCommandResult; |
| import '../windows/build_windows.dart'; |
| import 'build.dart'; |
| |
| class BuildPreviewCommand extends BuildSubCommand { |
| BuildPreviewCommand({ |
| required super.logger, |
| required super.verboseHelp, |
| required this.fs, |
| required this.flutterRoot, |
| required this.processUtils, |
| required this.artifacts, |
| }); |
| |
| @override |
| final String name = '_preview'; |
| |
| @override |
| final bool hidden = true; |
| |
| @override |
| Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{ |
| DevelopmentArtifact.windows, |
| }; |
| |
| @override |
| final String description = 'Build Flutter preview (desktop) app.'; |
| |
| final FileSystem fs; |
| final String flutterRoot; |
| final ProcessUtils processUtils; |
| final Artifacts artifacts; |
| |
| static const BuildInfo buildInfo = BuildInfo( |
| BuildMode.debug, |
| null, // no flavor |
| // users may add icons later |
| treeShakeIcons: false, |
| ); |
| |
| @override |
| void requiresPubspecYaml() {} |
| |
| static const String appName = 'flutter_preview'; |
| |
| @override |
| Future<FlutterCommandResult> runCommand() async { |
| if (!globals.platform.isWindows) { |
| throwToolExit('"build _preview" is currently only supported on Windows hosts.'); |
| } |
| final Directory targetDir = fs.systemTempDirectory.createTempSync('flutter-build-preview'); |
| try { |
| final FlutterProject flutterProject = await _createProject(targetDir); |
| await buildWindows( |
| flutterProject.windows, |
| buildInfo, |
| ); |
| |
| final File previewDevice = targetDir |
| .childDirectory(getWindowsBuildDirectory(TargetPlatform.windows_x64)) |
| .childDirectory('runner') |
| .childDirectory('Debug') |
| .childFile('$appName.exe'); |
| if (!previewDevice.existsSync()) { |
| throw StateError('Preview device not found at ${previewDevice.absolute.path}'); |
| } |
| final String newPath = artifacts.getArtifactPath(Artifact.flutterPreviewDevice); |
| fs.file(newPath).parent.createSync(recursive: true); |
| previewDevice.copySync(newPath); |
| return FlutterCommandResult.success(); |
| } finally { |
| try { |
| targetDir.deleteSync(recursive: true); |
| } on FileSystemException catch (exception) { |
| logger.printError('Failed to delete ${targetDir.path}\n\n$exception'); |
| } |
| } |
| } |
| |
| Future<FlutterProject> _createProject(Directory targetDir) async { |
| final List<String> cmd = <String>[ |
| fs.path.join(flutterRoot, 'bin', 'flutter.bat'), |
| 'create', |
| '--empty', |
| '--project-name', |
| 'flutter_preview', |
| targetDir.path, |
| ]; |
| final RunResult result = await processUtils.run( |
| cmd, |
| allowReentrantFlutter: true, |
| ); |
| if (result.exitCode != 0) { |
| final StringBuffer buffer = StringBuffer('${cmd.join(' ')} exited with code ${result.exitCode}\n'); |
| buffer.writeln('stdout:\n${result.stdout}\n'); |
| buffer.writeln('stderr:\n${result.stderr}'); |
| throw ProcessException(cmd.first, cmd.sublist(1), buffer.toString(), result.exitCode); |
| } |
| return FlutterProject.fromDirectory(targetDir); |
| } |
| } |