mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
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
This commit is contained in:
parent
ca0d60087b
commit
9989c54cb1
|
@ -44,12 +44,12 @@ or
|
|||
|
||||
final String flutterExecutable = path.join(
|
||||
flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
|
||||
final String target = targetPlatform == 'windows-x64'
|
||||
? 'debug_bundle_windows_assets'
|
||||
: 'debug_bundle_linux_assets';
|
||||
|
||||
// TODO(jonahwilliams): currently all builds are debug builds. Remove the
|
||||
final String bundlePlatform = targetPlatform == 'windows-x64' ? 'windows' : 'linux';
|
||||
// TODO(jonahwilliams): currently all Linux builds are debug builds. Remove the
|
||||
// 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(
|
||||
flutterExecutable,
|
||||
<String>[
|
||||
|
@ -61,7 +61,7 @@ or
|
|||
'--output=build',
|
||||
'-dTargetPlatform=$targetPlatform',
|
||||
'-dTrackWidgetCreation=$trackWidgetCreation',
|
||||
'-dBuildMode=debug',
|
||||
'-dBuildMode=$bundleMode',
|
||||
'-dTargetFile=$flutterTarget',
|
||||
'-dTreeShakeIcons="$treeShakeIcons"',
|
||||
'-dDartObfuscation=$dartObfuscation',
|
||||
|
|
|
@ -62,8 +62,8 @@ class AotBuilder {
|
|||
case TargetPlatform.android_x64:
|
||||
expectSo = true;
|
||||
target = buildInfo.isRelease
|
||||
? const AotElfRelease()
|
||||
: const AotElfProfile();
|
||||
? const AotElfRelease(TargetPlatform.android_arm)
|
||||
: const AotElfProfile(TargetPlatform.android_arm);
|
||||
}
|
||||
|
||||
Status status;
|
||||
|
|
|
@ -23,6 +23,7 @@ enum Artifact {
|
|||
flutterMacOSFramework,
|
||||
vmSnapshotData,
|
||||
isolateSnapshotData,
|
||||
icuData,
|
||||
platformKernelDill,
|
||||
platformLibrariesJson,
|
||||
flutterPatchedSdkPath,
|
||||
|
@ -86,6 +87,8 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo
|
|||
return 'vm_isolate_snapshot.bin';
|
||||
case Artifact.isolateSnapshotData:
|
||||
return 'isolate_snapshot.bin';
|
||||
case Artifact.icuData:
|
||||
return 'icudtl.dat';
|
||||
case Artifact.platformKernelDill:
|
||||
return 'platform_strong.dill';
|
||||
case Artifact.platformLibrariesJson:
|
||||
|
@ -212,12 +215,12 @@ class CachedArtifacts extends Artifacts {
|
|||
case TargetPlatform.ios:
|
||||
return _getIosArtifactPath(artifact, platform, mode);
|
||||
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_x64:
|
||||
return _getFuchsiaArtifactPath(artifact, platform, mode);
|
||||
case TargetPlatform.linux_x64:
|
||||
case TargetPlatform.windows_x64:
|
||||
case TargetPlatform.tester:
|
||||
case TargetPlatform.web_javascript:
|
||||
default: // could be null, but that can't be specified as a case.
|
||||
|
@ -230,7 +233,7 @@ class CachedArtifacts extends Artifacts {
|
|||
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
|
||||
// and not the gen_snapshot for darwin as a target platform.
|
||||
if (platform != null && artifact == Artifact.genSnapshot) {
|
||||
|
@ -331,6 +334,7 @@ class CachedArtifacts extends Artifacts {
|
|||
case Artifact.vmSnapshotData:
|
||||
case Artifact.isolateSnapshotData:
|
||||
case Artifact.frontendServerSnapshotForEngineDartSdk:
|
||||
case Artifact.icuData:
|
||||
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
|
||||
final String platformDirName = getNameForTargetPlatform(platform);
|
||||
return _fileSystem.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact, platform, mode));
|
||||
|
@ -491,6 +495,8 @@ class LocalEngineArtifacts extends Artifacts {
|
|||
case Artifact.isolateSnapshotData:
|
||||
case Artifact.vmSnapshotData:
|
||||
return _fileSystem.path.join(engineOutPath, 'gen', 'flutter', 'lib', 'snapshot', artifactFileName);
|
||||
case Artifact.icuData:
|
||||
return _fileSystem.path.join(engineOutPath, artifactFileName);
|
||||
case Artifact.platformKernelDill:
|
||||
if (platform == TargetPlatform.fuchsia_x64 || platform == TargetPlatform.fuchsia_arm64) {
|
||||
return _fileSystem.path.join(engineOutPath, 'flutter_runner_patched_sdk', artifactFileName);
|
||||
|
|
|
@ -298,6 +298,7 @@ class AOTSnapshotter {
|
|||
TargetPlatform.android_x64,
|
||||
TargetPlatform.ios,
|
||||
TargetPlatform.darwin_x64,
|
||||
TargetPlatform.windows_x64,
|
||||
].contains(platform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ class ProfileAndroidApplication extends CopyFlutterAotBundle {
|
|||
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
AotElfProfile(),
|
||||
AotElfProfile(TargetPlatform.android_arm),
|
||||
AotAndroidAssetBundle(),
|
||||
];
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ class ReleaseAndroidApplication extends CopyFlutterAotBundle {
|
|||
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
AotElfRelease(),
|
||||
AotElfRelease(TargetPlatform.android_arm),
|
||||
AotAndroidAssetBundle(),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -312,20 +312,20 @@ abstract class AotElfBase extends Target {
|
|||
|
||||
/// Generate an ELF binary from a dart kernel file in profile mode.
|
||||
class AotElfProfile extends AotElfBase {
|
||||
const AotElfProfile();
|
||||
const AotElfProfile(this.targetPlatform);
|
||||
|
||||
@override
|
||||
String get name => 'aot_elf_profile';
|
||||
|
||||
@override
|
||||
List<Source> get inputs => const <Source>[
|
||||
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
|
||||
Source.pattern('{BUILD_DIR}/app.dill'),
|
||||
Source.pattern('{PROJECT_DIR}/.packages'),
|
||||
Source.artifact(Artifact.engineDartBinary),
|
||||
Source.artifact(Artifact.skyEnginePath),
|
||||
List<Source> get inputs => <Source>[
|
||||
const Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
|
||||
const Source.pattern('{BUILD_DIR}/app.dill'),
|
||||
const Source.pattern('{PROJECT_DIR}/.packages'),
|
||||
const Source.artifact(Artifact.engineDartBinary),
|
||||
const Source.artifact(Artifact.skyEnginePath),
|
||||
Source.artifact(Artifact.genSnapshot,
|
||||
platform: TargetPlatform.android_arm,
|
||||
platform: targetPlatform,
|
||||
mode: BuildMode.profile,
|
||||
),
|
||||
];
|
||||
|
@ -339,24 +339,26 @@ class AotElfProfile extends AotElfBase {
|
|||
List<Target> get dependencies => const <Target>[
|
||||
KernelSnapshot(),
|
||||
];
|
||||
|
||||
final TargetPlatform targetPlatform;
|
||||
}
|
||||
|
||||
/// Generate an ELF binary from a dart kernel file in release mode.
|
||||
class AotElfRelease extends AotElfBase {
|
||||
const AotElfRelease();
|
||||
const AotElfRelease(this.targetPlatform);
|
||||
|
||||
@override
|
||||
String get name => 'aot_elf_release';
|
||||
|
||||
@override
|
||||
List<Source> get inputs => const <Source>[
|
||||
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
|
||||
Source.pattern('{BUILD_DIR}/app.dill'),
|
||||
Source.pattern('{PROJECT_DIR}/.packages'),
|
||||
Source.artifact(Artifact.engineDartBinary),
|
||||
Source.artifact(Artifact.skyEnginePath),
|
||||
List<Source> get inputs => <Source>[
|
||||
const Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/dart.dart'),
|
||||
const Source.pattern('{BUILD_DIR}/app.dill'),
|
||||
const Source.pattern('{PROJECT_DIR}/.packages'),
|
||||
const Source.artifact(Artifact.engineDartBinary),
|
||||
const Source.artifact(Artifact.skyEnginePath),
|
||||
Source.artifact(Artifact.genSnapshot,
|
||||
platform: TargetPlatform.android_arm,
|
||||
platform: targetPlatform,
|
||||
mode: BuildMode.release,
|
||||
),
|
||||
];
|
||||
|
@ -370,6 +372,8 @@ class AotElfRelease extends AotElfBase {
|
|||
List<Target> get dependencies => const <Target>[
|
||||
KernelSnapshot(),
|
||||
];
|
||||
|
||||
final TargetPlatform targetPlatform;
|
||||
}
|
||||
|
||||
/// Copies the pre-built flutter aot bundle.
|
||||
|
|
|
@ -7,8 +7,9 @@ import 'package:meta/meta.dart';
|
|||
import '../../base/file_system.dart';
|
||||
import '../depfile.dart';
|
||||
|
||||
/// Unpack the engine artifact list [artifacts] from [engineSourcePath] and
|
||||
/// [clientSourcePaths] (if provided) into a directory [outputDirectory].
|
||||
/// Unpack the engine artifact list [artifacts] from [engineSourcePath], ICU
|
||||
/// data (if provided), and [clientSourcePaths] (if provided) into a directory
|
||||
/// [outputDirectory].
|
||||
///
|
||||
/// Returns a [Depfile] including all copied files.
|
||||
///
|
||||
|
@ -20,6 +21,7 @@ Depfile unpackDesktopArtifacts({
|
|||
@required Directory outputDirectory,
|
||||
@required String engineSourcePath,
|
||||
List<String> clientSourcePaths,
|
||||
String icuDataPath,
|
||||
}) {
|
||||
final List<File> inputs = <File>[];
|
||||
final List<File> outputs = <File>[];
|
||||
|
@ -30,7 +32,7 @@ Depfile unpackDesktopArtifacts({
|
|||
if (entityType == FileSystemEntityType.notFound
|
||||
|| entityType == FileSystemEntityType.directory
|
||||
|| entityType == FileSystemEntityType.link) {
|
||||
throw Exception('Unsupported file type: $entityType');
|
||||
throw Exception('Unsupported file type "$entityType" for $entityPath');
|
||||
}
|
||||
assert(entityType == FileSystemEntityType.file);
|
||||
final String outputPath = fileSystem.path.join(
|
||||
|
@ -46,6 +48,13 @@ Depfile unpackDesktopArtifacts({
|
|||
inputs.add(inputFile);
|
||||
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) {
|
||||
return Depfile(inputs, outputs);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ const List<String> _kWindowsArtifacts = <String>[
|
|||
'flutter_messenger.h',
|
||||
'flutter_plugin_registrar.h',
|
||||
'flutter_windows.h',
|
||||
'icudtl.dat',
|
||||
];
|
||||
|
||||
const String _kWindowsDepfile = 'windows_engine_sources.d';
|
||||
|
@ -78,6 +77,10 @@ class UnpackWindows extends Target {
|
|||
engineSourcePath: engineSourcePath,
|
||||
outputDirectory: outputDirectory,
|
||||
clientSourcePaths: <String>[clientSourcePath],
|
||||
icuDataPath: environment.artifacts.getArtifactPath(
|
||||
Artifact.icuData,
|
||||
platform: TargetPlatform.windows_x64
|
||||
)
|
||||
);
|
||||
final DepfileService depfileService = DepfileService(
|
||||
fileSystem: environment.fileSystem,
|
||||
|
@ -90,12 +93,9 @@ class UnpackWindows extends Target {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a debug bundle for the Windows desktop target.
|
||||
class DebugBundleWindowsAssets extends Target {
|
||||
const DebugBundleWindowsAssets();
|
||||
|
||||
@override
|
||||
String get name => 'debug_bundle_windows_assets';
|
||||
/// Creates a bundle for the Windows desktop target.
|
||||
abstract class BundleWindowsAssets extends Target {
|
||||
const BundleWindowsAssets();
|
||||
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
|
@ -105,17 +105,11 @@ class DebugBundleWindowsAssets extends Target {
|
|||
|
||||
@override
|
||||
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('{PROJECT_DIR}/pubspec.yaml'),
|
||||
...IconTreeShaker.inputs,
|
||||
];
|
||||
|
||||
@override
|
||||
List<Source> get outputs => const <Source>[
|
||||
Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'),
|
||||
];
|
||||
|
||||
@override
|
||||
List<String> get depfiles => const <String>[
|
||||
'flutter_assets.d',
|
||||
|
@ -124,7 +118,7 @@ class DebugBundleWindowsAssets extends Target {
|
|||
@override
|
||||
Future<void> build(Environment environment) async {
|
||||
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 Directory outputDirectory = environment.outputDir
|
||||
|
@ -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>[
|
|||
// Shared targets
|
||||
CopyAssets(),
|
||||
KernelSnapshot(),
|
||||
AotElfProfile(),
|
||||
AotElfRelease(),
|
||||
AotElfProfile(TargetPlatform.android_arm),
|
||||
AotElfRelease(TargetPlatform.android_arm),
|
||||
AotAssemblyProfile(),
|
||||
AotAssemblyRelease(),
|
||||
// macOS targets
|
||||
|
@ -63,6 +63,8 @@ const List<Target> _kDefaultTargets = <Target>[
|
|||
// Windows targets
|
||||
UnpackWindows(),
|
||||
DebugBundleWindowsAssets(),
|
||||
ProfileBundleWindowsAssets(),
|
||||
ReleaseBundleWindowsAssets(),
|
||||
];
|
||||
|
||||
/// Assemble provides a low level API to interact with the flutter tool build
|
||||
|
|
|
@ -7,6 +7,7 @@ import '../base/common.dart';
|
|||
import '../base/file_system.dart';
|
||||
import '../base/logger.dart';
|
||||
import '../base/process.dart';
|
||||
import '../base/utils.dart';
|
||||
import '../build_info.dart';
|
||||
import '../cache.dart';
|
||||
import '../globals.dart' as globals;
|
||||
|
@ -57,15 +58,6 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {
|
|||
'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(
|
||||
Cache.flutterRoot,
|
||||
'packages',
|
||||
|
@ -74,7 +66,7 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {
|
|||
'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 Stopwatch sw = Stopwatch()..start();
|
||||
final Status status = globals.logger.startProgress(
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
</Message>
|
||||
</PostBuildEvent>
|
||||
<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>
|
||||
<Message>Bundling dependencies</Message>
|
||||
|
@ -165,7 +165,7 @@
|
|||
</Message>
|
||||
</PostBuildEvent>
|
||||
<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>
|
||||
<Message>Bundling dependencies</Message>
|
||||
|
@ -214,7 +214,7 @@
|
|||
</Message>
|
||||
</PostBuildEvent>
|
||||
<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>
|
||||
<Message>Bundling dependencies</Message>
|
||||
|
|
|
@ -4,6 +4,7 @@ set FLUTTER_CACHE_DIR=%~1
|
|||
set BUNDLE_DIR=%~2
|
||||
set PLUGIN_DIR=%~3
|
||||
set EXE_NAME=%~4
|
||||
set BUILD_MODE=%~5
|
||||
|
||||
set DATA_DIR=%BUNDLE_DIR%data
|
||||
|
||||
|
@ -14,18 +15,24 @@ if %errorlevel% neq 0 exit /b %errorlevel%
|
|||
echo %EXE_NAME%>"%FLUTTER_CACHE_DIR%exe_filename"
|
||||
|
||||
:: 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 TARGET_ASSET_DIR=%DATA_DIR%\%ASSET_DIR_NAME%
|
||||
if exist "%TARGET_ASSET_DIR%" call rmdir /s /q "%TARGET_ASSET_DIR%"
|
||||
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%
|
||||
|
||||
:: 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%"
|
||||
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.
|
||||
call xcopy /y /d /q "%FLUTTER_CACHE_DIR%flutter_windows.dll" "%BUNDLE_DIR%"
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
|
|
@ -304,31 +304,28 @@ void main() {
|
|||
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()
|
||||
..visualStudioOverride = mockVisualStudio;
|
||||
applyMocksToCommand(command);
|
||||
setUpMockProjectFilesForBuild();
|
||||
when(mockVisualStudio.vcvarsPath).thenReturn(vcvarsPath);
|
||||
|
||||
when(mockProcessManager.start(
|
||||
<String>[
|
||||
when(mockProcessManager.start(<String>[
|
||||
fileSystem.path.join(flutterRoot, 'packages', 'flutter_tools', 'bin', 'vs_build.bat'),
|
||||
vcvarsPath,
|
||||
fileSystem.path.basename(solutionPath),
|
||||
'Release',
|
||||
'Profile',
|
||||
],
|
||||
environment: <String, String>{},
|
||||
workingDirectory: fileSystem.path.dirname(solutionPath))).thenAnswer((Invocation invocation) async {
|
||||
workingDirectory: fileSystem.path.dirname(solutionPath))
|
||||
).thenAnswer((Invocation invocation) async {
|
||||
return mockProcess;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
await createTestCommandRunner(command).run(
|
||||
const <String>['windows', '--no-pub']
|
||||
const <String>['windows', '--profile', '--no-pub']
|
||||
);
|
||||
|
||||
expect(testLogger.statusText, contains('🚧'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => mockProcessManager,
|
||||
|
|
|
@ -333,7 +333,7 @@ void main() {
|
|||
]);
|
||||
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);
|
||||
}));
|
||||
|
@ -341,14 +341,14 @@ void main() {
|
|||
test('AotElfProfile throws error if missing build mode', () => testbed.run(() async {
|
||||
androidEnvironment.defines.remove(kBuildMode);
|
||||
|
||||
expect(const AotElfProfile().build(androidEnvironment),
|
||||
expect(const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment),
|
||||
throwsA(isA<MissingDefineException>()));
|
||||
}));
|
||||
|
||||
test('AotElfProfile throws error if missing target platform', () => testbed.run(() async {
|
||||
androidEnvironment.defines.remove(kTargetPlatform);
|
||||
|
||||
expect(const AotElfProfile().build(androidEnvironment),
|
||||
expect(const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment),
|
||||
throwsA(isA<MissingDefineException>()));
|
||||
}));
|
||||
|
||||
|
@ -594,7 +594,7 @@ void main() {
|
|||
]),
|
||||
]);
|
||||
|
||||
await const AotElfRelease().build(androidEnvironment);
|
||||
await const AotElfRelease(TargetPlatform.android_arm).build(androidEnvironment);
|
||||
|
||||
expect(processManager.hasRemainingExpectations, false);
|
||||
}));
|
||||
|
|
|
@ -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/logger.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/depfile.dart';
|
||||
import 'package:flutter_tools/src/build_system/targets/dart.dart';
|
||||
|
@ -67,6 +68,11 @@ void main() {
|
|||
mode: anyNamed('mode'),
|
||||
platform: anyNamed('platform')
|
||||
)).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) {
|
||||
fileSystem.file(path).createSync(recursive: true);
|
||||
}
|
||||
|
@ -158,6 +164,60 @@ void main() {
|
|||
FileSystem: () => fileSystem,
|
||||
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 {}
|
||||
|
|
Loading…
Reference in a new issue