mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

Changes to original CL: The code that issues an error on unsupported operating system in the dry-run case was missing a case for iOS and Android Original CL description tl;dr Removes 50% (>1650 locs) of native asset related code in `packages/flutter_tools` Before this PR the invocation of dart build/link/dry-run was implemented per OS. This lead to very large code duplication of almost identical, but slightly different code. It also led to similarly duplicated test code. Almost the entire dart build/link/dry-run implementation is identical across OSes. There's small variations: - configuration of the build (e.g. android/macos/ios version, ios sdk, ...) - determining target locations & copying the final shared libraries This PR unifies the implementation by reducing the code to basically two main functions: * `runFlutterSpecificDartBuild` which is responsible for - obtain flutter configuration - perform dart build (& link) - determine target location & install binaries * `runFlutterSpecificDartDryRunOnPlatforms` which is responsible for a similar (but not same): - obtain flutter configuration - perform dart dry run - determine target location these two functions will call out to helpers for the OS specific functionality: * `_assetTargetLocationsForOS` for determining the location of the code assets * `_copyNativeCodeAssetsForOS` for copying the code assets (and possibly overriting the install name, etc) => Since we get rid of the code duplication across OSes and have only a single code path for the build/link/dry-run, we can also remove the duplicated tests that were pretty much identical across OSes. We also harden the building code by adding asserts, e.g. * the dry fun functionality should never be used by `flutter test` * the `build/native_assets/<os>/native_assets.yaml` should only be used by `flutter test` and the dry-run of `flutter run` => We change the tests to also comply with these invariants (so the tests are not testing things that cannot happen in reality) We also rename `{,Flutter}NativeAssetsBuildRunner` to disambiguate it from the `package:native_asset_builder`'s `NativeAssetsBuildRunner`.
309 lines
11 KiB
Dart
309 lines
11 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:file/file.dart';
|
|
import 'package:file/memory.dart';
|
|
import 'package:file_testing/file_testing.dart';
|
|
import 'package:flutter_tools/src/artifacts.dart';
|
|
import 'package:flutter_tools/src/base/file_system.dart';
|
|
import 'package:flutter_tools/src/base/logger.dart';
|
|
import 'package:flutter_tools/src/build_info.dart';
|
|
import 'package:flutter_tools/src/build_system/build_system.dart';
|
|
import 'package:flutter_tools/src/features.dart';
|
|
import 'package:flutter_tools/src/globals.dart' as globals;
|
|
import 'package:flutter_tools/src/isolated/native_assets/native_assets.dart';
|
|
import 'package:native_assets_cli/native_assets_cli_internal.dart';
|
|
import 'package:package_config/package_config_types.dart';
|
|
|
|
import '../../src/common.dart';
|
|
import '../../src/context.dart';
|
|
import '../../src/fakes.dart';
|
|
import 'fake_native_assets_build_runner.dart';
|
|
|
|
void main() {
|
|
late FakeProcessManager processManager;
|
|
late Environment environment;
|
|
late Artifacts artifacts;
|
|
late FileSystem fileSystem;
|
|
late BufferLogger logger;
|
|
late Uri projectUri;
|
|
|
|
setUp(() {
|
|
processManager = FakeProcessManager.empty();
|
|
logger = BufferLogger.test();
|
|
artifacts = Artifacts.test();
|
|
fileSystem = MemoryFileSystem.test();
|
|
environment = Environment.test(
|
|
fileSystem.currentDirectory,
|
|
inputs: <String, String>{},
|
|
artifacts: artifacts,
|
|
processManager: processManager,
|
|
fileSystem: fileSystem,
|
|
logger: logger,
|
|
);
|
|
environment.buildDir.createSync(recursive: true);
|
|
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 {
|
|
final Uri nonFlutterTesterAssetUri = environment.buildDir.childFile('native_assets.yaml').uri;
|
|
await runFlutterSpecificDartBuild(
|
|
environmentDefines: <String, String>{
|
|
kBuildMode: BuildMode.debug.cliName,
|
|
},
|
|
targetPlatform: TargetPlatform.windows_x64,
|
|
projectUri: projectUri,
|
|
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
|
fileSystem: fileSystem,
|
|
buildRunner: FakeFlutterNativeAssetsBuildRunner(
|
|
hasPackageConfigResult: false,
|
|
),
|
|
);
|
|
expect(
|
|
(globals.logger as BufferLogger).traceText,
|
|
contains('No package config found. Skipping native assets compilation.'),
|
|
);
|
|
});
|
|
|
|
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(
|
|
assets: <AssetImpl>[
|
|
NativeCodeAssetImpl(
|
|
id: 'package:bar/bar.dart',
|
|
linkMode: DynamicLoadingBundledImpl(),
|
|
os: OSImpl.windows,
|
|
architecture: ArchitectureImpl.x64,
|
|
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/native_assets.yaml'),
|
|
);
|
|
expect(
|
|
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
|
contains('package:bar/bar.dart'),
|
|
);
|
|
expect(buildRunner.buildDryRunInvocations, 1);
|
|
});
|
|
|
|
testUsingContext('build with assets but not enabled', overrides: <Type, Generator>{
|
|
ProcessManager: () => FakeProcessManager.empty(),
|
|
}, () async {
|
|
final File packageConfig = environment.projectDir.childFile('.dart_tool/package_config.json');
|
|
final Uri nonFlutterTesterAssetUri = environment.buildDir.childFile('native_assets.yaml').uri;
|
|
await packageConfig.parent.create();
|
|
await packageConfig.create();
|
|
expect(
|
|
() => runFlutterSpecificDartBuild(
|
|
environmentDefines: <String, String>{
|
|
kBuildMode: BuildMode.debug.cliName,
|
|
},
|
|
targetPlatform: TargetPlatform.windows_x64,
|
|
projectUri: projectUri,
|
|
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
|
fileSystem: fileSystem,
|
|
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('build no assets', overrides: <Type, Generator>{
|
|
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
|
ProcessManager: () => FakeProcessManager.empty(),
|
|
}, () async {
|
|
final File packageConfig = environment.projectDir.childFile('.dart_tool/package_config.json');
|
|
final Uri nonFlutterTesterAssetUri = environment.buildDir.childFile('native_assets.yaml').uri;
|
|
await packageConfig.parent.create();
|
|
await packageConfig.create();
|
|
final (_, Uri nativeAssetsYaml) = await runFlutterSpecificDartBuild(
|
|
environmentDefines: <String, String>{
|
|
kBuildMode: BuildMode.debug.cliName,
|
|
},
|
|
targetPlatform: TargetPlatform.windows_x64,
|
|
projectUri: projectUri,
|
|
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
|
fileSystem: fileSystem,
|
|
buildRunner: FakeFlutterNativeAssetsBuildRunner(
|
|
packagesWithNativeAssetsResult: <Package>[
|
|
Package('bar', projectUri),
|
|
],
|
|
),
|
|
);
|
|
expect(nativeAssetsYaml, nonFlutterTesterAssetUri);
|
|
expect(
|
|
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
|
isNot(contains('package:bar/bar.dart')),
|
|
);
|
|
expect(
|
|
environment.projectDir.childDirectory('build').childDirectory('native_assets').childDirectory('windows'),
|
|
exists,
|
|
);
|
|
});
|
|
|
|
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: const FakeFlutterNativeAssetsBuilderResult(
|
|
success: false,
|
|
),
|
|
),
|
|
),
|
|
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(),
|
|
}, () async {
|
|
final File packageConfig =
|
|
environment.projectDir.childFile('.dart_tool/package_config.json');
|
|
final Uri nonFlutterTesterAssetUri = environment.buildDir.childFile('native_assets.yaml').uri;
|
|
await packageConfig.parent.create();
|
|
await packageConfig.create();
|
|
expect(
|
|
() => runFlutterSpecificDartBuild(
|
|
environmentDefines: <String, String>{
|
|
kBuildMode: BuildMode.debug.cliName,
|
|
},
|
|
targetPlatform: TargetPlatform.linux_x64,
|
|
projectUri: projectUri,
|
|
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
|
fileSystem: fileSystem,
|
|
buildRunner: FakeFlutterNativeAssetsBuildRunner(
|
|
packagesWithNativeAssetsResult: <Package>[
|
|
Package('bar', projectUri),
|
|
],
|
|
buildResult: const FakeFlutterNativeAssetsBuilderResult(
|
|
success: false,
|
|
),
|
|
),
|
|
),
|
|
throwsToolExit(
|
|
message:
|
|
'Building native assets failed. See the logs for more details.',
|
|
),
|
|
);
|
|
});
|
|
|
|
}
|