Skip to content

Commit 9989c54

Browse files
Add release and profile support for Windows (flutter#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 flutter#38477 Fixes flutter#39664
1 parent ca0d600 commit 9989c54

File tree

15 files changed

+237
-79
lines changed

15 files changed

+237
-79
lines changed

packages/flutter_tools/bin/tool_backend.dart

+6-6
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ or
4444

4545
final String flutterExecutable = path.join(
4646
flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
47-
final String target = targetPlatform == 'windows-x64'
48-
? 'debug_bundle_windows_assets'
49-
: 'debug_bundle_linux_assets';
50-
51-
// TODO(jonahwilliams): currently all builds are debug builds. Remove the
47+
final String bundlePlatform = targetPlatform == 'windows-x64' ? 'windows' : 'linux';
48+
// TODO(jonahwilliams): currently all Linux builds are debug builds. Remove the
5249
// hardcoded mode when profile and release support is added.
50+
final String bundleMode = targetPlatform == 'windows-x64' ? buildMode : 'debug';
51+
final String target = '${bundleMode}_bundle_${bundlePlatform}_assets';
52+
5353
final Process assembleProcess = await Process.start(
5454
flutterExecutable,
5555
<String>[
@@ -61,7 +61,7 @@ or
6161
'--output=build',
6262
'-dTargetPlatform=$targetPlatform',
6363
'-dTrackWidgetCreation=$trackWidgetCreation',
64-
'-dBuildMode=debug',
64+
'-dBuildMode=$bundleMode',
6565
'-dTargetFile=$flutterTarget',
6666
'-dTreeShakeIcons="$treeShakeIcons"',
6767
'-dDartObfuscation=$dartObfuscation',

packages/flutter_tools/lib/src/aot.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ class AotBuilder {
6262
case TargetPlatform.android_x64:
6363
expectSo = true;
6464
target = buildInfo.isRelease
65-
? const AotElfRelease()
66-
: const AotElfProfile();
65+
? const AotElfRelease(TargetPlatform.android_arm)
66+
: const AotElfProfile(TargetPlatform.android_arm);
6767
}
6868

6969
Status status;

packages/flutter_tools/lib/src/artifacts.dart

+10-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ enum Artifact {
2323
flutterMacOSFramework,
2424
vmSnapshotData,
2525
isolateSnapshotData,
26+
icuData,
2627
platformKernelDill,
2728
platformLibrariesJson,
2829
flutterPatchedSdkPath,
@@ -86,6 +87,8 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo
8687
return 'vm_isolate_snapshot.bin';
8788
case Artifact.isolateSnapshotData:
8889
return 'isolate_snapshot.bin';
90+
case Artifact.icuData:
91+
return 'icudtl.dat';
8992
case Artifact.platformKernelDill:
9093
return 'platform_strong.dill';
9194
case Artifact.platformLibrariesJson:
@@ -212,12 +215,12 @@ class CachedArtifacts extends Artifacts {
212215
case TargetPlatform.ios:
213216
return _getIosArtifactPath(artifact, platform, mode);
214217
case TargetPlatform.darwin_x64:
215-
return _getDarwinArtifactPath(artifact, platform, mode);
218+
case TargetPlatform.linux_x64:
219+
case TargetPlatform.windows_x64:
220+
return _getDesktopArtifactPath(artifact, platform, mode);
216221
case TargetPlatform.fuchsia_arm64:
217222
case TargetPlatform.fuchsia_x64:
218223
return _getFuchsiaArtifactPath(artifact, platform, mode);
219-
case TargetPlatform.linux_x64:
220-
case TargetPlatform.windows_x64:
221224
case TargetPlatform.tester:
222225
case TargetPlatform.web_javascript:
223226
default: // could be null, but that can't be specified as a case.
@@ -230,7 +233,7 @@ class CachedArtifacts extends Artifacts {
230233
return _fileSystem.path.basename(_getEngineArtifactsPath(platform, mode));
231234
}
232235

233-
String _getDarwinArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
236+
String _getDesktopArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
234237
// When platform is null, a generic host platform artifact is being requested
235238
// and not the gen_snapshot for darwin as a target platform.
236239
if (platform != null && artifact == Artifact.genSnapshot) {
@@ -331,6 +334,7 @@ class CachedArtifacts extends Artifacts {
331334
case Artifact.vmSnapshotData:
332335
case Artifact.isolateSnapshotData:
333336
case Artifact.frontendServerSnapshotForEngineDartSdk:
337+
case Artifact.icuData:
334338
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
335339
final String platformDirName = getNameForTargetPlatform(platform);
336340
return _fileSystem.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact, platform, mode));
@@ -491,6 +495,8 @@ class LocalEngineArtifacts extends Artifacts {
491495
case Artifact.isolateSnapshotData:
492496
case Artifact.vmSnapshotData:
493497
return _fileSystem.path.join(engineOutPath, 'gen', 'flutter', 'lib', 'snapshot', artifactFileName);
498+
case Artifact.icuData:
499+
return _fileSystem.path.join(engineOutPath, artifactFileName);
494500
case Artifact.platformKernelDill:
495501
if (platform == TargetPlatform.fuchsia_x64 || platform == TargetPlatform.fuchsia_arm64) {
496502
return _fileSystem.path.join(engineOutPath, 'flutter_runner_patched_sdk', artifactFileName);

packages/flutter_tools/lib/src/base/build.dart

+1
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ class AOTSnapshotter {
298298
TargetPlatform.android_x64,
299299
TargetPlatform.ios,
300300
TargetPlatform.darwin_x64,
301+
TargetPlatform.windows_x64,
301302
].contains(platform);
302303
}
303304
}

packages/flutter_tools/lib/src/build_system/targets/android.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class ProfileAndroidApplication extends CopyFlutterAotBundle {
153153

154154
@override
155155
List<Target> get dependencies => const <Target>[
156-
AotElfProfile(),
156+
AotElfProfile(TargetPlatform.android_arm),
157157
AotAndroidAssetBundle(),
158158
];
159159
}
@@ -167,7 +167,7 @@ class ReleaseAndroidApplication extends CopyFlutterAotBundle {
167167

168168
@override
169169
List<Target> get dependencies => const <Target>[
170-
AotElfRelease(),
170+
AotElfRelease(TargetPlatform.android_arm),
171171
AotAndroidAssetBundle(),
172172
];
173173
}

packages/flutter_tools/lib/src/build_system/targets/dart.dart

+20-16
Original file line numberDiff line numberDiff line change
@@ -312,20 +312,20 @@ abstract class AotElfBase extends Target {
312312

313313
/// Generate an ELF binary from a dart kernel file in profile mode.
314314
class AotElfProfile extends AotElfBase {
315-
const AotElfProfile();
315+
const AotElfProfile(this.targetPlatform);
316316

317317
@override
318318
String get name => 'aot_elf_profile';
319319

320320
@override
321-
List<Source> get inputs => const <Source>[
322-
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
323-
Source.pattern('{BUILD_DIR}/app.dill'),
324-
Source.pattern('{PROJECT_DIR}/.packages'),
325-
Source.artifact(Artifact.engineDartBinary),
326-
Source.artifact(Artifact.skyEnginePath),
321+
List<Source> get inputs => <Source>[
322+
const Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
323+
const Source.pattern('{BUILD_DIR}/app.dill'),
324+
const Source.pattern('{PROJECT_DIR}/.packages'),
325+
const Source.artifact(Artifact.engineDartBinary),
326+
const Source.artifact(Artifact.skyEnginePath),
327327
Source.artifact(Artifact.genSnapshot,
328-
platform: TargetPlatform.android_arm,
328+
platform: targetPlatform,
329329
mode: BuildMode.profile,
330330
),
331331
];
@@ -339,24 +339,26 @@ class AotElfProfile extends AotElfBase {
339339
List<Target> get dependencies => const <Target>[
340340
KernelSnapshot(),
341341
];
342+
343+
final TargetPlatform targetPlatform;
342344
}
343345

344346
/// Generate an ELF binary from a dart kernel file in release mode.
345347
class AotElfRelease extends AotElfBase {
346-
const AotElfRelease();
348+
const AotElfRelease(this.targetPlatform);
347349

348350
@override
349351
String get name => 'aot_elf_release';
350352

351353
@override
352-
List<Source> get inputs => const <Source>[
353-
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
354-
Source.pattern('{BUILD_DIR}/app.dill'),
355-
Source.pattern('{PROJECT_DIR}/.packages'),
356-
Source.artifact(Artifact.engineDartBinary),
357-
Source.artifact(Artifact.skyEnginePath),
354+
List<Source> get inputs => <Source>[
355+
const Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
356+
const Source.pattern('{BUILD_DIR}/app.dill'),
357+
const Source.pattern('{PROJECT_DIR}/.packages'),
358+
const Source.artifact(Artifact.engineDartBinary),
359+
const Source.artifact(Artifact.skyEnginePath),
358360
Source.artifact(Artifact.genSnapshot,
359-
platform: TargetPlatform.android_arm,
361+
platform: targetPlatform,
360362
mode: BuildMode.release,
361363
),
362364
];
@@ -370,6 +372,8 @@ class AotElfRelease extends AotElfBase {
370372
List<Target> get dependencies => const <Target>[
371373
KernelSnapshot(),
372374
];
375+
376+
final TargetPlatform targetPlatform;
373377
}
374378

375379
/// Copies the pre-built flutter aot bundle.

packages/flutter_tools/lib/src/build_system/targets/desktop.dart

+12-3
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import 'package:meta/meta.dart';
77
import '../../base/file_system.dart';
88
import '../depfile.dart';
99

10-
/// Unpack the engine artifact list [artifacts] from [engineSourcePath] and
11-
/// [clientSourcePaths] (if provided) into a directory [outputDirectory].
10+
/// Unpack the engine artifact list [artifacts] from [engineSourcePath], ICU
11+
/// data (if provided), and [clientSourcePaths] (if provided) into a directory
12+
/// [outputDirectory].
1213
///
1314
/// Returns a [Depfile] including all copied files.
1415
///
@@ -20,6 +21,7 @@ Depfile unpackDesktopArtifacts({
2021
@required Directory outputDirectory,
2122
@required String engineSourcePath,
2223
List<String> clientSourcePaths,
24+
String icuDataPath,
2325
}) {
2426
final List<File> inputs = <File>[];
2527
final List<File> outputs = <File>[];
@@ -30,7 +32,7 @@ Depfile unpackDesktopArtifacts({
3032
if (entityType == FileSystemEntityType.notFound
3133
|| entityType == FileSystemEntityType.directory
3234
|| entityType == FileSystemEntityType.link) {
33-
throw Exception('Unsupported file type: $entityType');
35+
throw Exception('Unsupported file type "$entityType" for $entityPath');
3436
}
3537
assert(entityType == FileSystemEntityType.file);
3638
final String outputPath = fileSystem.path.join(
@@ -46,6 +48,13 @@ Depfile unpackDesktopArtifacts({
4648
inputs.add(inputFile);
4749
outputs.add(destinationFile);
4850
}
51+
if (icuDataPath != null) {
52+
final File inputFile = fileSystem.file(icuDataPath);
53+
final File outputFile = fileSystem.file(fileSystem.path.join(outputDirectory.path, inputFile.basename));
54+
inputFile.copySync(outputFile.path);
55+
inputs.add(inputFile);
56+
outputs.add(outputFile);
57+
}
4958
if (clientSourcePaths == null) {
5059
return Depfile(inputs, outputs);
5160
}

packages/flutter_tools/lib/src/build_system/targets/windows.dart

+94-14
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ const List<String> _kWindowsArtifacts = <String>[
2323
'flutter_messenger.h',
2424
'flutter_plugin_registrar.h',
2525
'flutter_windows.h',
26-
'icudtl.dat',
2726
];
2827

2928
const String _kWindowsDepfile = 'windows_engine_sources.d';
@@ -78,6 +77,10 @@ class UnpackWindows extends Target {
7877
engineSourcePath: engineSourcePath,
7978
outputDirectory: outputDirectory,
8079
clientSourcePaths: <String>[clientSourcePath],
80+
icuDataPath: environment.artifacts.getArtifactPath(
81+
Artifact.icuData,
82+
platform: TargetPlatform.windows_x64
83+
)
8184
);
8285
final DepfileService depfileService = DepfileService(
8386
fileSystem: environment.fileSystem,
@@ -90,12 +93,9 @@ class UnpackWindows extends Target {
9093
}
9194
}
9295

93-
/// Creates a debug bundle for the Windows desktop target.
94-
class DebugBundleWindowsAssets extends Target {
95-
const DebugBundleWindowsAssets();
96-
97-
@override
98-
String get name => 'debug_bundle_windows_assets';
96+
/// Creates a bundle for the Windows desktop target.
97+
abstract class BundleWindowsAssets extends Target {
98+
const BundleWindowsAssets();
9999

100100
@override
101101
List<Target> get dependencies => const <Target>[
@@ -105,17 +105,11 @@ class DebugBundleWindowsAssets extends Target {
105105

106106
@override
107107
List<Source> get inputs => const <Source>[
108-
Source.pattern('{BUILD_DIR}/app.dill'),
109108
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/windows.dart'),
110109
Source.pattern('{PROJECT_DIR}/pubspec.yaml'),
111110
...IconTreeShaker.inputs,
112111
];
113112

114-
@override
115-
List<Source> get outputs => const <Source>[
116-
Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'),
117-
];
118-
119113
@override
120114
List<String> get depfiles => const <String>[
121115
'flutter_assets.d',
@@ -124,7 +118,7 @@ class DebugBundleWindowsAssets extends Target {
124118
@override
125119
Future<void> build(Environment environment) async {
126120
if (environment.defines[kBuildMode] == null) {
127-
throw MissingDefineException(kBuildMode, 'debug_bundle_windows_assets');
121+
throw MissingDefineException(kBuildMode, 'bundle_windows_assets');
128122
}
129123
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
130124
final Directory outputDirectory = environment.outputDir
@@ -149,3 +143,89 @@ class DebugBundleWindowsAssets extends Target {
149143
);
150144
}
151145
}
146+
147+
/// A wrapper for AOT compilation that copies app.so into the output directory.
148+
class WindowsAotBundle extends Target {
149+
/// Create a [WindowsAotBundle] wrapper for [aotTarget].
150+
const WindowsAotBundle(this.aotTarget);
151+
152+
/// The [AotElfBase] subclass that produces the app.so.
153+
final AotElfBase aotTarget;
154+
155+
@override
156+
String get name => 'windows_aot_bundle';
157+
158+
@override
159+
List<Source> get inputs => const <Source>[
160+
Source.pattern('{BUILD_DIR}/app.so'),
161+
];
162+
163+
@override
164+
List<Source> get outputs => const <Source>[
165+
Source.pattern('{OUTPUT_DIR}/windows/app.so'),
166+
];
167+
168+
@override
169+
List<Target> get dependencies => <Target>[
170+
aotTarget,
171+
];
172+
173+
@override
174+
Future<void> build(Environment environment) async {
175+
final File outputFile = environment.buildDir.childFile('app.so');
176+
final Directory outputDirectory = environment.outputDir.childDirectory('windows');
177+
if (!outputDirectory.existsSync()) {
178+
outputDirectory.createSync(recursive: true);
179+
}
180+
outputFile.copySync(outputDirectory.childFile('app.so').path);
181+
}
182+
}
183+
184+
class ReleaseBundleWindowsAssets extends BundleWindowsAssets {
185+
const ReleaseBundleWindowsAssets();
186+
187+
@override
188+
String get name => 'release_bundle_windows_assets';
189+
190+
@override
191+
List<Source> get outputs => const <Source>[];
192+
193+
@override
194+
List<Target> get dependencies => <Target>[
195+
...super.dependencies,
196+
const WindowsAotBundle(AotElfRelease(TargetPlatform.windows_x64)),
197+
];
198+
}
199+
200+
class ProfileBundleWindowsAssets extends BundleWindowsAssets {
201+
const ProfileBundleWindowsAssets();
202+
203+
@override
204+
String get name => 'profile_bundle_windows_assets';
205+
206+
@override
207+
List<Source> get outputs => const <Source>[];
208+
209+
@override
210+
List<Target> get dependencies => <Target>[
211+
...super.dependencies,
212+
const WindowsAotBundle(AotElfProfile(TargetPlatform.windows_x64)),
213+
];
214+
}
215+
216+
class DebugBundleWindowsAssets extends BundleWindowsAssets {
217+
const DebugBundleWindowsAssets();
218+
219+
@override
220+
String get name => 'debug_bundle_windows_assets';
221+
222+
@override
223+
List<Source> get inputs => <Source>[
224+
const Source.pattern('{BUILD_DIR}/app.dill'),
225+
];
226+
227+
@override
228+
List<Source> get outputs => <Source>[
229+
const Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'),
230+
];
231+
}

0 commit comments

Comments
 (0)