blob: ec20f0cc23f46381b11a6f47d425bae46fd6ac35 [file] [log] [blame]
// 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);
// TODO(loic-sharma): Support windows-arm64 preview device, https://github.com/flutter/flutter/issues/139949.
await buildWindows(
flutterProject.windows,
buildInfo,
TargetPlatform.windows_x64,
);
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);
}
}