[native assets] Create NativeAssetsManifest.json
instead of kernel embedding (#159322)
This PR introduces a `NativeAssetsManifest.json` next to the `AssetManifest.bin` and `FontManifest.json`. This removes the need for embedding the native assets mapping inside the kernel file and enables decoupling native assets building and bundling from the kernel compilation in flutter tools. This means `flutter run` no longer does a dry run of `hook/build.dart` hooks. (It also means all isolate groups will have the same native assets. However, since Flutter does not support `Isolate.spawnUri` from kernel files, this is not a regression.) Implementation details: * g3 is still using kernel embedding. https://github.com/flutter/flutter/pull/142016 introduced an argument to embed a `native_assets.yaml` inside `flutter attach` and `flutter run` (the outer flutter process), but it is not used in `flutter assemble` (the inner process when doing `flutter run`). So, those arguments need to still be respected. However, all other logic related to embedding a yaml encoding in the kernel file has been removed. * All dry-run logic has been removed. 🎉 * The `KernelSnapshot` target no longer depends on the `InstallCodeAssets` target. Instead, the various OS-specific "BundleAsset" targets now depend on the `InstallCodeAssets` target. The `InstallCodeAssets` invokes the build hooks and produces the `NativeAssetsManifest.json`. The various "BundleAsset" commands synchronize the `NativeAssetsManifest.json` to the app bundle. * `InstallCodeAssets` produces a `native_assets.json`, which is renamed to `NativeAssetsManifest.json` in the various "Bundle" targets. This means that all unit tests of the "Bundle" targets now need to create this file. (Similar to how `app.dill` is expected to exist because `KernelSnapshot` is a dependency of the "Bundle" targets.) * Because dynamic libraries need to be code signed (at least on iOS and MacOS), the bundling of the dylibs is _not_ migrated to reuse `_updateDevFS` (which is used for ordinary assets). Only the 2nd and 3rd invocation of `flutter assemble` from `xcodebuild` has access to the code signing identity. Relevant tests: * test/integration.shard/isolated/native_assets_test.dart - runs `flutter run` with native assets including hot restart and hot reload. TODO: * Undo engine-roll in this PR after engine has rolled in. Issue: * https://github.com/flutter/flutter/issues/154425 Related PRs: * https://dart-review.googlesource.com/c/sdk/+/388161 * https://github.com/flutter/engine/pull/56727 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
c6260a86f6
commit
4aa2caef20
@ -218,7 +218,7 @@ EmbedFrameworks() {
|
||||
fi
|
||||
local native_assets_path="${project_path}/${FLUTTER_BUILD_DIR}/native_assets/macos/"
|
||||
if [[ -d "$native_assets_path" ]]; then
|
||||
RunCommand rsync -av --filter "- .DS_Store" --filter "- native_assets.yaml" "${native_assets_path}" "${xcode_frameworks_dir}"
|
||||
RunCommand rsync -av --filter "- .DS_Store" --filter "- native_assets.yaml" --filter "- native_assets.json" "${native_assets_path}" "${xcode_frameworks_dir}"
|
||||
|
||||
# Iterate through all .frameworks in native assets directory.
|
||||
for native_asset in "${native_assets_path}"*.framework; do
|
||||
|
@ -245,6 +245,8 @@ class Context {
|
||||
extraArgs: <String>[
|
||||
'--filter',
|
||||
'- native_assets.yaml',
|
||||
'--filter',
|
||||
'- native_assets.json',
|
||||
],
|
||||
nativeAssetsPath,
|
||||
xcodeFrameworksDir,
|
||||
|
@ -49,7 +49,6 @@ import 'src/globals.dart' as globals;
|
||||
// Files in `isolated` are intentionally excluded from google3 tooling.
|
||||
import 'src/isolated/build_targets.dart';
|
||||
import 'src/isolated/mustache_template.dart';
|
||||
import 'src/isolated/native_assets/native_assets.dart';
|
||||
import 'src/isolated/native_assets/test/native_assets.dart';
|
||||
import 'src/isolated/resident_web_runner.dart';
|
||||
import 'src/native_assets.dart';
|
||||
@ -181,7 +180,6 @@ List<FlutterCommand> generateCommands({
|
||||
platform: globals.platform,
|
||||
processInfo: globals.processInfo,
|
||||
fileSystem: globals.fs,
|
||||
nativeAssetsBuilder: const HotRunnerNativeAssetsBuilderImpl(),
|
||||
),
|
||||
BuildCommand(
|
||||
artifacts: globals.artifacts!,
|
||||
@ -244,7 +242,6 @@ List<FlutterCommand> generateCommands({
|
||||
),
|
||||
RunCommand(
|
||||
verboseHelp: verboseHelp,
|
||||
nativeAssetsBuilder: const HotRunnerNativeAssetsBuilderImpl(),
|
||||
),
|
||||
ScreenshotCommand(fs: globals.fs),
|
||||
ShellCompletionCommand(),
|
||||
|
@ -7,6 +7,7 @@ import '../../base/build.dart';
|
||||
import '../../base/deferred_component.dart';
|
||||
import '../../base/file_system.dart';
|
||||
import '../../build_info.dart';
|
||||
import '../../devfs.dart';
|
||||
import '../../globals.dart' as globals show xcode;
|
||||
import '../../project.dart';
|
||||
import '../build_system.dart';
|
||||
@ -15,6 +16,7 @@ import '../exceptions.dart';
|
||||
import 'assets.dart';
|
||||
import 'common.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'native_assets.dart';
|
||||
|
||||
/// Prepares the asset bundle in the format expected by flutter.gradle.
|
||||
///
|
||||
@ -68,6 +70,10 @@ abstract class AndroidAssetBundle extends Target {
|
||||
targetPlatform: TargetPlatform.android,
|
||||
buildMode: buildMode,
|
||||
flavor: environment.defines[kFlavor],
|
||||
additionalContent: <String, DevFSContent>{
|
||||
'NativeAssetsManifest.json':
|
||||
DevFSFileContent(environment.buildDir.childFile('native_assets.json')),
|
||||
},
|
||||
);
|
||||
environment.depFileService.writeToFile(
|
||||
assetDepfile,
|
||||
@ -78,6 +84,7 @@ abstract class AndroidAssetBundle extends Target {
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
KernelSnapshot(),
|
||||
InstallCodeAssets(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import '../tools/scene_importer.dart';
|
||||
import '../tools/shader_compiler.dart';
|
||||
import 'common.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'native_assets.dart';
|
||||
|
||||
/// A helper function to copy an asset bundle into an [environment]'s output
|
||||
/// directory.
|
||||
@ -329,6 +330,7 @@ class CopyAssets extends Target {
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
KernelSnapshot(),
|
||||
InstallCodeAssets(),
|
||||
];
|
||||
|
||||
@override
|
||||
@ -363,6 +365,10 @@ class CopyAssets extends Target {
|
||||
targetPlatform: TargetPlatform.android,
|
||||
buildMode: buildMode,
|
||||
flavor: environment.defines[kFlavor],
|
||||
additionalContent: <String, DevFSContent>{
|
||||
'NativeAssetsManifest.json':
|
||||
DevFSFileContent(environment.buildDir.childFile('native_assets.json')),
|
||||
},
|
||||
);
|
||||
environment.depFileService.writeToFile(
|
||||
depfile,
|
||||
|
@ -3,16 +3,15 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
import '../../artifacts.dart';
|
||||
import '../../base/build.dart';
|
||||
import '../../base/common.dart';
|
||||
import '../../base/file_system.dart';
|
||||
import '../../base/io.dart';
|
||||
import '../../build_info.dart';
|
||||
import '../../compile.dart';
|
||||
import '../../dart/package_map.dart';
|
||||
import '../../devfs.dart';
|
||||
import '../../globals.dart' as globals show xcode;
|
||||
import '../build_system.dart';
|
||||
import '../depfile.dart';
|
||||
@ -81,6 +80,10 @@ class CopyFlutterBundle extends Target {
|
||||
targetPlatform: TargetPlatform.android,
|
||||
buildMode: buildMode,
|
||||
flavor: flavor,
|
||||
additionalContent: <String, DevFSContent>{
|
||||
'NativeAssetsManifest.json':
|
||||
DevFSFileContent(environment.buildDir.childFile('native_assets.json')),
|
||||
},
|
||||
);
|
||||
environment.depFileService.writeToFile(
|
||||
assetDepfile,
|
||||
@ -91,6 +94,7 @@ class CopyFlutterBundle extends Target {
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
KernelSnapshot(),
|
||||
InstallCodeAssets(),
|
||||
];
|
||||
}
|
||||
|
||||
@ -122,11 +126,8 @@ class ReleaseCopyFlutterBundle extends CopyFlutterBundle {
|
||||
/// even though it is not listed as an input. Pub inserts a timestamp into
|
||||
/// the file which causes unnecessary rebuilds, so instead a subset of the contents
|
||||
/// are used an input instead.
|
||||
///
|
||||
/// This kernel snapshot is concatenated with the [KernelSnapshotNativeAssets]
|
||||
/// inside [KernelSnapshot] byte-wise to create the combined kernel snapshot.
|
||||
class KernelSnapshotProgram extends Target {
|
||||
const KernelSnapshotProgram();
|
||||
class KernelSnapshot extends Target {
|
||||
const KernelSnapshot();
|
||||
|
||||
@override
|
||||
String get name => 'kernel_snapshot_program';
|
||||
@ -143,7 +144,7 @@ class KernelSnapshotProgram extends Target {
|
||||
|
||||
@override
|
||||
List<Source> get outputs => const <Source>[
|
||||
Source.pattern('{BUILD_DIR}/${KernelSnapshotProgram.dillName}'),
|
||||
Source.pattern('{BUILD_DIR}/${KernelSnapshot.dillName}'),
|
||||
// TODO(mosuem): Should output resources.json. https://github.com/flutter/flutter/issues/146263
|
||||
];
|
||||
|
||||
@ -160,7 +161,7 @@ class KernelSnapshotProgram extends Target {
|
||||
DartPluginRegistrantTarget(),
|
||||
];
|
||||
|
||||
static const String dillName = 'program.dill';
|
||||
static const String dillName = 'app.dill';
|
||||
|
||||
@override
|
||||
Future<void> build(Environment environment) async {
|
||||
@ -276,150 +277,6 @@ class KernelSnapshotProgram extends Target {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a kernel snapshot of the native assets mapping for resolving
|
||||
/// `@Native` assets at runtime.
|
||||
///
|
||||
/// This kernel snapshot is concatenated to the [KernelSnapshotProgram]
|
||||
/// inside [KernelSnapshot] to create the combined kernel snapshot.
|
||||
class KernelSnapshotNativeAssets extends Target {
|
||||
const KernelSnapshotNativeAssets();
|
||||
|
||||
@override
|
||||
String get name => 'kernel_snapshot_native_assets';
|
||||
|
||||
@override
|
||||
List<Source> get inputs => <Source>[
|
||||
const Source.pattern('{BUILD_DIR}/${InstallCodeAssets.nativeAssetsFilename}'),
|
||||
...const KernelSnapshotProgram().inputs,
|
||||
];
|
||||
|
||||
@override
|
||||
List<Source> get outputs => const <Source>[
|
||||
Source.pattern('{BUILD_DIR}/${KernelSnapshotNativeAssets.dillName}'),
|
||||
];
|
||||
|
||||
@override
|
||||
List<String> get depfiles => const <String>[];
|
||||
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
InstallCodeAssets(),
|
||||
];
|
||||
|
||||
static const String dillName = 'native_assets.dill';
|
||||
|
||||
@override
|
||||
Future<void> build(Environment environment) async {
|
||||
final File nativeAssetsFile = environment.buildDir.childFile(InstallCodeAssets.nativeAssetsFilename);
|
||||
final File dillFile = environment.buildDir.childFile(dillName);
|
||||
|
||||
final YamlNode nativeAssetContents = loadYamlNode(await nativeAssetsFile.readAsString());
|
||||
final Object? nativeAssetsInYaml = (nativeAssetContents as Map<Object?, Object?>)['native-assets'];
|
||||
if (nativeAssetsInYaml is! Map || nativeAssetsInYaml.isEmpty) {
|
||||
// Write an empty file to make concatenation a no-op.
|
||||
// Write the file out to disk for caching.
|
||||
await dillFile.writeAsBytes(<int>[]);
|
||||
return;
|
||||
}
|
||||
|
||||
final KernelCompiler compiler = KernelCompiler(
|
||||
fileSystem: environment.fileSystem,
|
||||
logger: environment.logger,
|
||||
processManager: environment.processManager,
|
||||
artifacts: environment.artifacts,
|
||||
fileSystemRoots: <String>[],
|
||||
);
|
||||
final String? buildModeEnvironment = environment.defines[kBuildMode];
|
||||
if (buildModeEnvironment == null) {
|
||||
throw MissingDefineException(kBuildMode, 'kernel_snapshot');
|
||||
}
|
||||
final String? targetPlatformEnvironment = environment.defines[kTargetPlatform];
|
||||
if (targetPlatformEnvironment == null) {
|
||||
throw MissingDefineException(kTargetPlatform, 'kernel_snapshot');
|
||||
}
|
||||
final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment);
|
||||
final File packageConfigFile = findPackageConfigFileOrDefault(environment.projectDir);
|
||||
|
||||
final TargetPlatform targetPlatform = getTargetPlatformForName(targetPlatformEnvironment);
|
||||
|
||||
final String? frontendServerStarterPath = environment.defines[kFrontendServerStarterPath];
|
||||
|
||||
final String nativeAssets = nativeAssetsFile.path;
|
||||
if (!await nativeAssetsFile.exists()) {
|
||||
throwToolExit("$nativeAssets doesn't exist.");
|
||||
}
|
||||
environment.logger.printTrace('Embedding native assets mapping $nativeAssets in kernel.');
|
||||
|
||||
final PackageConfig packageConfig = await loadPackageConfigWithLogging(
|
||||
packageConfigFile,
|
||||
logger: environment.logger,
|
||||
);
|
||||
|
||||
final String dillPath = dillFile.path;
|
||||
|
||||
final CompilerOutput? output = await compiler.compile(
|
||||
sdkRoot: environment.artifacts.getArtifactPath(
|
||||
Artifact.flutterPatchedSdkPath,
|
||||
platform: targetPlatform,
|
||||
mode: buildMode,
|
||||
),
|
||||
aot: buildMode.isPrecompiled,
|
||||
buildMode: buildMode,
|
||||
trackWidgetCreation: false,
|
||||
outputFilePath: dillPath,
|
||||
packagesPath: packageConfigFile.path,
|
||||
frontendServerStarterPath: frontendServerStarterPath,
|
||||
packageConfig: packageConfig,
|
||||
buildDir: environment.buildDir,
|
||||
dartDefines: <String>[],
|
||||
nativeAssets: nativeAssets,
|
||||
);
|
||||
if (output == null || output.errorCount != 0) {
|
||||
throw Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KernelSnapshot extends Target {
|
||||
const KernelSnapshot();
|
||||
|
||||
@override
|
||||
String get name => 'kernel_snapshot';
|
||||
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
KernelSnapshotProgram(),
|
||||
KernelSnapshotNativeAssets(),
|
||||
];
|
||||
|
||||
@override
|
||||
List<Source> get inputs => const <Source>[
|
||||
Source.pattern('{BUILD_DIR}/${KernelSnapshotProgram.dillName}'),
|
||||
Source.pattern('{BUILD_DIR}/${KernelSnapshotNativeAssets.dillName}'),
|
||||
];
|
||||
|
||||
@override
|
||||
List<Source> get outputs => <Source>[];
|
||||
|
||||
static const String dillName = 'app.dill';
|
||||
|
||||
@override
|
||||
Future<void> build(Environment environment) async {
|
||||
final File programDill = environment.buildDir.childFile(
|
||||
KernelSnapshotProgram.dillName,
|
||||
);
|
||||
final File nativeAssetsDill = environment.buildDir.childFile(
|
||||
KernelSnapshotNativeAssets.dillName,
|
||||
);
|
||||
final File dill = environment.buildDir.childFile(dillName);
|
||||
await programDill.copy(dill.path);
|
||||
await dill.writeAsBytes(
|
||||
await nativeAssetsDill.readAsBytes(),
|
||||
mode: FileMode.append,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Supports compiling a dart kernel file to an ELF binary.
|
||||
abstract class AotElfBase extends Target {
|
||||
const AotElfBase();
|
||||
|
@ -12,6 +12,7 @@ import '../../base/file_system.dart';
|
||||
import '../../base/io.dart';
|
||||
import '../../base/process.dart';
|
||||
import '../../build_info.dart';
|
||||
import '../../devfs.dart';
|
||||
import '../../globals.dart' as globals;
|
||||
import '../../ios/mac.dart';
|
||||
import '../../macos/xcode.dart';
|
||||
@ -24,6 +25,7 @@ import '../tools/shader_compiler.dart';
|
||||
import 'assets.dart';
|
||||
import 'common.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'native_assets.dart';
|
||||
|
||||
/// Supports compiling a dart kernel file to an assembly file.
|
||||
///
|
||||
@ -464,6 +466,7 @@ abstract class IosAssetBundle extends Target {
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
KernelSnapshot(),
|
||||
InstallCodeAssets(),
|
||||
];
|
||||
|
||||
@override
|
||||
@ -551,6 +554,10 @@ abstract class IosAssetBundle extends Target {
|
||||
flutterProject.ios.infoPlist,
|
||||
flutterProject.ios.appFrameworkInfoPlist,
|
||||
],
|
||||
additionalContent: <String, DevFSContent>{
|
||||
'NativeAssetsManifest.json':
|
||||
DevFSFileContent(environment.buildDir.childFile('native_assets.json')),
|
||||
},
|
||||
flavor: environment.defines[kFlavor],
|
||||
);
|
||||
environment.depFileService.writeToFile(
|
||||
@ -625,6 +632,7 @@ class ProfileIosApplicationBundle extends _IosAssetBundleWithDSYM {
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
AotAssemblyProfile(),
|
||||
InstallCodeAssets(),
|
||||
];
|
||||
}
|
||||
|
||||
@ -638,6 +646,7 @@ class ReleaseIosApplicationBundle extends _IosAssetBundleWithDSYM {
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
AotAssemblyRelease(),
|
||||
InstallCodeAssets(),
|
||||
];
|
||||
|
||||
@override
|
||||
|
@ -15,6 +15,7 @@ import 'assets.dart';
|
||||
import 'common.dart';
|
||||
import 'desktop.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'native_assets.dart';
|
||||
|
||||
/// The only files/subdirectories we care out.
|
||||
const List<String> _kLinuxArtifacts = <String>[
|
||||
@ -99,6 +100,7 @@ abstract class BundleLinuxAssets extends Target {
|
||||
@override
|
||||
List<Target> get dependencies => <Target>[
|
||||
const KernelSnapshot(),
|
||||
const InstallCodeAssets(),
|
||||
UnpackLinux(targetPlatform),
|
||||
];
|
||||
|
||||
@ -140,6 +142,8 @@ abstract class BundleLinuxAssets extends Target {
|
||||
buildMode: buildMode,
|
||||
additionalContent: <String, DevFSContent>{
|
||||
'version.json': DevFSStringContent(versionInfo),
|
||||
'NativeAssetsManifest.json':
|
||||
DevFSFileContent(environment.buildDir.childFile('native_assets.json')),
|
||||
},
|
||||
);
|
||||
environment.depFileService.writeToFile(
|
||||
|
@ -10,6 +10,7 @@ import '../../base/file_system.dart';
|
||||
import '../../base/io.dart';
|
||||
import '../../base/process.dart';
|
||||
import '../../build_info.dart';
|
||||
import '../../devfs.dart';
|
||||
import '../../globals.dart' as globals show xcode;
|
||||
import '../../reporting/reporting.dart';
|
||||
import '../build_system.dart';
|
||||
@ -18,6 +19,7 @@ import '../exceptions.dart';
|
||||
import 'assets.dart';
|
||||
import 'common.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'native_assets.dart';
|
||||
|
||||
/// Copy the macOS framework to the correct copy dir by invoking 'rsync'.
|
||||
///
|
||||
@ -489,6 +491,10 @@ abstract class MacOSBundleFlutterAssets extends Target {
|
||||
targetPlatform: TargetPlatform.darwin,
|
||||
buildMode: buildMode,
|
||||
flavor: environment.defines[kFlavor],
|
||||
additionalContent: <String, DevFSContent>{
|
||||
'NativeAssetsManifest.json':
|
||||
DevFSFileContent(environment.buildDir.childFile('native_assets.json')),
|
||||
},
|
||||
);
|
||||
environment.depFileService.writeToFile(
|
||||
assetDepfile,
|
||||
@ -591,6 +597,7 @@ class DebugMacOSBundleFlutterAssets extends MacOSBundleFlutterAssets {
|
||||
KernelSnapshot(),
|
||||
DebugMacOSFramework(),
|
||||
DebugUnpackMacOS(),
|
||||
InstallCodeAssets(),
|
||||
];
|
||||
|
||||
@override
|
||||
@ -620,6 +627,7 @@ class ProfileMacOSBundleFlutterAssets extends MacOSBundleFlutterAssets {
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
CompileMacOSFramework(),
|
||||
InstallCodeAssets(),
|
||||
ProfileUnpackMacOS(),
|
||||
];
|
||||
|
||||
@ -647,6 +655,7 @@ class ReleaseMacOSBundleFlutterAssets extends MacOSBundleFlutterAssets {
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
CompileMacOSFramework(),
|
||||
InstallCodeAssets(),
|
||||
ReleaseUnpackMacOS(),
|
||||
];
|
||||
|
||||
|
@ -116,7 +116,7 @@ class DartBuildForNative extends DartBuild {
|
||||
|
||||
@override
|
||||
List<Target> get dependencies => const <Target>[
|
||||
KernelSnapshotProgram(),
|
||||
KernelSnapshot(),
|
||||
];
|
||||
}
|
||||
|
||||
@ -125,11 +125,6 @@ class DartBuildForNative extends DartBuild {
|
||||
/// The build mode and target architecture can be changed from the
|
||||
/// native build project (Xcode etc.), so only `flutter assemble` has the
|
||||
/// information about build-mode and target architecture.
|
||||
/// Invocations of flutter_tools other than `flutter assemble` are dry runs.
|
||||
///
|
||||
/// This step needs to be consistent with the dry run invocations in `flutter
|
||||
/// run`s so that the kernel mapping of asset id to dylib lines up after hot
|
||||
/// restart.
|
||||
class InstallCodeAssets extends Target {
|
||||
const InstallCodeAssets();
|
||||
|
||||
@ -188,7 +183,7 @@ class InstallCodeAssets extends Target {
|
||||
Source.pattern('{BUILD_DIR}/$nativeAssetsFilename'),
|
||||
];
|
||||
|
||||
static const String nativeAssetsFilename = 'native_assets.yaml';
|
||||
static const String nativeAssetsFilename = 'native_assets.json';
|
||||
static const String depFilename = 'install_code_assets.d';
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
import '../../artifacts.dart';
|
||||
import '../../base/file_system.dart';
|
||||
import '../../build_info.dart';
|
||||
import '../../devfs.dart';
|
||||
import '../build_system.dart';
|
||||
import '../depfile.dart';
|
||||
import '../exceptions.dart';
|
||||
@ -12,6 +13,7 @@ import 'assets.dart';
|
||||
import 'common.dart';
|
||||
import 'desktop.dart';
|
||||
import 'icon_tree_shaker.dart';
|
||||
import 'native_assets.dart';
|
||||
|
||||
/// The only files/subdirectories we care about.
|
||||
const List<String> _kWindowsArtifacts = <String>[
|
||||
@ -105,6 +107,7 @@ abstract class BundleWindowsAssets extends Target {
|
||||
@override
|
||||
List<Target> get dependencies => <Target>[
|
||||
const KernelSnapshot(),
|
||||
const InstallCodeAssets(),
|
||||
UnpackWindows(targetPlatform),
|
||||
];
|
||||
|
||||
@ -143,6 +146,10 @@ abstract class BundleWindowsAssets extends Target {
|
||||
outputDirectory,
|
||||
targetPlatform: targetPlatform,
|
||||
buildMode: buildMode,
|
||||
additionalContent: <String, DevFSContent>{
|
||||
'NativeAssetsManifest.json':
|
||||
DevFSFileContent(environment.buildDir.childFile('native_assets.json')),
|
||||
},
|
||||
);
|
||||
environment.depFileService.writeToFile(
|
||||
depfile,
|
||||
|
@ -68,7 +68,6 @@ class AttachCommand extends FlutterCommand {
|
||||
required Platform platform,
|
||||
required ProcessInfo processInfo,
|
||||
required FileSystem fileSystem,
|
||||
HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
}) : _hotRunnerFactory = hotRunnerFactory ?? HotRunnerFactory(),
|
||||
_stdio = stdio,
|
||||
_logger = logger,
|
||||
@ -76,8 +75,7 @@ class AttachCommand extends FlutterCommand {
|
||||
_signals = signals,
|
||||
_platform = platform,
|
||||
_processInfo = processInfo,
|
||||
_fileSystem = fileSystem,
|
||||
_nativeAssetsBuilder = nativeAssetsBuilder {
|
||||
_fileSystem = fileSystem {
|
||||
addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false, excludeRelease: true);
|
||||
usesTargetOption();
|
||||
usesPortOptions(verboseHelp: verboseHelp);
|
||||
@ -149,7 +147,6 @@ class AttachCommand extends FlutterCommand {
|
||||
final Platform _platform;
|
||||
final ProcessInfo _processInfo;
|
||||
final FileSystem _fileSystem;
|
||||
final HotRunnerNativeAssetsBuilder? _nativeAssetsBuilder;
|
||||
|
||||
@override
|
||||
final String name = 'attach';
|
||||
@ -348,7 +345,6 @@ known, it can be explicitly provided to attach via the command-line, e.g.
|
||||
device: device,
|
||||
flutterProject: flutterProject,
|
||||
usesIpv6: usesIpv6,
|
||||
nativeAssetsBuilder: _nativeAssetsBuilder,
|
||||
);
|
||||
late AppInstance app;
|
||||
try {
|
||||
@ -381,7 +377,6 @@ known, it can be explicitly provided to attach via the command-line, e.g.
|
||||
device: device,
|
||||
flutterProject: flutterProject,
|
||||
usesIpv6: usesIpv6,
|
||||
nativeAssetsBuilder: _nativeAssetsBuilder,
|
||||
);
|
||||
final Completer<void> onAppStart = Completer<void>.sync();
|
||||
TerminalHandler? terminalHandler;
|
||||
@ -438,7 +433,6 @@ known, it can be explicitly provided to attach via the command-line, e.g.
|
||||
required Device device,
|
||||
required FlutterProject flutterProject,
|
||||
required bool usesIpv6,
|
||||
required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
}) async {
|
||||
final BuildInfo buildInfo = await getBuildInfo();
|
||||
|
||||
@ -475,7 +469,6 @@ known, it can be explicitly provided to attach via the command-line, e.g.
|
||||
dillOutputPath: stringArg('output-dill'),
|
||||
flutterProject: flutterProject,
|
||||
nativeAssetsYamlFile: stringArg(FlutterOptions.kNativeAssetsYamlFile),
|
||||
nativeAssetsBuilder: _nativeAssetsBuilder,
|
||||
analytics: analytics,
|
||||
)
|
||||
: ColdRunner(
|
||||
@ -507,7 +500,6 @@ class HotRunnerFactory {
|
||||
bool stayResident = true,
|
||||
FlutterProject? flutterProject,
|
||||
String? nativeAssetsYamlFile,
|
||||
required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
required Analytics analytics,
|
||||
}) => HotRunner(
|
||||
devices,
|
||||
@ -520,7 +512,6 @@ class HotRunnerFactory {
|
||||
dillOutputPath: dillOutputPath,
|
||||
stayResident: stayResident,
|
||||
nativeAssetsYamlFile: nativeAssetsYamlFile,
|
||||
nativeAssetsBuilder: nativeAssetsBuilder,
|
||||
analytics: analytics,
|
||||
);
|
||||
}
|
||||
|
@ -286,6 +286,8 @@ class BuildIOSFrameworkCommand extends BuildFrameworkCommand {
|
||||
'- .DS_Store',
|
||||
'--filter',
|
||||
'- native_assets.yaml',
|
||||
'--filter',
|
||||
'- native_assets.json',
|
||||
nativeAssetsDirectory.path,
|
||||
modeDirectory.path,
|
||||
]);
|
||||
|
@ -118,6 +118,8 @@ class BuildMacOSFrameworkCommand extends BuildFrameworkCommand {
|
||||
'- .DS_Store',
|
||||
'--filter',
|
||||
'- native_assets.yaml',
|
||||
'--filter',
|
||||
'- native_assets.json',
|
||||
nativeAssetsDirectory.path,
|
||||
modeDirectory.path,
|
||||
]);
|
||||
|
@ -667,7 +667,6 @@ class AppDomain extends Domain {
|
||||
String? isolateFilter,
|
||||
bool machine = true,
|
||||
String? userIdentifier,
|
||||
required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
}) async {
|
||||
if (!await device.supportsRuntimeMode(options.buildInfo.mode)) {
|
||||
throw Exception(
|
||||
@ -717,7 +716,6 @@ class AppDomain extends Domain {
|
||||
hostIsIde: true,
|
||||
machine: machine,
|
||||
analytics: globals.analytics,
|
||||
nativeAssetsBuilder: nativeAssetsBuilder,
|
||||
);
|
||||
} else {
|
||||
runner = ColdRunner(
|
||||
|
@ -349,9 +349,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
|
||||
class RunCommand extends RunCommandBase {
|
||||
RunCommand({
|
||||
bool verboseHelp = false,
|
||||
HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
}) : _nativeAssetsBuilder = nativeAssetsBuilder,
|
||||
super(verboseHelp: verboseHelp) {
|
||||
}) : super(verboseHelp: verboseHelp) {
|
||||
requiresPubspecYaml();
|
||||
usesFilesystemOptions(hide: !verboseHelp);
|
||||
usesExtraDartFlagOptions(verboseHelp: verboseHelp);
|
||||
@ -435,8 +433,6 @@ class RunCommand extends RunCommandBase {
|
||||
);
|
||||
}
|
||||
|
||||
final HotRunnerNativeAssetsBuilder? _nativeAssetsBuilder;
|
||||
|
||||
@override
|
||||
final String name = 'run';
|
||||
|
||||
@ -695,7 +691,6 @@ class RunCommand extends RunCommandBase {
|
||||
stayResident: stayResident,
|
||||
analytics: globals.analytics,
|
||||
nativeAssetsYamlFile: stringArg(FlutterOptions.kNativeAssetsYamlFile),
|
||||
nativeAssetsBuilder: _nativeAssetsBuilder,
|
||||
);
|
||||
} else if (webMode) {
|
||||
return webRunnerFactory!.createWebRunner(
|
||||
@ -765,7 +760,6 @@ class RunCommand extends RunCommandBase {
|
||||
packagesFilePath: globalResults![FlutterGlobalOptions.kPackagesOption] as String?,
|
||||
dillOutputPath: stringArg('output-dill'),
|
||||
userIdentifier: userIdentifier,
|
||||
nativeAssetsBuilder: _nativeAssetsBuilder,
|
||||
);
|
||||
} on Exception catch (error) {
|
||||
throwToolExit(error.toString());
|
||||
|
@ -419,7 +419,8 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
||||
webUseWasm: useWasm,
|
||||
);
|
||||
|
||||
String? testAssetDirectory;
|
||||
final Uri? nativeAssetsJson = await nativeAssetsBuilder?.build(buildInfo);
|
||||
String? testAssetPath;
|
||||
if (buildTestAssets) {
|
||||
await _buildTestAsset(
|
||||
flavor: buildInfo.flavor,
|
||||
@ -427,8 +428,19 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
||||
buildMode: debuggingOptions.buildInfo.mode,
|
||||
packageConfigPath: buildInfo.packageConfigPath,
|
||||
);
|
||||
testAssetDirectory = globals.fs.path.
|
||||
join(flutterProject.directory.path, 'build', 'unit_test_assets');
|
||||
}
|
||||
if (buildTestAssets || nativeAssetsJson != null) {
|
||||
testAssetPath = globals.fs.path
|
||||
.join(flutterProject.directory.path, 'build', 'unit_test_assets');
|
||||
}
|
||||
if (nativeAssetsJson != null) {
|
||||
final Directory testAssetDirectory = globals.fs.directory(testAssetPath);
|
||||
if (!testAssetDirectory.existsSync()) {
|
||||
await testAssetDirectory.create(recursive: true);
|
||||
}
|
||||
final File nativeAssetsManifest =
|
||||
testAssetDirectory.childFile('NativeAssetsManifest.json');
|
||||
await globals.fs.file(nativeAssetsJson).copy(nativeAssetsManifest.path);
|
||||
}
|
||||
|
||||
final String? concurrencyString = stringArg('concurrency');
|
||||
@ -585,7 +597,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
||||
machine: machine,
|
||||
updateGoldens: boolArg('update-goldens'),
|
||||
concurrency: jobs,
|
||||
testAssetDirectory: testAssetDirectory,
|
||||
testAssetDirectory: testAssetPath,
|
||||
flutterProject: flutterProject,
|
||||
randomSeed: stringArg('test-randomize-ordering-seed'),
|
||||
reporter: stringArg('reporter'),
|
||||
@ -612,7 +624,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
|
||||
machine: machine,
|
||||
updateGoldens: boolArg('update-goldens'),
|
||||
concurrency: jobs,
|
||||
testAssetDirectory: testAssetDirectory,
|
||||
testAssetDirectory: testAssetPath,
|
||||
flutterProject: flutterProject,
|
||||
web: isWeb,
|
||||
randomSeed: stringArg('test-randomize-ordering-seed'),
|
||||
|
@ -17,11 +17,10 @@ import '../../base/platform.dart';
|
||||
import '../../build_info.dart' as build_info;
|
||||
import '../../build_system/exceptions.dart';
|
||||
import '../../cache.dart';
|
||||
import '../../convert.dart';
|
||||
import '../../features.dart';
|
||||
import '../../globals.dart' as globals;
|
||||
import '../../macos/xcode.dart' as xcode;
|
||||
import '../../resident_runner.dart';
|
||||
import '../../run_hot.dart';
|
||||
import 'android/native_assets.dart';
|
||||
import 'ios/native_assets.dart';
|
||||
import 'linux/native_assets.dart';
|
||||
@ -129,67 +128,7 @@ Future<void> installCodeAssets({
|
||||
final String? codesignIdentity = environmentDefines[build_info.kCodesignIdentity];
|
||||
final Map<CodeAsset, KernelAsset> assetTargetLocations = assetTargetLocationsForOS(targetOS, dartBuildResult.codeAssets, flutterTester, buildUri);
|
||||
await _copyNativeCodeAssetsForOS(targetOS, buildUri, buildMode, fileSystem, assetTargetLocations, codesignIdentity, flutterTester);
|
||||
final KernelAssets kernelAssets = KernelAssets(assetTargetLocations.values.toList());
|
||||
await _writeNativeAssetsYaml(kernelAssets, nativeAssetsFileUri, fileSystem);
|
||||
}
|
||||
|
||||
Future<Uri?> runFlutterSpecificDartDryRunOnPlatforms({
|
||||
required Uri projectUri,
|
||||
required FileSystem fileSystem,
|
||||
required FlutterNativeAssetsBuildRunner buildRunner,
|
||||
required List<build_info.TargetPlatform> targetPlatforms,
|
||||
}) async {
|
||||
if (!await _nativeBuildRequired(buildRunner)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Map<CodeAsset, KernelAsset> assetTargetLocations =
|
||||
<CodeAsset, KernelAsset>{};
|
||||
for (final build_info.TargetPlatform targetPlatform in targetPlatforms) {
|
||||
// This dry-run functionality is only used in the `flutter run`
|
||||
// implementation (not in `flutter build` or `flutter test`).
|
||||
//
|
||||
// Though we can end up with `flutterTester == true` if someone uses the
|
||||
// `flutter-tester` device via `flutter run -d flutter-tester` (which mainly
|
||||
// happens in tests)
|
||||
final bool flutterTester =
|
||||
targetPlatform == build_info.TargetPlatform.tester;
|
||||
|
||||
final OS targetOS = getNativeOSFromTargetPlatfrorm(targetPlatform);
|
||||
if (targetOS != OS.macOS &&
|
||||
targetOS != OS.windows &&
|
||||
targetOS != OS.linux &&
|
||||
targetOS != OS.android &&
|
||||
targetOS != OS.iOS) {
|
||||
await ensureNoNativeAssetsOrOsIsSupported(
|
||||
projectUri,
|
||||
targetPlatform.toString(),
|
||||
fileSystem,
|
||||
buildRunner,
|
||||
);
|
||||
}
|
||||
|
||||
final Uri buildUri = nativeAssetsBuildUri(projectUri, targetOS);
|
||||
final DartBuildResult result = await _runDartDryRunBuild(
|
||||
buildRunner: buildRunner,
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetOS: targetOS);
|
||||
assetTargetLocations.addAll(assetTargetLocationsForOS(
|
||||
targetOS, result.codeAssets, flutterTester, buildUri));
|
||||
}
|
||||
|
||||
final Uri buildUri = targetPlatforms.length == 1
|
||||
? nativeAssetsBuildUri(
|
||||
projectUri, getNativeOSFromTargetPlatfrorm(targetPlatforms.single))
|
||||
: _buildUriMultiple(projectUri);
|
||||
final Uri nativeAssetsYamlUri = buildUri.resolve('native_assets.yaml');
|
||||
await _writeNativeAssetsYaml(
|
||||
KernelAssets(assetTargetLocations.values.toList()),
|
||||
nativeAssetsYamlUri,
|
||||
fileSystem,
|
||||
);
|
||||
return nativeAssetsYamlUri;
|
||||
await _writeNativeAssetsJson(assetTargetLocations.values.toList(), nativeAssetsFileUri, fileSystem,);
|
||||
}
|
||||
|
||||
/// Programmatic API to be used by Dart launchers to invoke native builds.
|
||||
@ -199,23 +138,13 @@ Future<Uri?> runFlutterSpecificDartDryRunOnPlatforms({
|
||||
abstract interface class FlutterNativeAssetsBuildRunner {
|
||||
/// Whether the project has a `.dart_tools/package_config.json`.
|
||||
///
|
||||
/// If there is no package config, [packagesWithNativeAssets], [build], and
|
||||
/// [buildDryRun] must not be invoked.
|
||||
/// If there is no package config, [packagesWithNativeAssets], [build] and
|
||||
/// [link] must not be invoked.
|
||||
Future<bool> hasPackageConfig();
|
||||
|
||||
/// All packages in the transitive dependencies that have a `build.dart`.
|
||||
Future<List<Package>> packagesWithNativeAssets();
|
||||
|
||||
/// Runs all [packagesWithNativeAssets] `build.dart` in dry run.
|
||||
Future<BuildDryRunResult?> buildDryRun({
|
||||
required List<String> supportedAssetTypes,
|
||||
required BuildConfigCreator configCreator,
|
||||
required BuildValidator buildValidator,
|
||||
required bool includeParentEnvironment,
|
||||
required OS targetOS,
|
||||
required Uri workingDirectory,
|
||||
});
|
||||
|
||||
/// Runs all [packagesWithNativeAssets] `build.dart`.
|
||||
Future<BuildResult?> build({
|
||||
required List<String> supportedAssetTypes,
|
||||
@ -307,30 +236,6 @@ class FlutterNativeAssetsBuildRunnerImpl implements FlutterNativeAssetsBuildRunn
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BuildDryRunResult?> buildDryRun({
|
||||
required List<String> supportedAssetTypes,
|
||||
required BuildConfigCreator configCreator,
|
||||
required BuildValidator buildValidator,
|
||||
required bool includeParentEnvironment,
|
||||
required OS targetOS,
|
||||
required Uri workingDirectory,
|
||||
}) {
|
||||
final PackageLayout packageLayout = PackageLayout.fromPackageConfig(
|
||||
packageConfig,
|
||||
Uri.file(packageConfigPath),
|
||||
);
|
||||
return _buildRunner.buildDryRun(
|
||||
supportedAssetTypes: supportedAssetTypes,
|
||||
configCreator: configCreator,
|
||||
buildValidator: buildValidator,
|
||||
includeParentEnvironment: includeParentEnvironment,
|
||||
targetOS: targetOS,
|
||||
workingDirectory: workingDirectory,
|
||||
packageLayout: packageLayout,
|
||||
linkingEnabled: false, // Dry run is only used in JIT mode.
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BuildResult?> build({
|
||||
required List<String> supportedAssetTypes,
|
||||
@ -418,14 +323,14 @@ class FlutterNativeAssetsBuildRunnerImpl implements FlutterNativeAssetsBuildRunn
|
||||
}();
|
||||
}
|
||||
|
||||
Future<Uri> _writeNativeAssetsYaml(
|
||||
KernelAssets assets,
|
||||
Uri nativeAssetsYamlUri,
|
||||
Future<Uri> _writeNativeAssetsJson(
|
||||
List<KernelAsset> assets,
|
||||
Uri nativeAssetsJsonUri,
|
||||
FileSystem fileSystem,
|
||||
) async {
|
||||
globals.logger.printTrace('Writing native assets yaml to $nativeAssetsYamlUri.');
|
||||
final String nativeAssetsDartContents = assets.toNativeAssetsFile();
|
||||
final File nativeAssetsFile = fileSystem.file(nativeAssetsYamlUri);
|
||||
globals.logger.printTrace('Writing native assets json to $nativeAssetsJsonUri.');
|
||||
final String nativeAssetsDartContents = _toNativeAssetsJsonFile(assets);
|
||||
final File nativeAssetsFile = fileSystem.file(nativeAssetsJsonUri);
|
||||
final Directory parentDirectory = nativeAssetsFile.parent;
|
||||
if (!await parentDirectory.exists()) {
|
||||
await parentDirectory.create(recursive: true);
|
||||
@ -435,6 +340,29 @@ Future<Uri> _writeNativeAssetsYaml(
|
||||
return nativeAssetsFile.uri;
|
||||
}
|
||||
|
||||
String _toNativeAssetsJsonFile(List<KernelAsset> kernelAssets) {
|
||||
final Map<Target, List<KernelAsset>> assetsPerTarget = <Target, List<KernelAsset>>{};
|
||||
for (final KernelAsset asset in kernelAssets) {
|
||||
assetsPerTarget.putIfAbsent(asset.target, () => <KernelAsset>[]).add(asset);
|
||||
}
|
||||
|
||||
const String formatVersionKey = 'format-version';
|
||||
const String nativeAssetsKey = 'native-assets';
|
||||
|
||||
// See assets/native_assets.cc in the engine for the expected format.
|
||||
final Map<String, Object> jsonContents = <String, Object>{
|
||||
formatVersionKey: const <int>[1, 0, 0],
|
||||
nativeAssetsKey: <String, Map<String, List<String>>>{
|
||||
for (final MapEntry<Target, List<KernelAsset>> entry in assetsPerTarget.entries)
|
||||
entry.key.toString(): <String, List<String>>{
|
||||
for (final KernelAsset e in entry.value) e.id: e.path.toJson(),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return jsonEncode(jsonContents);
|
||||
}
|
||||
|
||||
/// Select the native asset build mode for a given Flutter build mode.
|
||||
BuildMode _nativeAssetsBuildMode(build_info.BuildMode buildMode) {
|
||||
switch (buildMode) {
|
||||
@ -518,54 +446,6 @@ Uri nativeAssetsBuildUri(Uri projectUri, OS os) {
|
||||
return projectUri.resolve('$buildDir/native_assets/$os/');
|
||||
}
|
||||
|
||||
/// Gets the native asset id to dylib mapping to embed in the kernel file.
|
||||
///
|
||||
/// Run hot compiles a kernel file that is pushed to the device after hot
|
||||
/// restart. We need to embed the native assets mapping in order to access
|
||||
/// native assets after hot restart.
|
||||
class HotRunnerNativeAssetsBuilderImpl implements HotRunnerNativeAssetsBuilder {
|
||||
const HotRunnerNativeAssetsBuilderImpl();
|
||||
|
||||
@override
|
||||
Future<Uri?> dryRun({
|
||||
required Uri projectUri,
|
||||
required FileSystem fileSystem,
|
||||
required List<FlutterDevice> flutterDevices,
|
||||
required String packageConfigPath,
|
||||
required PackageConfig packageConfig,
|
||||
required Logger logger,
|
||||
}) async {
|
||||
final FlutterNativeAssetsBuildRunner buildRunner =
|
||||
FlutterNativeAssetsBuildRunnerImpl(
|
||||
projectUri,
|
||||
packageConfigPath,
|
||||
packageConfig,
|
||||
fileSystem,
|
||||
globals.logger,
|
||||
);
|
||||
|
||||
// If `flutter run -d all` is used then we may have multiple OSes.
|
||||
final List<build_info.TargetPlatform> targetPlatforms = flutterDevices
|
||||
.map((FlutterDevice d) => d.targetPlatform)
|
||||
.nonNulls
|
||||
.toList();
|
||||
|
||||
return runFlutterSpecificDartDryRunOnPlatforms(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
targetPlatforms: targetPlatforms,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// With `flutter run -d all` we need a place to store the native assets
|
||||
/// mapping for multiple OSes combined.
|
||||
Uri _buildUriMultiple(Uri projectUri) {
|
||||
final String buildDir = build_info.getBuildDirectory();
|
||||
return projectUri.resolve('$buildDir/native_assets/multiple/');
|
||||
}
|
||||
|
||||
Map<CodeAsset, KernelAsset> _assetTargetLocationsWindowsLinux(
|
||||
List<CodeAsset> assets,
|
||||
Uri? absolutePath,
|
||||
@ -830,44 +710,6 @@ Future<DartBuildResult> _runDartBuild({
|
||||
return DartBuildResult(codeAssets, dependencies.toList());
|
||||
}
|
||||
|
||||
Future<DartBuildResult> _runDartDryRunBuild({
|
||||
required FlutterNativeAssetsBuildRunner buildRunner,
|
||||
required Uri projectUri,
|
||||
required FileSystem fileSystem,
|
||||
required OS targetOS,
|
||||
}) async {
|
||||
globals.logger.printTrace('Dry running native assets for $targetOS.');
|
||||
final List<EncodedAsset> assets = <EncodedAsset>[];
|
||||
final Set<Uri> dependencies = <Uri>{};
|
||||
final BuildDryRunResult? buildResult = await buildRunner.buildDryRun(
|
||||
supportedAssetTypes: <String>[CodeAsset.type],
|
||||
configCreator: () => BuildConfigBuilder()
|
||||
..setupCodeConfig(
|
||||
targetArchitecture: null,
|
||||
linkModePreference: LinkModePreference.dynamic,
|
||||
),
|
||||
buildValidator: (BuildConfig config, BuildOutput output) async => <String>[
|
||||
...await validateCodeAssetBuildOutput(config, output),
|
||||
],
|
||||
workingDirectory: projectUri,
|
||||
targetOS: targetOS,
|
||||
includeParentEnvironment: true,
|
||||
);
|
||||
if (buildResult == null) {
|
||||
_throwNativeAssetsBuildDryRunFailed();
|
||||
}
|
||||
assets.addAll(buildResult.encodedAssets);
|
||||
|
||||
final List<CodeAsset> codeAssets = assets
|
||||
.where((EncodedAsset asset) => asset.type == CodeAsset.type)
|
||||
.map<CodeAsset>(CodeAsset.fromEncoded)
|
||||
.toList();
|
||||
globals.logger.printTrace('Dry running native assets for $targetOS done.');
|
||||
return DartBuildResult(
|
||||
_expandCodeAssetsToAllArchitectures(codeAssets),
|
||||
dependencies.toList());
|
||||
}
|
||||
|
||||
List<Architecture> _architecturesForOS(build_info.TargetPlatform targetPlatform,
|
||||
OS targetOS, Map<String, String> environmentDefines) {
|
||||
switch (targetOS) {
|
||||
@ -953,12 +795,6 @@ Future<void> _copyNativeCodeAssetsToBundleOnWindowsLinux(
|
||||
}
|
||||
}
|
||||
|
||||
Never _throwNativeAssetsBuildDryRunFailed() {
|
||||
throwToolExit(
|
||||
'Building (dry run) native assets failed. See the logs for more details.',
|
||||
);
|
||||
}
|
||||
|
||||
Never _throwNativeAssetsBuildFailed() {
|
||||
throwToolExit(
|
||||
'Building native assets failed. See the logs for more details.',
|
||||
@ -1049,15 +885,6 @@ String? _emptyToNull(String? input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
List<CodeAsset> _expandCodeAssetsToAllArchitectures(List<CodeAsset> codeAssets) {
|
||||
assert(codeAssets.every((CodeAsset asset) => asset.architecture == null));
|
||||
return <CodeAsset>[
|
||||
for (final CodeAsset codeAsset in codeAssets)
|
||||
for (final Architecture architecture in codeAsset.os.architectures)
|
||||
codeAsset.copyWith(architecture: architecture),
|
||||
];
|
||||
}
|
||||
|
||||
extension OSArchitectures on OS {
|
||||
Set<Architecture> get architectures => _osTargets[this]!;
|
||||
}
|
||||
|
@ -52,11 +52,11 @@ Future<Uri?> testCompilerBuildNativeAssets(BuildInfo buildInfo) async {
|
||||
}
|
||||
|
||||
// Only `flutter test` uses the
|
||||
// `build/native_assets/<os>/native_assets.yaml` file which uses absolute
|
||||
// `build/native_assets/<os>/native_assets.json` file which uses absolute
|
||||
// paths to the shared libraries.
|
||||
final OS targetOS = getNativeOSFromTargetPlatfrorm(TargetPlatform.tester);
|
||||
final Uri buildUri = nativeAssetsBuildUri(projectUri, targetOS);
|
||||
final Uri nativeAssetsFileUri = buildUri.resolve('native_assets.yaml');
|
||||
final Uri nativeAssetsFileUri = buildUri.resolve('native_assets.json');
|
||||
|
||||
final Map<String, String> environmentDefines = <String, String>{
|
||||
kBuildMode: buildInfo.mode.cliName,
|
||||
|
@ -90,13 +90,11 @@ class HotRunner extends ResidentRunner {
|
||||
StopwatchFactory stopwatchFactory = const StopwatchFactory(),
|
||||
ReloadSourcesHelper reloadSourcesHelper = defaultReloadSourcesHelper,
|
||||
ReassembleHelper reassembleHelper = _defaultReassembleHelper,
|
||||
HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
String? nativeAssetsYamlFile,
|
||||
required Analytics analytics,
|
||||
}) : _stopwatchFactory = stopwatchFactory,
|
||||
_reloadSourcesHelper = reloadSourcesHelper,
|
||||
_reassembleHelper = reassembleHelper,
|
||||
_nativeAssetsBuilder = nativeAssetsBuilder,
|
||||
_nativeAssetsYamlFile = nativeAssetsYamlFile,
|
||||
_analytics = analytics,
|
||||
super(
|
||||
@ -131,7 +129,6 @@ class HotRunner extends ResidentRunner {
|
||||
String? _sdkName;
|
||||
bool? _emulator;
|
||||
|
||||
final HotRunnerNativeAssetsBuilder? _nativeAssetsBuilder;
|
||||
final String? _nativeAssetsYamlFile;
|
||||
|
||||
String? flavor;
|
||||
@ -378,20 +375,9 @@ class HotRunner extends ResidentRunner {
|
||||
}) async {
|
||||
await _calculateTargetPlatform();
|
||||
|
||||
final Uri? nativeAssetsYaml;
|
||||
if (_nativeAssetsYamlFile != null) {
|
||||
nativeAssetsYaml = globals.fs.path.toUri(_nativeAssetsYamlFile);
|
||||
} else {
|
||||
final Uri projectUri = Uri.directory(projectRootPath);
|
||||
nativeAssetsYaml = await _nativeAssetsBuilder?.dryRun(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
flutterDevices: flutterDevices,
|
||||
logger: logger,
|
||||
packageConfigPath: debuggingOptions.buildInfo.packageConfigPath,
|
||||
packageConfig: debuggingOptions.buildInfo.packageConfig,
|
||||
);
|
||||
}
|
||||
final Uri? nativeAssetsYaml = _nativeAssetsYamlFile != null
|
||||
? globals.fs.path.toUri(_nativeAssetsYamlFile)
|
||||
: null;
|
||||
|
||||
final Stopwatch appStartedTimer = Stopwatch()..start();
|
||||
final File mainFile = globals.fs.file(mainPath);
|
||||
@ -1708,16 +1694,3 @@ class ReasonForCancelling {
|
||||
return '$message.\nTry performing a hot restart instead.';
|
||||
}
|
||||
}
|
||||
|
||||
/// An interface to enable overriding native assets build logic in other
|
||||
/// build systems.
|
||||
abstract class HotRunnerNativeAssetsBuilder {
|
||||
Future<Uri?> dryRun({
|
||||
required Uri projectUri,
|
||||
required FileSystem fileSystem,
|
||||
required List<FlutterDevice> flutterDevices,
|
||||
required String packageConfigPath,
|
||||
required PackageConfig packageConfig,
|
||||
required Logger logger,
|
||||
});
|
||||
}
|
||||
|
@ -529,7 +529,6 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
flutterProject,
|
||||
precompiledDillPath: precompiledDillPath,
|
||||
testTimeRecorder: testTimeRecorder,
|
||||
nativeAssetsBuilder: nativeAssetsBuilder,
|
||||
);
|
||||
final Uri uri = globals.fs.file(path).uri;
|
||||
// Trigger a compilation to initialize the resident compiler.
|
||||
@ -556,7 +555,6 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
debuggingOptions.buildInfo,
|
||||
flutterProject,
|
||||
testTimeRecorder: testTimeRecorder,
|
||||
nativeAssetsBuilder: nativeAssetsBuilder,
|
||||
);
|
||||
mainDart = await compiler!.compile(globals.fs.file(mainDart).uri);
|
||||
|
||||
|
@ -766,9 +766,6 @@ class SpawnPlugin extends PlatformPlugin {
|
||||
rootTestIsolateSpawnerSourceFile: rootTestIsolateSpawnerSourceFile,
|
||||
);
|
||||
|
||||
final Uri? nativeAssetsYaml = await nativeAssetsBuilder?.build(
|
||||
debuggingOptions.buildInfo,
|
||||
);
|
||||
|
||||
await _compileFile(
|
||||
debuggingOptions: debuggingOptions,
|
||||
@ -777,7 +774,6 @@ class SpawnPlugin extends PlatformPlugin {
|
||||
sourceFile: childTestIsolateSpawnerSourceFile,
|
||||
outputDillFile: childTestIsolateSpawnerDillFile,
|
||||
testTimeRecorder: testTimeRecorder,
|
||||
nativeAssetsYaml: nativeAssetsYaml,
|
||||
);
|
||||
|
||||
await _compileFile(
|
||||
|
@ -15,7 +15,6 @@ import '../bundle.dart';
|
||||
import '../compile.dart';
|
||||
import '../flutter_plugins.dart';
|
||||
import '../globals.dart' as globals;
|
||||
import '../native_assets.dart';
|
||||
import '../project.dart';
|
||||
import 'test_time_recorder.dart';
|
||||
|
||||
@ -49,7 +48,6 @@ class TestCompiler {
|
||||
this.flutterProject, {
|
||||
String? precompiledDillPath,
|
||||
this.testTimeRecorder,
|
||||
TestCompilerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
}) : testFilePath = precompiledDillPath ?? globals.fs.path.join(
|
||||
flutterProject!.directory.path,
|
||||
getBuildDirectory(),
|
||||
@ -59,8 +57,7 @@ class TestCompiler {
|
||||
dartDefines: buildInfo.dartDefines,
|
||||
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
|
||||
)),
|
||||
shouldCopyDillFile = precompiledDillPath == null,
|
||||
_nativeAssetsBuilder = nativeAssetsBuilder {
|
||||
shouldCopyDillFile = precompiledDillPath == null {
|
||||
// Compiler maintains and updates single incremental dill file.
|
||||
// Incremental compilation requests done for each test copy that file away
|
||||
// for independent execution.
|
||||
@ -81,8 +78,6 @@ class TestCompiler {
|
||||
final String testFilePath;
|
||||
final bool shouldCopyDillFile;
|
||||
final TestTimeRecorder? testTimeRecorder;
|
||||
final TestCompilerNativeAssetsBuilder? _nativeAssetsBuilder;
|
||||
|
||||
|
||||
ResidentCompiler? compiler;
|
||||
late File outputDill;
|
||||
@ -169,8 +164,6 @@ class TestCompiler {
|
||||
invalidatedRegistrantFiles.add(flutterProject!.dartPluginRegistrant.absolute.uri);
|
||||
}
|
||||
|
||||
final Uri? nativeAssetsYaml = await _nativeAssetsBuilder?.build(buildInfo);
|
||||
|
||||
final CompilerOutput? compilerOutput = await compiler!.recompile(
|
||||
request.mainUri,
|
||||
<Uri>[request.mainUri, ...invalidatedRegistrantFiles],
|
||||
@ -179,7 +172,6 @@ class TestCompiler {
|
||||
projectRootPath: flutterProject?.directory.absolute.path,
|
||||
checkDartPluginRegistry: true,
|
||||
fs: globals.fs,
|
||||
nativeAssetsYaml: nativeAssetsYaml,
|
||||
);
|
||||
final String? outputPath = compilerOutput?.outputFilename;
|
||||
|
||||
|
@ -1258,7 +1258,6 @@ class FakeHotRunnerFactory extends Fake implements HotRunnerFactory {
|
||||
FlutterProject? flutterProject,
|
||||
Analytics? analytics,
|
||||
String? nativeAssetsYamlFile,
|
||||
HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
}) {
|
||||
if (_artifactTester != null) {
|
||||
for (final FlutterDevice device in devices) {
|
||||
|
@ -27,7 +27,6 @@ import 'package:flutter_tools/src/macos/macos_ipad_device.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||
import 'package:flutter_tools/src/resident_runner.dart';
|
||||
import 'package:flutter_tools/src/run_hot.dart';
|
||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||
import 'package:flutter_tools/src/web/compile.dart';
|
||||
import 'package:test/fake.dart';
|
||||
@ -1611,7 +1610,6 @@ class CapturingAppDomain extends AppDomain {
|
||||
String? isolateFilter,
|
||||
bool machine = true,
|
||||
String? userIdentifier,
|
||||
required HotRunnerNativeAssetsBuilder? nativeAssetsBuilder,
|
||||
}) async {
|
||||
this.userIdentifier = userIdentifier;
|
||||
enableDevTools = options.enableDevTools;
|
||||
|
@ -52,6 +52,7 @@ void main() {
|
||||
// create pre-requisites.
|
||||
environment.buildDir.childFile('app.dill')
|
||||
.writeAsStringSync('abcd');
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
fileSystem
|
||||
.file(artifacts.getArtifactPath(Artifact.vmSnapshotData, mode: BuildMode.debug))
|
||||
.createSync(recursive: true);
|
||||
@ -96,6 +97,7 @@ void main() {
|
||||
// create pre-requisites.
|
||||
environment.buildDir.childFile('app.dill')
|
||||
.writeAsStringSync('abcd');
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
fileSystem
|
||||
.file(artifacts.getArtifactPath(Artifact.vmSnapshotData, mode: BuildMode.debug))
|
||||
.createSync(recursive: true);
|
||||
@ -185,6 +187,7 @@ void main() {
|
||||
));
|
||||
environment.buildDir.createSync(recursive: true);
|
||||
environment.buildDir.childFile('app.dill').createSync();
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
const AndroidAot androidAot = AndroidAot(TargetPlatform.android_arm64, BuildMode.release);
|
||||
|
||||
await androidAot.build(environment);
|
||||
@ -223,6 +226,7 @@ void main() {
|
||||
));
|
||||
environment.buildDir.createSync(recursive: true);
|
||||
environment.buildDir.childFile('app.dill').createSync();
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
const AndroidAot androidAot = AndroidAot(TargetPlatform.android_arm64, BuildMode.release);
|
||||
|
||||
await androidAot.build(environment);
|
||||
@ -264,6 +268,7 @@ void main() {
|
||||
));
|
||||
environment.buildDir.createSync(recursive: true);
|
||||
environment.buildDir.childFile('app.dill').createSync();
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
await const AndroidAot(TargetPlatform.android_arm64, BuildMode.release)
|
||||
.build(environment);
|
||||
@ -301,6 +306,7 @@ void main() {
|
||||
));
|
||||
environment.buildDir.createSync(recursive: true);
|
||||
environment.buildDir.childFile('app.dill').createSync();
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
await const AndroidAot(TargetPlatform.android_arm64, BuildMode.release)
|
||||
.build(environment);
|
||||
@ -518,6 +524,7 @@ void main() {
|
||||
// create pre-requisites.
|
||||
environment.buildDir.childFile('app.dill')
|
||||
.writeAsStringSync('abcd');
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
fileSystem
|
||||
.file(artifacts.getArtifactPath(Artifact.vmSnapshotData, mode: BuildMode.debug))
|
||||
.createSync(recursive: true);
|
||||
|
@ -43,6 +43,7 @@ void main() {
|
||||
},
|
||||
);
|
||||
fileSystem.file(environment.buildDir.childFile('app.dill')).createSync(recursive: true);
|
||||
fileSystem.file(environment.buildDir.childFile('native_assets.json')).createSync(recursive: true);
|
||||
fileSystem.file('packages/flutter_tools/lib/src/build_system/targets/assets.dart')
|
||||
.createSync(recursive: true);
|
||||
fileSystem.file('assets/foo/bar.png')
|
||||
|
@ -12,7 +12,6 @@ import 'package:flutter_tools/src/build_system/build_system.dart';
|
||||
import 'package:flutter_tools/src/build_system/exceptions.dart';
|
||||
import 'package:flutter_tools/src/build_system/targets/common.dart';
|
||||
import 'package:flutter_tools/src/build_system/targets/ios.dart';
|
||||
import 'package:flutter_tools/src/build_system/targets/native_assets.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
|
||||
import '../../../src/common.dart';
|
||||
@ -65,34 +64,14 @@ void main() {
|
||||
iosEnvironment.buildDir.createSync(recursive: true);
|
||||
});
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram throws error if missing build mode', () async {
|
||||
testWithoutContext('KernelSnapshot throws error if missing build mode', () async {
|
||||
androidEnvironment.defines.remove(kBuildMode);
|
||||
expect(
|
||||
const KernelSnapshotProgram().build(androidEnvironment),
|
||||
const KernelSnapshot().build(androidEnvironment),
|
||||
throwsA(isA<MissingDefineException>()));
|
||||
});
|
||||
|
||||
const String emptyNativeAssets = '''
|
||||
format-version:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
native-assets: {}
|
||||
''';
|
||||
|
||||
const String nonEmptyNativeAssets = '''
|
||||
format-version:
|
||||
- 1
|
||||
- 0
|
||||
- 0
|
||||
native-assets:
|
||||
macos_arm64:
|
||||
package:my_package/my_package_bindings_generated.dart:
|
||||
- absolute
|
||||
- my_package.framework/my_package
|
||||
''';
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram handles null result from kernel compilation', () async {
|
||||
testWithoutContext('KernelSnapshot handles null result from kernel compilation', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
@ -119,7 +98,7 @@ native-assets:
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--depfile',
|
||||
'$build/kernel_snapshot_program.d',
|
||||
'--verbosity=error',
|
||||
@ -127,11 +106,11 @@ native-assets:
|
||||
], exitCode: 1),
|
||||
]);
|
||||
|
||||
await expectLater(() => const KernelSnapshotProgram().build(androidEnvironment), throwsException);
|
||||
await expectLater(() => const KernelSnapshot().build(androidEnvironment), throwsException);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram does use track widget creation on profile builds', () async {
|
||||
testWithoutContext('KernelSnapshot does use track widget creation on profile builds', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
@ -158,20 +137,20 @@ native-assets:
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--depfile',
|
||||
'$build/kernel_snapshot_program.d',
|
||||
'--verbosity=error',
|
||||
'file:///lib/main.dart',
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/program.dill 0\n'),
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
|
||||
]);
|
||||
|
||||
await const KernelSnapshotProgram().build(androidEnvironment);
|
||||
await const KernelSnapshot().build(androidEnvironment);
|
||||
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram correctly handles an empty string in ExtraFrontEndOptions', () async {
|
||||
testWithoutContext('KernelSnapshot correctly handles an empty string in ExtraFrontEndOptions', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
@ -198,21 +177,21 @@ native-assets:
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--depfile',
|
||||
'$build/kernel_snapshot_program.d',
|
||||
'--verbosity=error',
|
||||
'file:///lib/main.dart',
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/program.dill 0\n'),
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
|
||||
]);
|
||||
|
||||
await const KernelSnapshotProgram()
|
||||
await const KernelSnapshot()
|
||||
.build(androidEnvironment..defines[kExtraFrontEndOptions] = '');
|
||||
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram correctly forwards FrontendServerStarterPath', () async {
|
||||
testWithoutContext('KernelSnapshot correctly forwards FrontendServerStarterPath', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
@ -239,21 +218,21 @@ native-assets:
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--depfile',
|
||||
'$build/kernel_snapshot_program.d',
|
||||
'--verbosity=error',
|
||||
'file:///lib/main.dart',
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/program.dill 0\n'),
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
|
||||
]);
|
||||
|
||||
await const KernelSnapshotProgram()
|
||||
await const KernelSnapshot()
|
||||
.build(androidEnvironment..defines[kFrontendServerStarterPath] = 'path/to/frontend_server_starter.dart');
|
||||
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram correctly forwards ExtraFrontEndOptions', () async {
|
||||
testWithoutContext('KernelSnapshot correctly forwards ExtraFrontEndOptions', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
@ -280,23 +259,23 @@ native-assets:
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--depfile',
|
||||
'$build/kernel_snapshot_program.d',
|
||||
'--verbosity=error',
|
||||
'foo',
|
||||
'bar',
|
||||
'file:///lib/main.dart',
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/program.dill 0\n'),
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
|
||||
]);
|
||||
|
||||
await const KernelSnapshotProgram()
|
||||
await const KernelSnapshot()
|
||||
.build(androidEnvironment..defines[kExtraFrontEndOptions] = 'foo,bar');
|
||||
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram can disable track-widget-creation on debug builds', () async {
|
||||
testWithoutContext('KernelSnapshot can disable track-widget-creation on debug builds', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
@ -320,25 +299,25 @@ native-assets:
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--depfile',
|
||||
'$build/kernel_snapshot_program.d',
|
||||
'--incremental',
|
||||
'--initialize-from-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--verbosity=error',
|
||||
'file:///lib/main.dart',
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/program.dill 0\n'),
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
|
||||
]);
|
||||
|
||||
await const KernelSnapshotProgram().build(androidEnvironment
|
||||
await const KernelSnapshot().build(androidEnvironment
|
||||
..defines[kBuildMode] = BuildMode.debug.cliName
|
||||
..defines[kTrackWidgetCreation] = 'false');
|
||||
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram forces platform linking on debug for darwin target platforms', () async {
|
||||
testWithoutContext('KernelSnapshot forces platform linking on debug for darwin target platforms', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
@ -360,18 +339,18 @@ native-assets:
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--depfile',
|
||||
'$build/kernel_snapshot_program.d',
|
||||
'--incremental',
|
||||
'--initialize-from-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--verbosity=error',
|
||||
'file:///lib/main.dart',
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/program.dill 0\n'),
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
|
||||
]);
|
||||
|
||||
await const KernelSnapshotProgram().build(androidEnvironment
|
||||
await const KernelSnapshot().build(androidEnvironment
|
||||
..defines[kTargetPlatform] = getNameForTargetPlatform(TargetPlatform.darwin)
|
||||
..defines[kBuildMode] = BuildMode.debug.cliName
|
||||
..defines[kTrackWidgetCreation] = 'false'
|
||||
@ -380,7 +359,7 @@ native-assets:
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('KernelSnapshotProgram does use track widget creation on debug builds', () async {
|
||||
testWithoutContext('KernelSnapshot does use track widget creation on debug builds', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
@ -415,92 +394,22 @@ native-assets:
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--depfile',
|
||||
'$build/kernel_snapshot_program.d',
|
||||
'--incremental',
|
||||
'--initialize-from-dill',
|
||||
'$build/program.dill',
|
||||
'$build/app.dill',
|
||||
'--verbosity=error',
|
||||
'file:///lib/main.dart',
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey /build/653e11a8e6908714056a57cd6b4f602a/program.dill 0\n'),
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey /build/653e11a8e6908714056a57cd6b4f602a/app.dill 0\n'),
|
||||
]);
|
||||
|
||||
await const KernelSnapshotProgram().build(testEnvironment);
|
||||
await const KernelSnapshot().build(testEnvironment);
|
||||
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
for (final BuildMode buildMode in <BuildMode>[BuildMode.debug, BuildMode.release]) {
|
||||
for (final bool empty in <bool>[true, false]) {
|
||||
final String testName = empty ? 'empty' : 'non empty';
|
||||
testWithoutContext('KernelSnapshotNativeAssets ${buildMode.name} $testName', () async {
|
||||
fileSystem.file('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion": 2, "packages":[]}');
|
||||
androidEnvironment.buildDir.childFile(InstallCodeAssets.nativeAssetsFilename)
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(empty ? emptyNativeAssets : nonEmptyNativeAssets);
|
||||
final String build = androidEnvironment.buildDir.path;
|
||||
final String flutterPatchedSdkPath = artifacts.getArtifactPath(
|
||||
Artifact.flutterPatchedSdkPath,
|
||||
platform: TargetPlatform.darwin,
|
||||
mode: buildMode,
|
||||
);
|
||||
processManager.addCommands(<FakeCommand>[
|
||||
if (!empty)
|
||||
FakeCommand(command: <String>[
|
||||
artifacts.getArtifactPath(Artifact.engineDartAotRuntime),
|
||||
artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
|
||||
'--sdk-root',
|
||||
'$flutterPatchedSdkPath/',
|
||||
'--target=flutter',
|
||||
'--no-print-incremental-dependencies',
|
||||
...buildModeOptions(buildMode, <String>[]),
|
||||
'--no-link-platform',
|
||||
if (buildMode == BuildMode.release) ...<String>['--aot', '--tfa'],
|
||||
'--packages',
|
||||
'/.dart_tool/package_config.json',
|
||||
'--output-dill',
|
||||
'$build/native_assets.dill',
|
||||
'--native-assets',
|
||||
'$build/${InstallCodeAssets.nativeAssetsFilename}',
|
||||
'--verbosity=error',
|
||||
'--native-assets-only',
|
||||
], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
|
||||
]);
|
||||
|
||||
await const KernelSnapshotNativeAssets().build(androidEnvironment
|
||||
..defines[kTargetPlatform] = getNameForTargetPlatform(TargetPlatform.darwin)
|
||||
..defines[kBuildMode] = buildMode.cliName
|
||||
);
|
||||
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (final bool empty in <bool>[true, false]) {
|
||||
final String testName = empty ? 'empty' : 'non empty';
|
||||
testWithoutContext('KernelSnapshot native assets $testName', () async {
|
||||
const List<int> programDillBytes = <int>[1, 2, 3, 4];
|
||||
androidEnvironment.buildDir.childFile('program.dill')
|
||||
..createSync(recursive: true)
|
||||
..writeAsBytesSync(programDillBytes);
|
||||
final List<int> nativeAssetsDillBytes = empty ? <int>[] : <int>[5, 6, 7, 8];
|
||||
androidEnvironment.buildDir.childFile('native_assets.dill')
|
||||
..createSync(recursive: true)
|
||||
..writeAsBytesSync(nativeAssetsDillBytes);
|
||||
|
||||
await const KernelSnapshot().build(androidEnvironment);
|
||||
|
||||
expect(
|
||||
androidEnvironment.buildDir.childFile('app.dill').readAsBytesSync(),
|
||||
equals(<int>[...programDillBytes, ...nativeAssetsDillBytes]),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
testUsingContext('AotElfProfile Produces correct output directory', () async {
|
||||
final String build = androidEnvironment.buildDir.path;
|
||||
processManager.addCommands(<FakeCommand>[
|
||||
@ -520,6 +429,7 @@ native-assets:
|
||||
]),
|
||||
]);
|
||||
androidEnvironment.buildDir.childFile('app.dill').createSync(recursive: true);
|
||||
androidEnvironment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
await const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment);
|
||||
|
||||
@ -548,6 +458,7 @@ native-assets:
|
||||
]),
|
||||
]);
|
||||
androidEnvironment.buildDir.childFile('app.dill').createSync(recursive: true);
|
||||
androidEnvironment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
await const AotElfRelease(TargetPlatform.android_arm).build(androidEnvironment);
|
||||
|
||||
|
@ -205,6 +205,7 @@ void main() {
|
||||
.createSync(recursive: true);
|
||||
// App kernel
|
||||
environment.buildDir.childFile('app.dill').createSync(recursive: true);
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
// Stub framework
|
||||
environment.buildDir
|
||||
.childDirectory('App.framework')
|
||||
@ -285,6 +286,7 @@ void main() {
|
||||
fileSystem.file('shader.glsl').writeAsStringSync('test');
|
||||
// App kernel
|
||||
environment.buildDir.childFile('app.dill').createSync(recursive: true);
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
// Stub framework
|
||||
environment.buildDir
|
||||
.childDirectory('App.framework')
|
||||
@ -360,6 +362,7 @@ void main() {
|
||||
.childDirectory('App.framework')
|
||||
.childFile('App')
|
||||
.createSync(recursive: true);
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
// Input dSYM
|
||||
environment.buildDir
|
||||
@ -425,6 +428,7 @@ void main() {
|
||||
.childDirectory('App.framework')
|
||||
.childFile('App')
|
||||
.createSync(recursive: true);
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
final Directory frameworkDirectory = environment.outputDir.childDirectory('App.framework');
|
||||
final File frameworkDirectoryBinary = frameworkDirectory.childFile('App');
|
||||
|
@ -116,6 +116,7 @@ void main() {
|
||||
|
||||
// Create input files.
|
||||
testEnvironment.buildDir.childFile('app.dill').createSync();
|
||||
testEnvironment.buildDir.childFile('native_assets.json').createSync();
|
||||
fileSystem.file('bundle.sksl').writeAsStringSync(json.encode(
|
||||
<String, Object>{
|
||||
'engineRevision': '2',
|
||||
@ -169,6 +170,7 @@ void main() {
|
||||
|
||||
// Create input files.
|
||||
testEnvironment.buildDir.childFile('app.so').createSync();
|
||||
testEnvironment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
await const LinuxAotBundle(AotElfProfile(TargetPlatform.linux_x64)).build(testEnvironment);
|
||||
await const ProfileBundleLinuxAssets(TargetPlatform.linux_x64).build(testEnvironment);
|
||||
@ -208,6 +210,7 @@ void main() {
|
||||
|
||||
// Create input files.
|
||||
testEnvironment.buildDir.childFile('app.so').createSync();
|
||||
testEnvironment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
await const LinuxAotBundle(AotElfRelease(TargetPlatform.linux_x64)).build(testEnvironment);
|
||||
await const ReleaseBundleLinuxAssets(TargetPlatform.linux_x64).build(testEnvironment);
|
||||
|
@ -418,6 +418,7 @@ void main() {
|
||||
fileSystem.file(inputKernel)
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('testing');
|
||||
environment.buildDir.childFile('native_assets.json').createSync();
|
||||
|
||||
await const DebugMacOSBundleFlutterAssets().build(environment);
|
||||
|
||||
@ -454,6 +455,9 @@ void main() {
|
||||
.createSync(recursive: true);
|
||||
fileSystem.file('${environment.buildDir.path}/App.framework/App')
|
||||
.createSync(recursive: true);
|
||||
fileSystem
|
||||
.file('${environment.buildDir.path}/native_assets.json')
|
||||
.createSync();
|
||||
|
||||
await const ProfileMacOSBundleFlutterAssets().build(environment..defines[kBuildMode] = 'profile');
|
||||
|
||||
@ -483,6 +487,9 @@ void main() {
|
||||
.createSync(recursive: true);
|
||||
fileSystem.file('${environment.buildDir.path}/App.framework.dSYM/Contents/Resources/DWARF/App')
|
||||
.createSync(recursive: true);
|
||||
fileSystem
|
||||
.file('${environment.buildDir.path}/native_assets.json')
|
||||
.createSync();
|
||||
|
||||
await const ReleaseMacOSBundleFlutterAssets()
|
||||
.build(environment..defines[kBuildMode] = 'release');
|
||||
@ -504,6 +511,9 @@ void main() {
|
||||
final File inputFramework = fileSystem.file(fileSystem.path.join(environment.buildDir.path, 'App.framework', 'App'))
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('ABC');
|
||||
fileSystem
|
||||
.file(environment.buildDir.childFile('native_assets.json'))
|
||||
.createSync();
|
||||
|
||||
await const ProfileMacOSBundleFlutterAssets().build(environment..defines[kBuildMode] = 'profile');
|
||||
final File outputFramework = fileSystem.file(fileSystem.path.join(environment.outputDir.path, 'App.framework', 'App'));
|
||||
@ -529,6 +539,9 @@ void main() {
|
||||
.createSync(recursive: true);
|
||||
fileSystem.file(fileSystem.path.join(environment.buildDir.path, 'App.framework', 'App'))
|
||||
.createSync(recursive: true);
|
||||
fileSystem
|
||||
.file(environment.buildDir.childFile('native_assets.json'))
|
||||
.createSync();
|
||||
|
||||
await const ReleaseMacOSBundleFlutterAssets().build(environment);
|
||||
expect(usage.events, contains(const TestUsageEvent('assemble', 'macos-archive', label: 'success')));
|
||||
|
@ -136,6 +136,7 @@ void main() {
|
||||
);
|
||||
|
||||
environment.buildDir.childFile('app.dill').createSync(recursive: true);
|
||||
environment.buildDir.childFile('native_assets.json').createSync(recursive: true);
|
||||
// sksl bundle
|
||||
fileSystem.file('bundle.sksl').writeAsStringSync(json.encode(
|
||||
<String, Object>{
|
||||
@ -173,6 +174,7 @@ void main() {
|
||||
);
|
||||
|
||||
environment.buildDir.childFile('app.so').createSync(recursive: true);
|
||||
environment.buildDir.childFile('native_assets.json').createSync(recursive: true);
|
||||
|
||||
await const WindowsAotBundle(AotElfProfile(TargetPlatform.windows_x64)).build(environment);
|
||||
await const ProfileBundleWindowsAssets(TargetPlatform.windows_x64).build(environment);
|
||||
@ -200,6 +202,7 @@ void main() {
|
||||
);
|
||||
|
||||
environment.buildDir.childFile('app.so').createSync(recursive: true);
|
||||
environment.buildDir.childFile('native_assets.json').createSync(recursive: true);
|
||||
|
||||
await const WindowsAotBundle(AotElfRelease(TargetPlatform.windows_x64)).build(environment);
|
||||
await const ReleaseBundleWindowsAssets(TargetPlatform.windows_x64).build(environment);
|
||||
|
@ -116,7 +116,7 @@ void main() {
|
||||
]),
|
||||
);
|
||||
|
||||
expect(environment.buildDir.childFile('native_assets.yaml'), exists);
|
||||
expect(environment.buildDir.childFile('native_assets.json'), exists);
|
||||
expect(buildRunner.buildInvocations, 1);
|
||||
expect(
|
||||
buildRunner.linkInvocations,
|
||||
|
@ -104,7 +104,7 @@ void main() {
|
||||
for (final bool isNativeAssetsEnabled in <bool>[true, false]) {
|
||||
final String postFix = isNativeAssetsEnabled ? 'enabled' : 'disabled';
|
||||
testUsingContext(
|
||||
'Successful native_assets.yaml and native_assets.d creation with feature $postFix',
|
||||
'Successful native_assets.json and native_assets.d creation with feature $postFix',
|
||||
overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => processManager,
|
||||
|
@ -2,12 +2,7 @@
|
||||
// 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 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart' hide BuildMode;
|
||||
import 'package:flutter_tools/src/isolated/native_assets/native_assets.dart';
|
||||
import 'package:flutter_tools/src/resident_runner.dart';
|
||||
import 'package:flutter_tools/src/run_hot.dart';
|
||||
import 'package:native_assets_builder/native_assets_builder.dart';
|
||||
import 'package:native_assets_cli/code_assets_builder.dart';
|
||||
import 'package:package_config/package_config_types.dart';
|
||||
@ -23,7 +18,6 @@ class FakeFlutterNativeAssetsBuildRunner
|
||||
this.packagesWithNativeAssetsResult = const <Package>[],
|
||||
this.onBuild,
|
||||
this.onLink,
|
||||
this.buildDryRunResult = const FakeFlutterNativeAssetsBuilderResult(),
|
||||
this.buildResult = const FakeFlutterNativeAssetsBuilderResult(),
|
||||
this.linkResult = const FakeFlutterNativeAssetsBuilderResult(),
|
||||
CCompilerConfig? cCompilerConfigResult,
|
||||
@ -36,14 +30,12 @@ class FakeFlutterNativeAssetsBuildRunner
|
||||
final LinkResult? Function(LinkConfig)? onLink;
|
||||
final BuildResult? buildResult;
|
||||
final LinkResult? linkResult;
|
||||
final BuildDryRunResult? buildDryRunResult;
|
||||
final bool hasPackageConfigResult;
|
||||
final List<Package> packagesWithNativeAssetsResult;
|
||||
final CCompilerConfig cCompilerConfigResult;
|
||||
final CCompilerConfig ndkCCompilerConfigResult;
|
||||
|
||||
int buildInvocations = 0;
|
||||
int buildDryRunInvocations = 0;
|
||||
int linkInvocations = 0;
|
||||
int hasPackageConfigInvocations = 0;
|
||||
int packagesWithNativeAssetsInvocations = 0;
|
||||
@ -128,19 +120,6 @@ class FakeFlutterNativeAssetsBuildRunner
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BuildDryRunResult?> buildDryRun({
|
||||
required List<String> supportedAssetTypes,
|
||||
required ConfigCreator configCreator,
|
||||
required BuildValidator buildValidator,
|
||||
required bool includeParentEnvironment,
|
||||
required OS targetOS,
|
||||
required Uri workingDirectory,
|
||||
}) async {
|
||||
buildDryRunInvocations++;
|
||||
return buildDryRunResult;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> hasPackageConfig() async {
|
||||
hasPackageConfigInvocations++;
|
||||
@ -161,7 +140,7 @@ class FakeFlutterNativeAssetsBuildRunner
|
||||
}
|
||||
|
||||
final class FakeFlutterNativeAssetsBuilderResult
|
||||
implements BuildResult, BuildDryRunResult, LinkResult {
|
||||
implements BuildResult, LinkResult {
|
||||
const FakeFlutterNativeAssetsBuilderResult({
|
||||
this.encodedAssets = const <EncodedAsset>[],
|
||||
this.encodedAssetsForLinking = const <String, List<EncodedAsset>>{},
|
||||
@ -197,30 +176,3 @@ final class FakeFlutterNativeAssetsBuilderResult
|
||||
@override
|
||||
final List<Uri> dependencies;
|
||||
}
|
||||
|
||||
class FakeHotRunnerNativeAssetsBuilder implements HotRunnerNativeAssetsBuilder {
|
||||
FakeHotRunnerNativeAssetsBuilder(this.buildRunner);
|
||||
|
||||
final FlutterNativeAssetsBuildRunner buildRunner;
|
||||
|
||||
@override
|
||||
Future<Uri?> dryRun({
|
||||
required Uri projectUri,
|
||||
required FileSystem fileSystem,
|
||||
required List<FlutterDevice> flutterDevices,
|
||||
required String packageConfigPath,
|
||||
required PackageConfig packageConfig,
|
||||
required Logger logger,
|
||||
}) {
|
||||
final List<TargetPlatform> targetPlatforms = flutterDevices
|
||||
.map((FlutterDevice d) => d.targetPlatform)
|
||||
.nonNulls
|
||||
.toList();
|
||||
return runFlutterSpecificDartDryRunOnPlatforms(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
targetPlatforms: targetPlatforms,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,182 +0,0 @@
|
||||
// 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/memory.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/devfs.dart';
|
||||
import 'package:flutter_tools/src/device.dart';
|
||||
import 'package:flutter_tools/src/features.dart';
|
||||
import 'package:flutter_tools/src/resident_devtools_handler.dart';
|
||||
import 'package:flutter_tools/src/resident_runner.dart';
|
||||
import 'package:flutter_tools/src/run_hot.dart';
|
||||
import 'package:native_assets_cli/code_assets_builder.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:unified_analytics/unified_analytics.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../hot_shared.dart';
|
||||
import 'fake_native_assets_build_runner.dart';
|
||||
|
||||
void main() {
|
||||
group('native assets', () {
|
||||
late TestHotRunnerConfig testingConfig;
|
||||
late MemoryFileSystem fileSystem;
|
||||
late FakeAnalytics fakeAnalytics;
|
||||
|
||||
setUp(() {
|
||||
fileSystem = MemoryFileSystem.test();
|
||||
testingConfig = TestHotRunnerConfig(
|
||||
successfulHotRestartSetup: true,
|
||||
);
|
||||
fakeAnalytics = getInitializedFakeAnalyticsInstance(
|
||||
fs: fileSystem,
|
||||
fakeFlutterVersion: FakeFlutterVersion(),
|
||||
);
|
||||
});
|
||||
testUsingContext('native assets restart', () async {
|
||||
final FakeDevice device = FakeDevice();
|
||||
final FakeFlutterDevice fakeFlutterDevice = FakeFlutterDevice(device);
|
||||
final List<FlutterDevice> devices = <FlutterDevice>[
|
||||
fakeFlutterDevice,
|
||||
];
|
||||
|
||||
fakeFlutterDevice.updateDevFSReportCallback = () async => UpdateFSReport(
|
||||
success: true,
|
||||
invalidatedSourcesCount: 6,
|
||||
syncedBytes: 8,
|
||||
scannedSourcesCount: 16,
|
||||
compileDuration: const Duration(seconds: 16),
|
||||
transferDuration: const Duration(seconds: 32),
|
||||
);
|
||||
|
||||
(fakeFlutterDevice.devFS! as FakeDevFs).baseUri = Uri.parse('file:///base_uri');
|
||||
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', fileSystem.currentDirectory.uri),
|
||||
],
|
||||
buildDryRunResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(
|
||||
codeAssets: <CodeAsset>[
|
||||
CodeAsset(
|
||||
package: 'bar',
|
||||
name: 'bar.dart',
|
||||
linkMode: DynamicLoadingBundled(),
|
||||
os: OS.macOS,
|
||||
architecture: Architecture.arm64,
|
||||
file: Uri.file('bar.dylib'),
|
||||
),
|
||||
CodeAsset(
|
||||
package: 'bar',
|
||||
name: 'bar.dart',
|
||||
linkMode: DynamicLoadingBundled(),
|
||||
os: OS.macOS,
|
||||
architecture: Architecture.x64,
|
||||
file: Uri.file('bar.dylib'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
final HotRunner hotRunner = HotRunner(
|
||||
devices,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
nativeAssetsBuilder: FakeHotRunnerNativeAssetsBuilder(buildRunner),
|
||||
analytics: fakeAnalytics,
|
||||
);
|
||||
final OperationResult result = await hotRunner.restart(fullRestart: true);
|
||||
expect(result.isOk, true);
|
||||
// Hot restart does not require rerunning anything for native assets.
|
||||
// The previous native assets mapping should be used.
|
||||
expect(buildRunner.buildInvocations, 0);
|
||||
expect(buildRunner.buildDryRunInvocations, 0);
|
||||
expect(buildRunner.linkInvocations, 0);
|
||||
expect(buildRunner.hasPackageConfigInvocations, 0);
|
||||
expect(buildRunner.packagesWithNativeAssetsInvocations, 0);
|
||||
}, overrides: <Type, Generator>{
|
||||
HotRunnerConfig: () => testingConfig,
|
||||
Artifacts: () => Artifacts.test(),
|
||||
FileSystem: () => fileSystem,
|
||||
Platform: () => FakePlatform(),
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true, isMacOSEnabled: true),
|
||||
});
|
||||
|
||||
testUsingContext('native assets run unsupported', () async {
|
||||
final FakeDevice device = FakeDevice(targetPlatform: TargetPlatform.fuchsia_arm64);
|
||||
final FakeFlutterDevice fakeFlutterDevice = FakeFlutterDevice(device);
|
||||
final List<FlutterDevice> devices = <FlutterDevice>[
|
||||
fakeFlutterDevice,
|
||||
];
|
||||
|
||||
fakeFlutterDevice.updateDevFSReportCallback = () async => UpdateFSReport(
|
||||
success: true,
|
||||
invalidatedSourcesCount: 6,
|
||||
syncedBytes: 8,
|
||||
scannedSourcesCount: 16,
|
||||
compileDuration: const Duration(seconds: 16),
|
||||
transferDuration: const Duration(seconds: 32),
|
||||
);
|
||||
|
||||
(fakeFlutterDevice.devFS! as FakeDevFs).baseUri = Uri.parse('file:///base_uri');
|
||||
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', fileSystem.currentDirectory.uri),
|
||||
],
|
||||
buildDryRunResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(
|
||||
codeAssets: <CodeAsset>[
|
||||
CodeAsset(
|
||||
package: 'bar',
|
||||
name: 'bar.dart',
|
||||
linkMode: DynamicLoadingBundled(),
|
||||
os: OS.macOS,
|
||||
architecture: Architecture.arm64,
|
||||
file: Uri.file('bar.dylib'),
|
||||
),
|
||||
CodeAsset(
|
||||
package: 'bar',
|
||||
name: 'bar.dart',
|
||||
linkMode: DynamicLoadingBundled(),
|
||||
os: OS.macOS,
|
||||
architecture: Architecture.x64,
|
||||
file: Uri.file('bar.dylib'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
final HotRunner hotRunner = HotRunner(
|
||||
devices,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
nativeAssetsBuilder: FakeHotRunnerNativeAssetsBuilder(buildRunner),
|
||||
analytics: fakeAnalytics,
|
||||
);
|
||||
expect(
|
||||
() => hotRunner.run(),
|
||||
throwsToolExit( message:
|
||||
'Package(s) bar require the native assets feature. '
|
||||
'This feature has not yet been implemented for `TargetPlatform.fuchsia_arm64`. '
|
||||
'For more info see https://github.com/flutter/flutter/issues/129757.',
|
||||
)
|
||||
);
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
HotRunnerConfig: () => testingConfig,
|
||||
Artifacts: () => Artifacts.test(),
|
||||
FileSystem: () => fileSystem,
|
||||
Platform: () => FakePlatform(),
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true, isMacOSEnabled: true),
|
||||
});
|
||||
});
|
||||
}
|
@ -47,26 +47,6 @@ void main() {
|
||||
projectUri = environment.projectDir.uri;
|
||||
});
|
||||
|
||||
testUsingContext('dry run with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
expect(
|
||||
await runFlutterSpecificDartDryRunOnPlatforms(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetPlatforms: <TargetPlatform>[TargetPlatform.windows_x64],
|
||||
buildRunner: FakeFlutterNativeAssetsBuildRunner(
|
||||
hasPackageConfigResult: false,
|
||||
),
|
||||
),
|
||||
null,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
contains('No package config found. Skipping native assets compilation.'),
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('build with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
@ -87,97 +67,6 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('dry run for multiple OSes with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
await runFlutterSpecificDartDryRunOnPlatforms(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetPlatforms: <TargetPlatform>[
|
||||
TargetPlatform.windows_x64,
|
||||
TargetPlatform.darwin,
|
||||
TargetPlatform.ios,
|
||||
],
|
||||
buildRunner: FakeFlutterNativeAssetsBuildRunner(
|
||||
hasPackageConfigResult: false,
|
||||
),
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
contains('No package config found. Skipping native assets compilation.'),
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('dry run with assets but not enabled', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
final File packageConfig = environment.projectDir.childFile('.dart_tool/package_config.json');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => runFlutterSpecificDartDryRunOnPlatforms(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetPlatforms: <TargetPlatform>[TargetPlatform.windows_x64],
|
||||
buildRunner: FakeFlutterNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
),
|
||||
),
|
||||
throwsToolExit(
|
||||
message: 'Package(s) bar require the native assets feature to be enabled. '
|
||||
'Enable using `flutter config --enable-native-assets`.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('dry run with assets', overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
final File packageConfig = environment.projectDir.childFile('.dart_tool/package_config.json');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(
|
||||
codeAssets: <CodeAsset>[
|
||||
CodeAsset(
|
||||
package: 'bar',
|
||||
name: 'bar.dart',
|
||||
linkMode: DynamicLoadingBundled(),
|
||||
os: OS.windows,
|
||||
file: Uri.file('bar.dll'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
final Uri? nativeAssetsYaml = await runFlutterSpecificDartDryRunOnPlatforms(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetPlatforms: <TargetPlatform>[TargetPlatform.windows_x64],
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Dry running native assets for windows.',
|
||||
'Dry running native assets for windows done.',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/windows/${InstallCodeAssets.nativeAssetsFilename}'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
contains('package:bar/bar.dart'),
|
||||
);
|
||||
expect(buildRunner.buildDryRunInvocations, 1);
|
||||
});
|
||||
|
||||
testUsingContext('Native assets: non-bundled libraries require no copying', overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
@ -185,7 +74,7 @@ void main() {
|
||||
}, () async {
|
||||
final File packageConfig =
|
||||
environment.projectDir.childFile('.dart_tool/package_config.json');
|
||||
final Uri nonFlutterTesterAssetUri = environment.buildDir.childFile('native_assets.yaml').uri;
|
||||
final Uri nonFlutterTesterAssetUri = environment.buildDir.childFile('native_assets.json').uri;
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
|
||||
@ -302,33 +191,6 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('Native assets dry run error', overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
final File packageConfig =
|
||||
environment.projectDir.childFile('.dart_tool/package_config.json');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => runFlutterSpecificDartDryRunOnPlatforms(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetPlatforms: <TargetPlatform>[TargetPlatform.windows_x64],
|
||||
buildRunner: FakeFlutterNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: null,
|
||||
),
|
||||
),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'Building (dry run) native assets failed. See the logs for more details.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('Native assets build error', overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
|
@ -17,7 +17,6 @@ import '../../src/fake_vm_services.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/testbed.dart';
|
||||
import '../resident_runner_helpers.dart';
|
||||
import 'fake_native_assets_build_runner.dart';
|
||||
|
||||
void main() {
|
||||
late Testbed testbed;
|
||||
@ -55,8 +54,7 @@ void main() {
|
||||
]);
|
||||
globals.fs
|
||||
.file(globals.fs.path.join('lib', 'main.dart'))
|
||||
.createSync(recursive: true);
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner();
|
||||
.createSync(recursive: true);
|
||||
final HotRunner residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
flutterDevice,
|
||||
@ -71,7 +69,6 @@ void main() {
|
||||
)),
|
||||
target: 'main.dart',
|
||||
devtoolsHandler: createNoOpHandler,
|
||||
nativeAssetsBuilder: FakeHotRunnerNativeAssetsBuilder(buildRunner),
|
||||
analytics: FakeAnalytics(),
|
||||
nativeAssetsYamlFile: 'foo.yaml',
|
||||
);
|
||||
@ -79,12 +76,6 @@ void main() {
|
||||
final int result = await residentRunner.run();
|
||||
expect(result, 0);
|
||||
|
||||
expect(buildRunner.buildInvocations, 0);
|
||||
expect(buildRunner.buildDryRunInvocations, 0);
|
||||
expect(buildRunner.linkInvocations, 0);
|
||||
expect(buildRunner.hasPackageConfigInvocations, 0);
|
||||
expect(buildRunner.packagesWithNativeAssetsInvocations, 0);
|
||||
|
||||
expect(residentCompiler.recompileCalled, true);
|
||||
expect(residentCompiler.receivedNativeAssetsYaml, globals.fs.path.toUri('foo.yaml'));
|
||||
}),
|
||||
|
@ -145,7 +145,10 @@ void main() {
|
||||
'package:bar/bar.dart',
|
||||
if (flutterTester)
|
||||
// Tests run on host system, so the have the full path on the system.
|
||||
projectUri.resolve('build/native_assets/$expectedDirectory/bar.dll').toFilePath()
|
||||
projectUri
|
||||
.resolve('build/native_assets/$expectedDirectory/bar.dll')
|
||||
.toFilePath()
|
||||
.replaceAll(r'\', r'\\') // Undo JSON string escaping.
|
||||
else
|
||||
// Apps are a bundle with the dylibs on their dlopen path.
|
||||
'bar.dll',
|
||||
|
Loading…
x
Reference in New Issue
Block a user