Unverified Commit 9989c54c authored by stuartmorgan's avatar stuartmorgan Committed by GitHub

Add release and profile support for Windows (#57749)

Builds and bundles an 'app.so' containing AOT data, and downloads and packages the release/profile artifacts for those builds, rather than always using the debug artifacts.

Fixes https://github.com/flutter/flutter/issues/38477
Fixes https://github.com/flutter/flutter/issues/39664
parent ca0d6008
...@@ -44,12 +44,12 @@ or ...@@ -44,12 +44,12 @@ or
final String flutterExecutable = path.join( final String flutterExecutable = path.join(
flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter'); flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
final String target = targetPlatform == 'windows-x64' final String bundlePlatform = targetPlatform == 'windows-x64' ? 'windows' : 'linux';
? 'debug_bundle_windows_assets' // TODO(jonahwilliams): currently all Linux builds are debug builds. Remove the
: 'debug_bundle_linux_assets';
// TODO(jonahwilliams): currently all builds are debug builds. Remove the
// hardcoded mode when profile and release support is added. // hardcoded mode when profile and release support is added.
final String bundleMode = targetPlatform == 'windows-x64' ? buildMode : 'debug';
final String target = '${bundleMode}_bundle_${bundlePlatform}_assets';
final Process assembleProcess = await Process.start( final Process assembleProcess = await Process.start(
flutterExecutable, flutterExecutable,
<String>[ <String>[
...@@ -61,7 +61,7 @@ or ...@@ -61,7 +61,7 @@ or
'--output=build', '--output=build',
'-dTargetPlatform=$targetPlatform', '-dTargetPlatform=$targetPlatform',
'-dTrackWidgetCreation=$trackWidgetCreation', '-dTrackWidgetCreation=$trackWidgetCreation',
'-dBuildMode=debug', '-dBuildMode=$bundleMode',
'-dTargetFile=$flutterTarget', '-dTargetFile=$flutterTarget',
'-dTreeShakeIcons="$treeShakeIcons"', '-dTreeShakeIcons="$treeShakeIcons"',
'-dDartObfuscation=$dartObfuscation', '-dDartObfuscation=$dartObfuscation',
......
...@@ -62,8 +62,8 @@ class AotBuilder { ...@@ -62,8 +62,8 @@ class AotBuilder {
case TargetPlatform.android_x64: case TargetPlatform.android_x64:
expectSo = true; expectSo = true;
target = buildInfo.isRelease target = buildInfo.isRelease
? const AotElfRelease() ? const AotElfRelease(TargetPlatform.android_arm)
: const AotElfProfile(); : const AotElfProfile(TargetPlatform.android_arm);
} }
Status status; Status status;
......
...@@ -23,6 +23,7 @@ enum Artifact { ...@@ -23,6 +23,7 @@ enum Artifact {
flutterMacOSFramework, flutterMacOSFramework,
vmSnapshotData, vmSnapshotData,
isolateSnapshotData, isolateSnapshotData,
icuData,
platformKernelDill, platformKernelDill,
platformLibrariesJson, platformLibrariesJson,
flutterPatchedSdkPath, flutterPatchedSdkPath,
...@@ -86,6 +87,8 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo ...@@ -86,6 +87,8 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo
return 'vm_isolate_snapshot.bin'; return 'vm_isolate_snapshot.bin';
case Artifact.isolateSnapshotData: case Artifact.isolateSnapshotData:
return 'isolate_snapshot.bin'; return 'isolate_snapshot.bin';
case Artifact.icuData:
return 'icudtl.dat';
case Artifact.platformKernelDill: case Artifact.platformKernelDill:
return 'platform_strong.dill'; return 'platform_strong.dill';
case Artifact.platformLibrariesJson: case Artifact.platformLibrariesJson:
...@@ -212,12 +215,12 @@ class CachedArtifacts extends Artifacts { ...@@ -212,12 +215,12 @@ class CachedArtifacts extends Artifacts {
case TargetPlatform.ios: case TargetPlatform.ios:
return _getIosArtifactPath(artifact, platform, mode); return _getIosArtifactPath(artifact, platform, mode);
case TargetPlatform.darwin_x64: case TargetPlatform.darwin_x64:
return _getDarwinArtifactPath(artifact, platform, mode); case TargetPlatform.linux_x64:
case TargetPlatform.windows_x64:
return _getDesktopArtifactPath(artifact, platform, mode);
case TargetPlatform.fuchsia_arm64: case TargetPlatform.fuchsia_arm64:
case TargetPlatform.fuchsia_x64: case TargetPlatform.fuchsia_x64:
return _getFuchsiaArtifactPath(artifact, platform, mode); return _getFuchsiaArtifactPath(artifact, platform, mode);
case TargetPlatform.linux_x64:
case TargetPlatform.windows_x64:
case TargetPlatform.tester: case TargetPlatform.tester:
case TargetPlatform.web_javascript: case TargetPlatform.web_javascript:
default: // could be null, but that can't be specified as a case. default: // could be null, but that can't be specified as a case.
...@@ -230,7 +233,7 @@ class CachedArtifacts extends Artifacts { ...@@ -230,7 +233,7 @@ class CachedArtifacts extends Artifacts {
return _fileSystem.path.basename(_getEngineArtifactsPath(platform, mode)); return _fileSystem.path.basename(_getEngineArtifactsPath(platform, mode));
} }
String _getDarwinArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) { String _getDesktopArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
// When platform is null, a generic host platform artifact is being requested // When platform is null, a generic host platform artifact is being requested
// and not the gen_snapshot for darwin as a target platform. // and not the gen_snapshot for darwin as a target platform.
if (platform != null && artifact == Artifact.genSnapshot) { if (platform != null && artifact == Artifact.genSnapshot) {
...@@ -331,6 +334,7 @@ class CachedArtifacts extends Artifacts { ...@@ -331,6 +334,7 @@ class CachedArtifacts extends Artifacts {
case Artifact.vmSnapshotData: case Artifact.vmSnapshotData:
case Artifact.isolateSnapshotData: case Artifact.isolateSnapshotData:
case Artifact.frontendServerSnapshotForEngineDartSdk: case Artifact.frontendServerSnapshotForEngineDartSdk:
case Artifact.icuData:
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path; final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
final String platformDirName = getNameForTargetPlatform(platform); final String platformDirName = getNameForTargetPlatform(platform);
return _fileSystem.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact, platform, mode)); return _fileSystem.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact, platform, mode));
...@@ -491,6 +495,8 @@ class LocalEngineArtifacts extends Artifacts { ...@@ -491,6 +495,8 @@ class LocalEngineArtifacts extends Artifacts {
case Artifact.isolateSnapshotData: case Artifact.isolateSnapshotData:
case Artifact.vmSnapshotData: case Artifact.vmSnapshotData:
return _fileSystem.path.join(engineOutPath, 'gen', 'flutter', 'lib', 'snapshot', artifactFileName); return _fileSystem.path.join(engineOutPath, 'gen', 'flutter', 'lib', 'snapshot', artifactFileName);
case Artifact.icuData:
return _fileSystem.path.join(engineOutPath, artifactFileName);
case Artifact.platformKernelDill: case Artifact.platformKernelDill:
if (platform == TargetPlatform.fuchsia_x64 || platform == TargetPlatform.fuchsia_arm64) { if (platform == TargetPlatform.fuchsia_x64 || platform == TargetPlatform.fuchsia_arm64) {
return _fileSystem.path.join(engineOutPath, 'flutter_runner_patched_sdk', artifactFileName); return _fileSystem.path.join(engineOutPath, 'flutter_runner_patched_sdk', artifactFileName);
......
...@@ -298,6 +298,7 @@ class AOTSnapshotter { ...@@ -298,6 +298,7 @@ class AOTSnapshotter {
TargetPlatform.android_x64, TargetPlatform.android_x64,
TargetPlatform.ios, TargetPlatform.ios,
TargetPlatform.darwin_x64, TargetPlatform.darwin_x64,
TargetPlatform.windows_x64,
].contains(platform); ].contains(platform);
} }
} }
...@@ -153,7 +153,7 @@ class ProfileAndroidApplication extends CopyFlutterAotBundle { ...@@ -153,7 +153,7 @@ class ProfileAndroidApplication extends CopyFlutterAotBundle {
@override @override
List<Target> get dependencies => const <Target>[ List<Target> get dependencies => const <Target>[
AotElfProfile(), AotElfProfile(TargetPlatform.android_arm),
AotAndroidAssetBundle(), AotAndroidAssetBundle(),
]; ];
} }
...@@ -167,7 +167,7 @@ class ReleaseAndroidApplication extends CopyFlutterAotBundle { ...@@ -167,7 +167,7 @@ class ReleaseAndroidApplication extends CopyFlutterAotBundle {
@override @override
List<Target> get dependencies => const <Target>[ List<Target> get dependencies => const <Target>[
AotElfRelease(), AotElfRelease(TargetPlatform.android_arm),
AotAndroidAssetBundle(), AotAndroidAssetBundle(),
]; ];
} }
......
...@@ -312,20 +312,20 @@ abstract class AotElfBase extends Target { ...@@ -312,20 +312,20 @@ abstract class AotElfBase extends Target {
/// Generate an ELF binary from a dart kernel file in profile mode. /// Generate an ELF binary from a dart kernel file in profile mode.
class AotElfProfile extends AotElfBase { class AotElfProfile extends AotElfBase {
const AotElfProfile(); const AotElfProfile(this.targetPlatform);
@override @override
String get name => 'aot_elf_profile'; String get name => 'aot_elf_profile';
@override @override
List<Source> get inputs => const <Source>[ List<Source> get inputs => <Source>[
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'), const Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
Source.pattern('{BUILD_DIR}/app.dill'), const Source.pattern('{BUILD_DIR}/app.dill'),
Source.pattern('{PROJECT_DIR}/.packages'), const Source.pattern('{PROJECT_DIR}/.packages'),
Source.artifact(Artifact.engineDartBinary), const Source.artifact(Artifact.engineDartBinary),
Source.artifact(Artifact.skyEnginePath), const Source.artifact(Artifact.skyEnginePath),
Source.artifact(Artifact.genSnapshot, Source.artifact(Artifact.genSnapshot,
platform: TargetPlatform.android_arm, platform: targetPlatform,
mode: BuildMode.profile, mode: BuildMode.profile,
), ),
]; ];
...@@ -339,24 +339,26 @@ class AotElfProfile extends AotElfBase { ...@@ -339,24 +339,26 @@ class AotElfProfile extends AotElfBase {
List<Target> get dependencies => const <Target>[ List<Target> get dependencies => const <Target>[
KernelSnapshot(), KernelSnapshot(),
]; ];
final TargetPlatform targetPlatform;
} }
/// Generate an ELF binary from a dart kernel file in release mode. /// Generate an ELF binary from a dart kernel file in release mode.
class AotElfRelease extends AotElfBase { class AotElfRelease extends AotElfBase {
const AotElfRelease(); const AotElfRelease(this.targetPlatform);
@override @override
String get name => 'aot_elf_release'; String get name => 'aot_elf_release';
@override @override
List<Source> get inputs => const <Source>[ List<Source> get inputs => <Source>[
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'), const Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
Source.pattern('{BUILD_DIR}/app.dill'), const Source.pattern('{BUILD_DIR}/app.dill'),
Source.pattern('{PROJECT_DIR}/.packages'), const Source.pattern('{PROJECT_DIR}/.packages'),
Source.artifact(Artifact.engineDartBinary), const Source.artifact(Artifact.engineDartBinary),
Source.artifact(Artifact.skyEnginePath), const Source.artifact(Artifact.skyEnginePath),
Source.artifact(Artifact.genSnapshot, Source.artifact(Artifact.genSnapshot,
platform: TargetPlatform.android_arm, platform: targetPlatform,
mode: BuildMode.release, mode: BuildMode.release,
), ),
]; ];
...@@ -370,6 +372,8 @@ class AotElfRelease extends AotElfBase { ...@@ -370,6 +372,8 @@ class AotElfRelease extends AotElfBase {
List<Target> get dependencies => const <Target>[ List<Target> get dependencies => const <Target>[
KernelSnapshot(), KernelSnapshot(),
]; ];
final TargetPlatform targetPlatform;
} }
/// Copies the pre-built flutter aot bundle. /// Copies the pre-built flutter aot bundle.
......
...@@ -7,8 +7,9 @@ import 'package:meta/meta.dart'; ...@@ -7,8 +7,9 @@ import 'package:meta/meta.dart';
import '../../base/file_system.dart'; import '../../base/file_system.dart';
import '../depfile.dart'; import '../depfile.dart';
/// Unpack the engine artifact list [artifacts] from [engineSourcePath] and /// Unpack the engine artifact list [artifacts] from [engineSourcePath], ICU
/// [clientSourcePaths] (if provided) into a directory [outputDirectory]. /// data (if provided), and [clientSourcePaths] (if provided) into a directory
/// [outputDirectory].
/// ///
/// Returns a [Depfile] including all copied files. /// Returns a [Depfile] including all copied files.
/// ///
...@@ -20,6 +21,7 @@ Depfile unpackDesktopArtifacts({ ...@@ -20,6 +21,7 @@ Depfile unpackDesktopArtifacts({
@required Directory outputDirectory, @required Directory outputDirectory,
@required String engineSourcePath, @required String engineSourcePath,
List<String> clientSourcePaths, List<String> clientSourcePaths,
String icuDataPath,
}) { }) {
final List<File> inputs = <File>[]; final List<File> inputs = <File>[];
final List<File> outputs = <File>[]; final List<File> outputs = <File>[];
...@@ -30,7 +32,7 @@ Depfile unpackDesktopArtifacts({ ...@@ -30,7 +32,7 @@ Depfile unpackDesktopArtifacts({
if (entityType == FileSystemEntityType.notFound if (entityType == FileSystemEntityType.notFound
|| entityType == FileSystemEntityType.directory || entityType == FileSystemEntityType.directory
|| entityType == FileSystemEntityType.link) { || entityType == FileSystemEntityType.link) {
throw Exception('Unsupported file type: $entityType'); throw Exception('Unsupported file type "$entityType" for $entityPath');
} }
assert(entityType == FileSystemEntityType.file); assert(entityType == FileSystemEntityType.file);
final String outputPath = fileSystem.path.join( final String outputPath = fileSystem.path.join(
...@@ -46,6 +48,13 @@ Depfile unpackDesktopArtifacts({ ...@@ -46,6 +48,13 @@ Depfile unpackDesktopArtifacts({
inputs.add(inputFile); inputs.add(inputFile);
outputs.add(destinationFile); outputs.add(destinationFile);
} }
if (icuDataPath != null) {
final File inputFile = fileSystem.file(icuDataPath);
final File outputFile = fileSystem.file(fileSystem.path.join(outputDirectory.path, inputFile.basename));
inputFile.copySync(outputFile.path);
inputs.add(inputFile);
outputs.add(outputFile);
}
if (clientSourcePaths == null) { if (clientSourcePaths == null) {
return Depfile(inputs, outputs); return Depfile(inputs, outputs);
} }
......
...@@ -23,7 +23,6 @@ const List<String> _kWindowsArtifacts = <String>[ ...@@ -23,7 +23,6 @@ const List<String> _kWindowsArtifacts = <String>[
'flutter_messenger.h', 'flutter_messenger.h',
'flutter_plugin_registrar.h', 'flutter_plugin_registrar.h',
'flutter_windows.h', 'flutter_windows.h',
'icudtl.dat',
]; ];
const String _kWindowsDepfile = 'windows_engine_sources.d'; const String _kWindowsDepfile = 'windows_engine_sources.d';
...@@ -78,6 +77,10 @@ class UnpackWindows extends Target { ...@@ -78,6 +77,10 @@ class UnpackWindows extends Target {
engineSourcePath: engineSourcePath, engineSourcePath: engineSourcePath,
outputDirectory: outputDirectory, outputDirectory: outputDirectory,
clientSourcePaths: <String>[clientSourcePath], clientSourcePaths: <String>[clientSourcePath],
icuDataPath: environment.artifacts.getArtifactPath(
Artifact.icuData,
platform: TargetPlatform.windows_x64
)
); );
final DepfileService depfileService = DepfileService( final DepfileService depfileService = DepfileService(
fileSystem: environment.fileSystem, fileSystem: environment.fileSystem,
...@@ -90,12 +93,9 @@ class UnpackWindows extends Target { ...@@ -90,12 +93,9 @@ class UnpackWindows extends Target {
} }
} }
/// Creates a debug bundle for the Windows desktop target. /// Creates a bundle for the Windows desktop target.
class DebugBundleWindowsAssets extends Target { abstract class BundleWindowsAssets extends Target {
const DebugBundleWindowsAssets(); const BundleWindowsAssets();
@override
String get name => 'debug_bundle_windows_assets';
@override @override
List<Target> get dependencies => const <Target>[ List<Target> get dependencies => const <Target>[
...@@ -105,17 +105,11 @@ class DebugBundleWindowsAssets extends Target { ...@@ -105,17 +105,11 @@ class DebugBundleWindowsAssets extends Target {
@override @override
List<Source> get inputs => const <Source>[ List<Source> get inputs => const <Source>[
Source.pattern('{BUILD_DIR}/app.dill'),
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/windows.dart'), Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/windows.dart'),
Source.pattern('{PROJECT_DIR}/pubspec.yaml'), Source.pattern('{PROJECT_DIR}/pubspec.yaml'),
...IconTreeShaker.inputs, ...IconTreeShaker.inputs,
]; ];
@override
List<Source> get outputs => const <Source>[
Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'),
];
@override @override
List<String> get depfiles => const <String>[ List<String> get depfiles => const <String>[
'flutter_assets.d', 'flutter_assets.d',
...@@ -124,7 +118,7 @@ class DebugBundleWindowsAssets extends Target { ...@@ -124,7 +118,7 @@ class DebugBundleWindowsAssets extends Target {
@override @override
Future<void> build(Environment environment) async { Future<void> build(Environment environment) async {
if (environment.defines[kBuildMode] == null) { if (environment.defines[kBuildMode] == null) {
throw MissingDefineException(kBuildMode, 'debug_bundle_windows_assets'); throw MissingDefineException(kBuildMode, 'bundle_windows_assets');
} }
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]); final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
final Directory outputDirectory = environment.outputDir final Directory outputDirectory = environment.outputDir
...@@ -149,3 +143,89 @@ class DebugBundleWindowsAssets extends Target { ...@@ -149,3 +143,89 @@ class DebugBundleWindowsAssets extends Target {
); );
} }
} }
/// A wrapper for AOT compilation that copies app.so into the output directory.
class WindowsAotBundle extends Target {
/// Create a [WindowsAotBundle] wrapper for [aotTarget].
const WindowsAotBundle(this.aotTarget);
/// The [AotElfBase] subclass that produces the app.so.
final AotElfBase aotTarget;
@override
String get name => 'windows_aot_bundle';
@override
List<Source> get inputs => const <Source>[
Source.pattern('{BUILD_DIR}/app.so'),
];
@override
List<Source> get outputs => const <Source>[
Source.pattern('{OUTPUT_DIR}/windows/app.so'),
];
@override
List<Target> get dependencies => <Target>[
aotTarget,
];
@override
Future<void> build(Environment environment) async {
final File outputFile = environment.buildDir.childFile('app.so');
final Directory outputDirectory = environment.outputDir.childDirectory('windows');
if (!outputDirectory.existsSync()) {
outputDirectory.createSync(recursive: true);
}
outputFile.copySync(outputDirectory.childFile('app.so').path);
}
}
class ReleaseBundleWindowsAssets extends BundleWindowsAssets {
const ReleaseBundleWindowsAssets();
@override
String get name => 'release_bundle_windows_assets';
@override
List<Source> get outputs => const <Source>[];
@override
List<Target> get dependencies => <Target>[
...super.dependencies,
const WindowsAotBundle(AotElfRelease(TargetPlatform.windows_x64)),
];
}
class ProfileBundleWindowsAssets extends BundleWindowsAssets {
const ProfileBundleWindowsAssets();
@override
String get name => 'profile_bundle_windows_assets';
@override
List<Source> get outputs => const <Source>[];
@override
List<Target> get dependencies => <Target>[
...super.dependencies,
const WindowsAotBundle(AotElfProfile(TargetPlatform.windows_x64)),
];
}
class DebugBundleWindowsAssets extends BundleWindowsAssets {
const DebugBundleWindowsAssets();
@override
String get name => 'debug_bundle_windows_assets';
@override
List<Source> get inputs => <Source>[
const Source.pattern('{BUILD_DIR}/app.dill'),
];
@override
List<Source> get outputs => <Source>[
const Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'),
];
}
...@@ -29,8 +29,8 @@ const List<Target> _kDefaultTargets = <Target>[ ...@@ -29,8 +29,8 @@ const List<Target> _kDefaultTargets = <Target>[
// Shared targets // Shared targets
CopyAssets(), CopyAssets(),
KernelSnapshot(), KernelSnapshot(),
AotElfProfile(), AotElfProfile(TargetPlatform.android_arm),
AotElfRelease(), AotElfRelease(TargetPlatform.android_arm),
AotAssemblyProfile(), AotAssemblyProfile(),
AotAssemblyRelease(), AotAssemblyRelease(),
// macOS targets // macOS targets
...@@ -63,6 +63,8 @@ const List<Target> _kDefaultTargets = <Target>[ ...@@ -63,6 +63,8 @@ const List<Target> _kDefaultTargets = <Target>[
// Windows targets // Windows targets
UnpackWindows(), UnpackWindows(),
DebugBundleWindowsAssets(), DebugBundleWindowsAssets(),
ProfileBundleWindowsAssets(),
ReleaseBundleWindowsAssets(),
]; ];
/// Assemble provides a low level API to interact with the flutter tool build /// Assemble provides a low level API to interact with the flutter tool build
......
...@@ -7,6 +7,7 @@ import '../base/common.dart'; ...@@ -7,6 +7,7 @@ import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../cache.dart'; import '../cache.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
...@@ -57,15 +58,6 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, { ...@@ -57,15 +58,6 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {
'Please run `flutter doctor` for more details.'); 'Please run `flutter doctor` for more details.');
} }
if (!buildInfo.isDebug) {
const String warning = '🚧 ';
globals.printStatus(warning * 20);
globals.printStatus('Warning: Only debug is currently implemented for Windows. This is effectively a debug build.');
globals.printStatus('See https://github.com/flutter/flutter/issues/38477 for details and updates.');
globals.printStatus(warning * 20);
globals.printStatus('');
}
final String buildScript = globals.fs.path.join( final String buildScript = globals.fs.path.join(
Cache.flutterRoot, Cache.flutterRoot,
'packages', 'packages',
...@@ -74,7 +66,7 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, { ...@@ -74,7 +66,7 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {
'vs_build.bat', 'vs_build.bat',
); );
final String configuration = buildInfo.isDebug ? 'Debug' : 'Release'; final String configuration = toTitleCase(getNameForBuildMode(buildInfo.mode ?? BuildMode.release));
final String solutionPath = windowsProject.solutionFile.path; final String solutionPath = windowsProject.solutionFile.path;
final Stopwatch sw = Stopwatch()..start(); final Stopwatch sw = Stopwatch()..start();
final Status status = globals.logger.startProgress( final Status status = globals.logger.startProgress(
......
...@@ -116,7 +116,7 @@ ...@@ -116,7 +116,7 @@
</Message> </Message>
</PostBuildEvent> </PostBuildEvent>
<CustomBuildStep> <CustomBuildStep>
<Command>"$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)"</Command> <Command>"$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)"</Command>
</CustomBuildStep> </CustomBuildStep>
<CustomBuildStep> <CustomBuildStep>
<Message>Bundling dependencies</Message> <Message>Bundling dependencies</Message>
...@@ -165,7 +165,7 @@ ...@@ -165,7 +165,7 @@
</Message> </Message>
</PostBuildEvent> </PostBuildEvent>
<CustomBuildStep> <CustomBuildStep>
<Command>"$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)"</Command> <Command>"$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)"</Command>
</CustomBuildStep> </CustomBuildStep>
<CustomBuildStep> <CustomBuildStep>
<Message>Bundling dependencies</Message> <Message>Bundling dependencies</Message>
...@@ -214,7 +214,7 @@ ...@@ -214,7 +214,7 @@
</Message> </Message>
</PostBuildEvent> </PostBuildEvent>
<CustomBuildStep> <CustomBuildStep>
<Command>"$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)"</Command> <Command>"$(ProjectDir)scripts\bundle_assets_and_deps" "$(FLUTTER_EPHEMERAL_DIR)\" "$(OutputPath)" "$(OutputPath)..\Plugins\" "$(TargetFileName)" "$(Configuration)"</Command>
</CustomBuildStep> </CustomBuildStep>
<CustomBuildStep> <CustomBuildStep>
<Message>Bundling dependencies</Message> <Message>Bundling dependencies</Message>
......
...@@ -4,6 +4,7 @@ set FLUTTER_CACHE_DIR=%~1 ...@@ -4,6 +4,7 @@ set FLUTTER_CACHE_DIR=%~1
set BUNDLE_DIR=%~2 set BUNDLE_DIR=%~2
set PLUGIN_DIR=%~3 set PLUGIN_DIR=%~3
set EXE_NAME=%~4 set EXE_NAME=%~4
set BUILD_MODE=%~5
set DATA_DIR=%BUNDLE_DIR%data set DATA_DIR=%BUNDLE_DIR%data
...@@ -14,18 +15,24 @@ if %errorlevel% neq 0 exit /b %errorlevel% ...@@ -14,18 +15,24 @@ if %errorlevel% neq 0 exit /b %errorlevel%
echo %EXE_NAME%>"%FLUTTER_CACHE_DIR%exe_filename" echo %EXE_NAME%>"%FLUTTER_CACHE_DIR%exe_filename"
:: Copy the Flutter assets to the data directory. :: Copy the Flutter assets to the data directory.
set FLUTTER_APP_DIR=%~dp0..\.. set FLUTTER_BUILD_DIR=%~dp0..\..\build\
set ASSET_DIR_NAME=flutter_assets set ASSET_DIR_NAME=flutter_assets
set TARGET_ASSET_DIR=%DATA_DIR%\%ASSET_DIR_NAME% set TARGET_ASSET_DIR=%DATA_DIR%\%ASSET_DIR_NAME%
if exist "%TARGET_ASSET_DIR%" call rmdir /s /q "%TARGET_ASSET_DIR%" if exist "%TARGET_ASSET_DIR%" call rmdir /s /q "%TARGET_ASSET_DIR%"
if %errorlevel% neq 0 exit /b %errorlevel% if %errorlevel% neq 0 exit /b %errorlevel%
call xcopy /s /e /i /q "%FLUTTER_APP_DIR%\build\%ASSET_DIR_NAME%" "%TARGET_ASSET_DIR%" call xcopy /s /e /i /q "%FLUTTER_BUILD_DIR%%ASSET_DIR_NAME%" "%TARGET_ASSET_DIR%"
if %errorlevel% neq 0 exit /b %errorlevel% if %errorlevel% neq 0 exit /b %errorlevel%
:: Copy the icudtl.dat file from the Flutter tree to the data directory. :: Copy the icudtl.dat file from the Flutter tree to the data directory.
call xcopy /y /d /q "%FLUTTER_CACHE_DIR%icudtl.dat" "%DATA_DIR%" call xcopy /y /d /q "%FLUTTER_CACHE_DIR%icudtl.dat" "%DATA_DIR%"
if %errorlevel% neq 0 exit /b %errorlevel% if %errorlevel% neq 0 exit /b %errorlevel%
:: For non-debug modes, copy app.so into the data directory.
if not %BUILD_MODE% == "Debug" (
call xcopy /y /d /q "%FLUTTER_BUILD_DIR%windows\app.so" "%DATA_DIR%"
if %errorlevel% neq 0 exit /b %errorlevel%
)
:: Copy the Flutter DLL to the target location. :: Copy the Flutter DLL to the target location.
call xcopy /y /d /q "%FLUTTER_CACHE_DIR%flutter_windows.dll" "%BUNDLE_DIR%" call xcopy /y /d /q "%FLUTTER_CACHE_DIR%flutter_windows.dll" "%BUNDLE_DIR%"
if %errorlevel% neq 0 exit /b %errorlevel% if %errorlevel% neq 0 exit /b %errorlevel%
......
...@@ -304,31 +304,28 @@ void main() { ...@@ -304,31 +304,28 @@ void main() {
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true), FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
}); });
testUsingContext('Release build prints an under-construction warning', () async { testUsingContext('Windows profile build passes Profile configuration', () async {
final BuildWindowsCommand command = BuildWindowsCommand() final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio; ..visualStudioOverride = mockVisualStudio;
applyMocksToCommand(command); applyMocksToCommand(command);
setUpMockProjectFilesForBuild(); setUpMockProjectFilesForBuild();
when(mockVisualStudio.vcvarsPath).thenReturn(vcvarsPath); when(mockVisualStudio.vcvarsPath).thenReturn(vcvarsPath);
when(mockProcessManager.start( when(mockProcessManager.start(<String>[
<String>[
fileSystem.path.join(flutterRoot, 'packages', 'flutter_tools', 'bin', 'vs_build.bat'), fileSystem.path.join(flutterRoot, 'packages', 'flutter_tools', 'bin', 'vs_build.bat'),
vcvarsPath, vcvarsPath,
fileSystem.path.basename(solutionPath), fileSystem.path.basename(solutionPath),
'Release', 'Profile',
], ],
environment: <String, String>{}, environment: <String, String>{},
workingDirectory: fileSystem.path.dirname(solutionPath))).thenAnswer((Invocation invocation) async { workingDirectory: fileSystem.path.dirname(solutionPath))
return mockProcess; ).thenAnswer((Invocation invocation) async {
}, return mockProcess;
); });
await createTestCommandRunner(command).run( await createTestCommandRunner(command).run(
const <String>['windows', '--no-pub'] const <String>['windows', '--profile', '--no-pub']
); );
expect(testLogger.statusText, contains('🚧'));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => mockProcessManager, ProcessManager: () => mockProcessManager,
......
...@@ -333,7 +333,7 @@ void main() { ...@@ -333,7 +333,7 @@ void main() {
]); ]);
androidEnvironment.buildDir.childFile('app.dill').createSync(recursive: true); androidEnvironment.buildDir.childFile('app.dill').createSync(recursive: true);
await const AotElfProfile().build(androidEnvironment); await const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment);
expect(processManager.hasRemainingExpectations, false); expect(processManager.hasRemainingExpectations, false);
})); }));
...@@ -341,14 +341,14 @@ void main() { ...@@ -341,14 +341,14 @@ void main() {
test('AotElfProfile throws error if missing build mode', () => testbed.run(() async { test('AotElfProfile throws error if missing build mode', () => testbed.run(() async {
androidEnvironment.defines.remove(kBuildMode); androidEnvironment.defines.remove(kBuildMode);
expect(const AotElfProfile().build(androidEnvironment), expect(const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment),
throwsA(isA<MissingDefineException>())); throwsA(isA<MissingDefineException>()));
})); }));
test('AotElfProfile throws error if missing target platform', () => testbed.run(() async { test('AotElfProfile throws error if missing target platform', () => testbed.run(() async {
androidEnvironment.defines.remove(kTargetPlatform); androidEnvironment.defines.remove(kTargetPlatform);
expect(const AotElfProfile().build(androidEnvironment), expect(const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment),
throwsA(isA<MissingDefineException>())); throwsA(isA<MissingDefineException>()));
})); }));
...@@ -594,7 +594,7 @@ void main() { ...@@ -594,7 +594,7 @@ void main() {
]), ]),
]); ]);
await const AotElfRelease().build(androidEnvironment); await const AotElfRelease(TargetPlatform.android_arm).build(androidEnvironment);
expect(processManager.hasRemainingExpectations, false); expect(processManager.hasRemainingExpectations, false);
})); }));
......
...@@ -8,6 +8,7 @@ import 'package:flutter_tools/src/artifacts.dart'; ...@@ -8,6 +8,7 @@ import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/depfile.dart'; import 'package:flutter_tools/src/build_system/depfile.dart';
import 'package:flutter_tools/src/build_system/targets/dart.dart'; import 'package:flutter_tools/src/build_system/targets/dart.dart';
...@@ -67,6 +68,11 @@ void main() { ...@@ -67,6 +68,11 @@ void main() {
mode: anyNamed('mode'), mode: anyNamed('mode'),
platform: anyNamed('platform') platform: anyNamed('platform')
)).thenReturn(r'C:\bin\cache\artifacts\engine\windows-x64\cpp_client_wrapper\'); )).thenReturn(r'C:\bin\cache\artifacts\engine\windows-x64\cpp_client_wrapper\');
when(artifacts.getArtifactPath(
Artifact.icuData,
mode: anyNamed('mode'),
platform: anyNamed('platform')
)).thenReturn(r'C:\bin\cache\artifacts\engine\windows-x64\icudtl.dat');
for (final String path in kRequiredFiles) { for (final String path in kRequiredFiles) {
fileSystem.file(path).createSync(recursive: true); fileSystem.file(path).createSync(recursive: true);
} }
...@@ -158,6 +164,60 @@ void main() { ...@@ -158,6 +164,60 @@ void main() {
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('ProfileBundleWindowsAssets creates correct bundle structure', () async {
final Environment environment = Environment.test(
fileSystem.currentDirectory,
artifacts: MockArtifacts(),
processManager: FakeProcessManager.any(),
fileSystem: fileSystem,
logger: BufferLogger.test(),
defines: <String, String>{
kBuildMode: 'profile',
}
);
environment.buildDir.childFile('app.so').createSync(recursive: true);
await const WindowsAotBundle(AotElfProfile(TargetPlatform.windows_x64)).build(environment);
await const ProfileBundleWindowsAssets().build(environment);
// Depfile is created and so is copied.
expect(environment.buildDir.childFile('flutter_assets.d'), exists);
expect(fileSystem.file(r'C:\windows\app.so'), exists);
expect(fileSystem.file(r'C:\flutter_assets\kernel_blob.bin').existsSync(), false);
expect(fileSystem.file(r'C:\flutter_assets\AssetManifest.json'), exists);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('ReleaseBundleWindowsAssets creates correct bundle structure', () async {
final Environment environment = Environment.test(
fileSystem.currentDirectory,
artifacts: MockArtifacts(),
processManager: FakeProcessManager.any(),
fileSystem: fileSystem,
logger: BufferLogger.test(),
defines: <String, String>{
kBuildMode: 'release',
}
);
environment.buildDir.childFile('app.so').createSync(recursive: true);
await const WindowsAotBundle(AotElfRelease(TargetPlatform.windows_x64)).build(environment);
await const ReleaseBundleWindowsAssets().build(environment);
// Depfile is created and so is copied.
expect(environment.buildDir.childFile('flutter_assets.d'), exists);
expect(fileSystem.file(r'C:\windows\app.so'), exists);
expect(fileSystem.file(r'C:\flutter_assets\kernel_blob.bin').existsSync(), false);
expect(fileSystem.file(r'C:\flutter_assets\AssetManifest.json'), exists);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
});
} }
class MockArtifacts extends Mock implements Artifacts {} class MockArtifacts extends Mock implements Artifacts {}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment