Reverts "[flutter_tools] Cleanup of native asset related code (removes around 50% of the native asset related code) (#155430)" (#155713)
Reverts: flutter/flutter#155430 Initiated by: eyebrowsoffire Reason for reverting: Postsubmit failures closing the tree. See the following examples: https://ci.chromium.org/ui/p/flutter/builders/prod/Mac_ios%20native_assets_ios/5738/overview https://ci.chromium.org/ui/p/flutter/builders/prod/Mac_arm64_mokey%20native_assets_android/583/overview https://ci.chromium.org/ui/p/flutter/builders/prod/Linux_pixel_7pro%20native_assets_android/4075/overview https://ci.chromium.org/u Original PR Author: mkustermann Reviewed By: {bkonyi, dcharkes} This change reverts the following previous change: 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 sligthly 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`. We also reorganize the main code to make it readable from top-down and make members private where they can be.
This commit is contained in:
parent
621e7ef951
commit
4dfa688ec4
@ -3,14 +3,22 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:native_assets_builder/native_assets_builder.dart';
|
||||
import 'package:native_assets_builder/native_assets_builder.dart' hide NativeAssetsBuildRunner;
|
||||
import 'package:package_config/package_config_types.dart';
|
||||
|
||||
import '../../android/gradle_utils.dart';
|
||||
import '../../base/common.dart';
|
||||
import '../../base/file_system.dart';
|
||||
import '../../base/platform.dart';
|
||||
import '../../build_info.dart';
|
||||
import '../../dart/package_map.dart';
|
||||
import '../../isolated/native_assets/android/native_assets.dart';
|
||||
import '../../isolated/native_assets/ios/native_assets.dart';
|
||||
import '../../isolated/native_assets/linux/native_assets.dart';
|
||||
import '../../isolated/native_assets/macos/native_assets.dart';
|
||||
import '../../isolated/native_assets/native_assets.dart';
|
||||
import '../../isolated/native_assets/windows/native_assets.dart';
|
||||
import '../../macos/xcode.dart';
|
||||
import '../build_system.dart';
|
||||
import '../depfile.dart';
|
||||
import '../exceptions.dart';
|
||||
@ -35,21 +43,20 @@ import 'common.dart';
|
||||
/// rebuild.
|
||||
class NativeAssets extends Target {
|
||||
const NativeAssets({
|
||||
@visibleForTesting FlutterNativeAssetsBuildRunner? buildRunner,
|
||||
@visibleForTesting NativeAssetsBuildRunner? buildRunner,
|
||||
}) : _buildRunner = buildRunner;
|
||||
|
||||
final FlutterNativeAssetsBuildRunner? _buildRunner;
|
||||
final NativeAssetsBuildRunner? _buildRunner;
|
||||
|
||||
@override
|
||||
Future<void> build(Environment environment) async {
|
||||
final String? nativeAssetsEnvironment = environment.defines[kNativeAssets];
|
||||
final List<Uri> dependencies;
|
||||
final FileSystem fileSystem = environment.fileSystem;
|
||||
final Uri nativeAssetsFileUri = environment.buildDir.childFile('native_assets.yaml').uri;
|
||||
|
||||
final DartBuildResult result;
|
||||
final File nativeAssetsFile = environment.buildDir.childFile('native_assets.yaml');
|
||||
if (nativeAssetsEnvironment == 'false') {
|
||||
result = const DartBuildResult.empty();
|
||||
await writeNativeAssetsYaml(KernelAssets(), nativeAssetsFileUri, fileSystem);
|
||||
dependencies = <Uri>[];
|
||||
await writeNativeAssetsYaml(KernelAssets(), environment.buildDir.uri, fileSystem);
|
||||
} else {
|
||||
final String? targetPlatformEnvironment = environment.defines[kTargetPlatform];
|
||||
if (targetPlatformEnvironment == null) {
|
||||
@ -62,8 +69,8 @@ class NativeAssets extends Target {
|
||||
fileSystem.file(environment.packageConfigPath),
|
||||
logger: environment.logger,
|
||||
);
|
||||
final FlutterNativeAssetsBuildRunner buildRunner = _buildRunner ??
|
||||
FlutterNativeAssetsBuildRunnerImpl(
|
||||
final NativeAssetsBuildRunner buildRunner = _buildRunner ??
|
||||
NativeAssetsBuildRunnerImpl(
|
||||
projectUri,
|
||||
environment.packageConfigPath,
|
||||
packageConfig,
|
||||
@ -71,22 +78,102 @@ class NativeAssets extends Target {
|
||||
environment.logger,
|
||||
);
|
||||
|
||||
(result, _) = await runFlutterSpecificDartBuild(
|
||||
environmentDefines: environment.defines,
|
||||
buildRunner: buildRunner,
|
||||
targetPlatform: targetPlatform,
|
||||
projectUri: projectUri,
|
||||
nativeAssetsYamlUri : nativeAssetsFileUri,
|
||||
fileSystem: fileSystem,
|
||||
);
|
||||
switch (targetPlatform) {
|
||||
case TargetPlatform.ios:
|
||||
dependencies = await _buildIOS(
|
||||
environment,
|
||||
projectUri,
|
||||
fileSystem,
|
||||
buildRunner,
|
||||
);
|
||||
case TargetPlatform.darwin:
|
||||
dependencies = await _buildMacOS(
|
||||
environment,
|
||||
projectUri,
|
||||
fileSystem,
|
||||
buildRunner,
|
||||
);
|
||||
case TargetPlatform.linux_arm64:
|
||||
case TargetPlatform.linux_x64:
|
||||
dependencies = await _buildLinux(
|
||||
environment,
|
||||
targetPlatform,
|
||||
projectUri,
|
||||
fileSystem,
|
||||
buildRunner,
|
||||
);
|
||||
case TargetPlatform.windows_arm64:
|
||||
case TargetPlatform.windows_x64:
|
||||
dependencies = await _buildWindows(
|
||||
environment,
|
||||
targetPlatform,
|
||||
projectUri,
|
||||
fileSystem,
|
||||
buildRunner,
|
||||
);
|
||||
case TargetPlatform.tester:
|
||||
if (const LocalPlatform().isMacOS) {
|
||||
(_, dependencies) = await buildNativeAssetsMacOS(
|
||||
buildMode: BuildMode.debug,
|
||||
projectUri: projectUri,
|
||||
codesignIdentity: environment.defines[kCodesignIdentity],
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
flutterTester: true,
|
||||
);
|
||||
} else if (const LocalPlatform().isLinux) {
|
||||
(_, dependencies) = await buildNativeAssetsLinux(
|
||||
buildMode: BuildMode.debug,
|
||||
projectUri: projectUri,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
flutterTester: true,
|
||||
);
|
||||
} else if (const LocalPlatform().isWindows) {
|
||||
(_, dependencies) = await buildNativeAssetsWindows(
|
||||
buildMode: BuildMode.debug,
|
||||
projectUri: projectUri,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
flutterTester: true,
|
||||
);
|
||||
} else {
|
||||
// TODO(dacoharkes): Implement other OSes. https://github.com/flutter/flutter/issues/129757
|
||||
// Write the file we claim to have in the [outputs].
|
||||
await writeNativeAssetsYaml(KernelAssets(), environment.buildDir.uri, fileSystem);
|
||||
dependencies = <Uri>[];
|
||||
}
|
||||
case TargetPlatform.android_arm:
|
||||
case TargetPlatform.android_arm64:
|
||||
case TargetPlatform.android_x64:
|
||||
case TargetPlatform.android_x86:
|
||||
case TargetPlatform.android:
|
||||
(_, dependencies) = await _buildAndroid(
|
||||
environment,
|
||||
targetPlatform,
|
||||
projectUri,
|
||||
fileSystem,
|
||||
buildRunner,
|
||||
);
|
||||
case TargetPlatform.fuchsia_arm64:
|
||||
case TargetPlatform.fuchsia_x64:
|
||||
case TargetPlatform.web_javascript:
|
||||
// TODO(dacoharkes): Implement other OSes. https://github.com/flutter/flutter/issues/129757
|
||||
// Write the file we claim to have in the [outputs].
|
||||
await writeNativeAssetsYaml(KernelAssets(), environment.buildDir.uri, fileSystem);
|
||||
dependencies = <Uri>[];
|
||||
}
|
||||
}
|
||||
|
||||
final Depfile depfile = Depfile(
|
||||
<File>[
|
||||
for (final Uri dependency in result.dependencies) fileSystem.file(dependency),
|
||||
for (final Uri dependency in dependencies) fileSystem.file(dependency),
|
||||
],
|
||||
<File>[
|
||||
fileSystem.file(nativeAssetsFileUri),
|
||||
nativeAssetsFile,
|
||||
],
|
||||
);
|
||||
final File outputDepfile = environment.buildDir.childFile('native_assets.d');
|
||||
@ -94,14 +181,188 @@ class NativeAssets extends Target {
|
||||
outputDepfile.parent.createSync(recursive: true);
|
||||
}
|
||||
environment.depFileService.writeToFile(depfile, outputDepfile);
|
||||
if (!await fileSystem.file(nativeAssetsFileUri).exists()) {
|
||||
throwToolExit("${nativeAssetsFileUri.path} doesn't exist.");
|
||||
if (!await nativeAssetsFile.exists()) {
|
||||
throwToolExit("${nativeAssetsFile.path} doesn't exist.");
|
||||
}
|
||||
if (!await outputDepfile.exists()) {
|
||||
throwToolExit("${outputDepfile.path} doesn't exist.");
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Uri>> _buildWindows(
|
||||
Environment environment,
|
||||
TargetPlatform targetPlatform,
|
||||
Uri projectUri,
|
||||
FileSystem fileSystem,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) async {
|
||||
final String? environmentBuildMode = environment.defines[kBuildMode];
|
||||
if (environmentBuildMode == null) {
|
||||
throw MissingDefineException(kBuildMode, name);
|
||||
}
|
||||
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
|
||||
final (_, List<Uri> dependencies) = await buildNativeAssetsWindows(
|
||||
targetPlatform: targetPlatform,
|
||||
buildMode: buildMode,
|
||||
projectUri: projectUri,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
Future<List<Uri>> _buildLinux(
|
||||
Environment environment,
|
||||
TargetPlatform targetPlatform,
|
||||
Uri projectUri,
|
||||
FileSystem fileSystem,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) async {
|
||||
final String? environmentBuildMode = environment.defines[kBuildMode];
|
||||
if (environmentBuildMode == null) {
|
||||
throw MissingDefineException(kBuildMode, name);
|
||||
}
|
||||
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
|
||||
final (_, List<Uri> dependencies) = await buildNativeAssetsLinux(
|
||||
targetPlatform: targetPlatform,
|
||||
buildMode: buildMode,
|
||||
projectUri: projectUri,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
Future<List<Uri>> _buildMacOS(
|
||||
Environment environment,
|
||||
Uri projectUri,
|
||||
FileSystem fileSystem,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) async {
|
||||
final List<DarwinArch> darwinArchs =
|
||||
_emptyToNull(environment.defines[kDarwinArchs])
|
||||
?.split(' ')
|
||||
.map(getDarwinArchForName)
|
||||
.toList() ??
|
||||
<DarwinArch>[DarwinArch.x86_64, DarwinArch.arm64];
|
||||
final String? environmentBuildMode = environment.defines[kBuildMode];
|
||||
if (environmentBuildMode == null) {
|
||||
throw MissingDefineException(kBuildMode, name);
|
||||
}
|
||||
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
|
||||
final (_, List<Uri> dependencies) = await buildNativeAssetsMacOS(
|
||||
darwinArchs: darwinArchs,
|
||||
buildMode: buildMode,
|
||||
projectUri: projectUri,
|
||||
codesignIdentity: environment.defines[kCodesignIdentity],
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
Future<List<Uri>> _buildIOS(
|
||||
Environment environment,
|
||||
Uri projectUri,
|
||||
FileSystem fileSystem,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) {
|
||||
final List<DarwinArch> iosArchs =
|
||||
_emptyToNull(environment.defines[kIosArchs])
|
||||
?.split(' ')
|
||||
.map(getIOSArchForName)
|
||||
.toList() ??
|
||||
<DarwinArch>[DarwinArch.arm64];
|
||||
final String? environmentBuildMode = environment.defines[kBuildMode];
|
||||
if (environmentBuildMode == null) {
|
||||
throw MissingDefineException(kBuildMode, name);
|
||||
}
|
||||
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
|
||||
final String? sdkRoot = environment.defines[kSdkRoot];
|
||||
if (sdkRoot == null) {
|
||||
throw MissingDefineException(kSdkRoot, name);
|
||||
}
|
||||
final EnvironmentType environmentType =
|
||||
environmentTypeFromSdkroot(sdkRoot, environment.fileSystem)!;
|
||||
return buildNativeAssetsIOS(
|
||||
environmentType: environmentType,
|
||||
darwinArchs: iosArchs,
|
||||
buildMode: buildMode,
|
||||
projectUri: projectUri,
|
||||
codesignIdentity: environment.defines[kCodesignIdentity],
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
);
|
||||
}
|
||||
|
||||
Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)> _buildAndroid(
|
||||
Environment environment,
|
||||
TargetPlatform targetPlatform,
|
||||
Uri projectUri,
|
||||
FileSystem fileSystem,
|
||||
NativeAssetsBuildRunner buildRunner) {
|
||||
final String? androidArchsEnvironment = environment.defines[kAndroidArchs];
|
||||
final List<AndroidArch> androidArchs = _androidArchs(
|
||||
targetPlatform,
|
||||
androidArchsEnvironment,
|
||||
);
|
||||
final int targetAndroidNdkApi =
|
||||
int.parse(environment.defines[kMinSdkVersion] ?? minSdkVersion);
|
||||
final String? environmentBuildMode = environment.defines[kBuildMode];
|
||||
if (environmentBuildMode == null) {
|
||||
throw MissingDefineException(kBuildMode, name);
|
||||
}
|
||||
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
|
||||
return buildNativeAssetsAndroid(
|
||||
buildMode: buildMode,
|
||||
projectUri: projectUri,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
androidArchs: androidArchs,
|
||||
targetAndroidNdkApi: targetAndroidNdkApi,
|
||||
);
|
||||
}
|
||||
|
||||
List<AndroidArch> _androidArchs(
|
||||
TargetPlatform targetPlatform,
|
||||
String? androidArchsEnvironment,
|
||||
) {
|
||||
switch (targetPlatform) {
|
||||
case TargetPlatform.android_arm:
|
||||
return <AndroidArch>[AndroidArch.armeabi_v7a];
|
||||
case TargetPlatform.android_arm64:
|
||||
return <AndroidArch>[AndroidArch.arm64_v8a];
|
||||
case TargetPlatform.android_x64:
|
||||
return <AndroidArch>[AndroidArch.x86_64];
|
||||
case TargetPlatform.android_x86:
|
||||
return <AndroidArch>[AndroidArch.x86];
|
||||
case TargetPlatform.android:
|
||||
if (androidArchsEnvironment == null) {
|
||||
throw MissingDefineException(kAndroidArchs, name);
|
||||
}
|
||||
return androidArchsEnvironment
|
||||
.split(' ')
|
||||
.map(getAndroidArchForName)
|
||||
.toList();
|
||||
case TargetPlatform.darwin:
|
||||
case TargetPlatform.fuchsia_arm64:
|
||||
case TargetPlatform.fuchsia_x64:
|
||||
case TargetPlatform.ios:
|
||||
case TargetPlatform.linux_arm64:
|
||||
case TargetPlatform.linux_x64:
|
||||
case TargetPlatform.tester:
|
||||
case TargetPlatform.web_javascript:
|
||||
case TargetPlatform.windows_x64:
|
||||
case TargetPlatform.windows_arm64:
|
||||
throwToolExit('Unsupported Android target platform: $targetPlatform.');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<String> get depfiles => <String>[
|
||||
'native_assets.d',
|
||||
@ -129,3 +390,10 @@ class NativeAssets extends Target {
|
||||
Source.pattern('{BUILD_DIR}/native_assets.yaml'),
|
||||
];
|
||||
}
|
||||
|
||||
String? _emptyToNull(String? input) {
|
||||
if (input == null || input.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
@ -2,24 +2,145 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:native_assets_builder/native_assets_builder.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli.dart';
|
||||
import 'package:native_assets_builder/native_assets_builder.dart'
|
||||
hide NativeAssetsBuildRunner;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart';
|
||||
|
||||
import '../../../android/android_sdk.dart';
|
||||
import '../../../android/gradle_utils.dart';
|
||||
import '../../../base/common.dart';
|
||||
import '../../../base/file_system.dart';
|
||||
import '../../../build_info.dart' hide BuildMode;
|
||||
import '../../../build_info.dart';
|
||||
import '../../../globals.dart' as globals;
|
||||
import '../native_assets.dart';
|
||||
|
||||
int targetAndroidNdkApi(Map<String, String> environmentDefines) {
|
||||
return int.parse(environmentDefines[kMinSdkVersion] ?? minSdkVersion);
|
||||
/// Dry run the native builds.
|
||||
///
|
||||
/// This does not build native assets, it only simulates what the final paths
|
||||
/// of all assets will be so that this can be embedded in the kernel file.
|
||||
Future<Uri?> dryRunNativeAssetsAndroid({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
required Uri projectUri,
|
||||
bool flutterTester = false,
|
||||
required FileSystem fileSystem,
|
||||
}) async {
|
||||
if (!await nativeBuildRequired(buildRunner)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Uri buildUri_ = nativeAssetsBuildUri(projectUri, OSImpl.android);
|
||||
final Iterable<KernelAsset> nativeAssetPaths =
|
||||
await dryRunNativeAssetsAndroidInternal(
|
||||
fileSystem,
|
||||
projectUri,
|
||||
buildRunner,
|
||||
);
|
||||
final Uri nativeAssetsUri = await writeNativeAssetsYaml(
|
||||
KernelAssets(nativeAssetPaths),
|
||||
buildUri_,
|
||||
fileSystem,
|
||||
);
|
||||
return nativeAssetsUri;
|
||||
}
|
||||
|
||||
Future<void> copyNativeCodeAssetsAndroid(
|
||||
Future<Iterable<KernelAsset>> dryRunNativeAssetsAndroidInternal(
|
||||
FileSystem fileSystem,
|
||||
Uri projectUri,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) async {
|
||||
const OSImpl targetOS = OSImpl.android;
|
||||
|
||||
globals.logger.printTrace('Dry running native assets for $targetOS.');
|
||||
final BuildDryRunResult buildDryRunResult = await buildRunner.buildDryRun(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
targetOS: targetOS,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
);
|
||||
ensureNativeAssetsBuildDryRunSucceed(buildDryRunResult);
|
||||
// No link hooks in JIT mode.
|
||||
final List<AssetImpl> nativeAssets = buildDryRunResult.assets;
|
||||
globals.logger.printTrace('Dry running native assets for $targetOS done.');
|
||||
final Map<AssetImpl, KernelAsset> assetTargetLocations =
|
||||
_assetTargetLocations(nativeAssets);
|
||||
return assetTargetLocations.values;
|
||||
}
|
||||
|
||||
/// Builds native assets.
|
||||
Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)>
|
||||
buildNativeAssetsAndroid({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
required Iterable<AndroidArch> androidArchs,
|
||||
required Uri projectUri,
|
||||
required BuildMode buildMode,
|
||||
String? codesignIdentity,
|
||||
Uri? yamlParentDirectory,
|
||||
required FileSystem fileSystem,
|
||||
required int targetAndroidNdkApi,
|
||||
}) async {
|
||||
const OSImpl targetOS = OSImpl.android;
|
||||
final Uri buildUri_ = nativeAssetsBuildUri(projectUri, targetOS);
|
||||
if (!await nativeBuildRequired(buildRunner)) {
|
||||
final Uri nativeAssetsYaml = await writeNativeAssetsYaml(
|
||||
KernelAssets(),
|
||||
yamlParentDirectory ?? buildUri_,
|
||||
fileSystem,
|
||||
);
|
||||
return (nativeAssetsYaml, <Uri>[]);
|
||||
}
|
||||
|
||||
final List<Target> targets = androidArchs.map(_getNativeTarget).toList();
|
||||
final BuildModeImpl buildModeCli =
|
||||
nativeAssetsBuildMode(buildMode);
|
||||
final bool linkingEnabled = buildModeCli == BuildModeImpl.release;
|
||||
|
||||
globals.logger
|
||||
.printTrace('Building native assets for $targets $buildModeCli.');
|
||||
final List<AssetImpl> nativeAssets = <AssetImpl>[];
|
||||
final Set<Uri> dependencies = <Uri>{};
|
||||
for (final Target target in targets) {
|
||||
final BuildResult buildResult = await buildRunner.build(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
target: target,
|
||||
buildMode: buildModeCli,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
cCompilerConfig: await buildRunner.ndkCCompilerConfigImpl,
|
||||
targetAndroidNdkApi: targetAndroidNdkApi,
|
||||
linkingEnabled: linkingEnabled,
|
||||
);
|
||||
ensureNativeAssetsBuildSucceed(buildResult);
|
||||
nativeAssets.addAll(buildResult.assets);
|
||||
dependencies.addAll(buildResult.dependencies);
|
||||
if (linkingEnabled) {
|
||||
final LinkResult linkResult = await buildRunner.link(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
target: target,
|
||||
buildMode: buildModeCli,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
cCompilerConfig: await buildRunner.ndkCCompilerConfigImpl,
|
||||
targetAndroidNdkApi: targetAndroidNdkApi,
|
||||
buildResult: buildResult,
|
||||
);
|
||||
ensureNativeAssetsLinkSucceed(linkResult);
|
||||
nativeAssets.addAll(linkResult.assets);
|
||||
dependencies.addAll(linkResult.dependencies);
|
||||
}
|
||||
}
|
||||
globals.logger.printTrace('Building native assets for $targets done.');
|
||||
final Map<AssetImpl, KernelAsset> assetTargetLocations =
|
||||
_assetTargetLocations(nativeAssets);
|
||||
await _copyNativeAssetsAndroid(buildUri_, assetTargetLocations, fileSystem);
|
||||
final Uri nativeAssetsUri = await writeNativeAssetsYaml(
|
||||
KernelAssets(assetTargetLocations.values),
|
||||
yamlParentDirectory ?? buildUri_,
|
||||
fileSystem);
|
||||
return (nativeAssetsUri, dependencies.toList());
|
||||
}
|
||||
|
||||
Future<void> _copyNativeAssetsAndroid(
|
||||
Uri buildUri,
|
||||
Map<NativeCodeAssetImpl, KernelAsset> assetTargetLocations,
|
||||
Map<AssetImpl, KernelAsset> assetTargetLocations,
|
||||
FileSystem fileSystem,
|
||||
) async {
|
||||
if (assetTargetLocations.isNotEmpty) {
|
||||
@ -33,7 +154,7 @@ Future<void> copyNativeCodeAssetsAndroid(
|
||||
final Uri archUri = buildUri.resolve('jniLibs/lib/$jniArchDir/');
|
||||
await fileSystem.directory(archUri).create(recursive: true);
|
||||
}
|
||||
for (final MapEntry<NativeCodeAssetImpl, KernelAsset> assetMapping
|
||||
for (final MapEntry<AssetImpl, KernelAsset> assetMapping
|
||||
in assetTargetLocations.entries) {
|
||||
final Uri source = assetMapping.key.file!;
|
||||
final Uri target = (assetMapping.value.path as KernelAssetAbsolutePath).uri;
|
||||
@ -50,7 +171,7 @@ Future<void> copyNativeCodeAssetsAndroid(
|
||||
}
|
||||
|
||||
/// Get the [Target] for [androidArch].
|
||||
Target getNativeAndroidTarget(AndroidArch androidArch) {
|
||||
Target _getNativeTarget(AndroidArch androidArch) {
|
||||
return switch (androidArch) {
|
||||
AndroidArch.armeabi_v7a => Target.androidArm,
|
||||
AndroidArch.arm64_v8a => Target.androidArm64,
|
||||
@ -71,27 +192,27 @@ AndroidArch _getAndroidArch(Target target) {
|
||||
};
|
||||
}
|
||||
|
||||
Map<NativeCodeAssetImpl, KernelAsset> assetTargetLocationsAndroid(
|
||||
List<NativeCodeAssetImpl> nativeAssets) {
|
||||
return <NativeCodeAssetImpl, KernelAsset>{
|
||||
for (final NativeCodeAssetImpl asset in nativeAssets)
|
||||
Map<AssetImpl, KernelAsset> _assetTargetLocations(
|
||||
List<AssetImpl> nativeAssets) {
|
||||
return <AssetImpl, KernelAsset>{
|
||||
for (final AssetImpl asset in nativeAssets)
|
||||
asset: _targetLocationAndroid(asset),
|
||||
};
|
||||
}
|
||||
|
||||
/// Converts the `path` of [asset] as output from a `build.dart` invocation to
|
||||
/// the path used inside the Flutter app bundle.
|
||||
KernelAsset _targetLocationAndroid(NativeCodeAssetImpl asset) {
|
||||
final LinkMode linkMode = asset.linkMode;
|
||||
KernelAsset _targetLocationAndroid(AssetImpl asset) {
|
||||
final LinkModeImpl linkMode = (asset as NativeCodeAssetImpl).linkMode;
|
||||
final KernelAssetPath kernelAssetPath;
|
||||
switch (linkMode) {
|
||||
case DynamicLoadingSystem _:
|
||||
case DynamicLoadingSystemImpl _:
|
||||
kernelAssetPath = KernelAssetSystemPath(linkMode.uri);
|
||||
case LookupInExecutable _:
|
||||
case LookupInExecutableImpl _:
|
||||
kernelAssetPath = KernelAssetInExecutable();
|
||||
case LookupInProcess _:
|
||||
case LookupInProcessImpl _:
|
||||
kernelAssetPath = KernelAssetInProcess();
|
||||
case DynamicLoadingBundled _:
|
||||
case DynamicLoadingBundledImpl _:
|
||||
final String fileName = asset.file!.pathSegments.last;
|
||||
kernelAssetPath = KernelAssetAbsolutePath(Uri(path: fileName));
|
||||
default:
|
||||
@ -113,6 +234,7 @@ KernelAsset _targetLocationAndroid(NativeCodeAssetImpl asset) {
|
||||
/// Should only be invoked if a native assets build is performed. If the native
|
||||
/// assets feature is disabled, or none of the packages have native assets, a
|
||||
/// missing NDK is okay.
|
||||
@override
|
||||
Future<CCompilerConfigImpl> cCompilerConfigAndroid() async {
|
||||
final AndroidSdk? androidSdk = AndroidSdk.locateAndroidSdk();
|
||||
if (androidSdk == null) {
|
||||
|
@ -2,20 +2,147 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:native_assets_builder/native_assets_builder.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli.dart';
|
||||
import 'package:native_assets_builder/native_assets_builder.dart'
|
||||
hide NativeAssetsBuildRunner;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart';
|
||||
|
||||
import '../../../base/file_system.dart';
|
||||
import '../../../build_info.dart' hide BuildMode;
|
||||
import '../../../build_info.dart' as build_info;
|
||||
import '../../../build_info.dart';
|
||||
import '../../../globals.dart' as globals;
|
||||
import '../macos/native_assets_host.dart';
|
||||
import '../native_assets.dart';
|
||||
|
||||
// TODO(dcharkes): Fetch minimum iOS version from somewhere. https://github.com/flutter/flutter/issues/145104
|
||||
const int targetIOSVersion = 12;
|
||||
/// Dry run the native builds.
|
||||
///
|
||||
/// This does not build native assets, it only simulates what the final paths
|
||||
/// of all assets will be so that this can be embedded in the kernel file and
|
||||
/// the Xcode project.
|
||||
Future<Uri?> dryRunNativeAssetsIOS({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
required Uri projectUri,
|
||||
required FileSystem fileSystem,
|
||||
}) async {
|
||||
if (!await nativeBuildRequired(buildRunner)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IOSSdkImpl getIOSSdk(EnvironmentType environmentType) {
|
||||
final Uri buildUri = nativeAssetsBuildUri(projectUri, OSImpl.iOS);
|
||||
final Iterable<KernelAsset> assetTargetLocations = await dryRunNativeAssetsIOSInternal(
|
||||
fileSystem,
|
||||
projectUri,
|
||||
buildRunner,
|
||||
);
|
||||
final Uri nativeAssetsUri = await writeNativeAssetsYaml(
|
||||
KernelAssets(assetTargetLocations),
|
||||
buildUri,
|
||||
fileSystem,
|
||||
);
|
||||
return nativeAssetsUri;
|
||||
}
|
||||
|
||||
Future<Iterable<KernelAsset>> dryRunNativeAssetsIOSInternal(
|
||||
FileSystem fileSystem,
|
||||
Uri projectUri,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) async {
|
||||
const OSImpl targetOS = OSImpl.iOS;
|
||||
globals.logger.printTrace('Dry running native assets for $targetOS.');
|
||||
final BuildDryRunResult buildDryRunResult = await buildRunner.buildDryRun(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
targetOS: targetOS,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
);
|
||||
ensureNativeAssetsBuildDryRunSucceed(buildDryRunResult);
|
||||
// No link hooks in JIT.
|
||||
final List<AssetImpl> nativeAssets = buildDryRunResult.assets;
|
||||
globals.logger.printTrace('Dry running native assets for $targetOS done.');
|
||||
return _assetTargetLocations(nativeAssets).values;
|
||||
}
|
||||
|
||||
/// Builds native assets.
|
||||
Future<List<Uri>> buildNativeAssetsIOS({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
required List<DarwinArch> darwinArchs,
|
||||
required EnvironmentType environmentType,
|
||||
required Uri projectUri,
|
||||
required BuildMode buildMode,
|
||||
String? codesignIdentity,
|
||||
required Uri yamlParentDirectory,
|
||||
required FileSystem fileSystem,
|
||||
}) async {
|
||||
if (!await nativeBuildRequired(buildRunner)) {
|
||||
await writeNativeAssetsYaml(KernelAssets(), yamlParentDirectory, fileSystem);
|
||||
return <Uri>[];
|
||||
}
|
||||
|
||||
final List<Target> targets = darwinArchs.map(_getNativeTarget).toList();
|
||||
final BuildModeImpl buildModeCli = nativeAssetsBuildMode(buildMode);
|
||||
final bool linkingEnabled = buildModeCli == BuildModeImpl.release;
|
||||
|
||||
const OSImpl targetOS = OSImpl.iOS;
|
||||
final Uri buildUri = nativeAssetsBuildUri(projectUri, targetOS);
|
||||
final IOSSdkImpl iosSdk = _getIOSSdkImpl(environmentType);
|
||||
|
||||
globals.logger.printTrace('Building native assets for $targets $buildModeCli.');
|
||||
final List<AssetImpl> nativeAssets = <AssetImpl>[];
|
||||
final Set<Uri> dependencies = <Uri>{};
|
||||
for (final Target target in targets) {
|
||||
final BuildResult buildResult = await buildRunner.build(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
target: target,
|
||||
targetIOSSdkImpl: iosSdk,
|
||||
buildMode: buildModeCli,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
cCompilerConfig: await buildRunner.cCompilerConfig,
|
||||
// TODO(dcharkes): Fetch minimum iOS version from somewhere. https://github.com/flutter/flutter/issues/145104
|
||||
targetIOSVersion: 12,
|
||||
linkingEnabled: linkingEnabled,
|
||||
);
|
||||
ensureNativeAssetsBuildSucceed(buildResult);
|
||||
nativeAssets.addAll(buildResult.assets);
|
||||
dependencies.addAll(buildResult.dependencies);
|
||||
if (linkingEnabled) {
|
||||
final LinkResult linkResult = await buildRunner.link(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
target: target,
|
||||
targetIOSSdkImpl: iosSdk,
|
||||
buildMode: buildModeCli,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
cCompilerConfig: await buildRunner.cCompilerConfig,
|
||||
buildResult: buildResult,
|
||||
// TODO(dcharkes): Fetch minimum iOS version from somewhere. https://github.com/flutter/flutter/issues/145104
|
||||
targetIOSVersion: 12,
|
||||
);
|
||||
ensureNativeAssetsLinkSucceed(linkResult);
|
||||
nativeAssets.addAll(linkResult.assets);
|
||||
dependencies.addAll(linkResult.dependencies);
|
||||
}
|
||||
}
|
||||
globals.logger.printTrace('Building native assets for $targets done.');
|
||||
final Map<KernelAssetPath, List<AssetImpl>> fatAssetTargetLocations =
|
||||
_fatAssetTargetLocations(nativeAssets);
|
||||
await _copyNativeAssetsIOS(
|
||||
buildUri,
|
||||
fatAssetTargetLocations,
|
||||
codesignIdentity,
|
||||
buildMode,
|
||||
fileSystem,
|
||||
);
|
||||
|
||||
final Map<AssetImpl, KernelAsset> assetTargetLocations =
|
||||
_assetTargetLocations(nativeAssets);
|
||||
await writeNativeAssetsYaml(
|
||||
KernelAssets(assetTargetLocations.values),
|
||||
yamlParentDirectory,
|
||||
fileSystem,
|
||||
);
|
||||
return dependencies.toList();
|
||||
}
|
||||
|
||||
IOSSdkImpl _getIOSSdkImpl(EnvironmentType environmentType) {
|
||||
return switch (environmentType) {
|
||||
EnvironmentType.physical => IOSSdkImpl.iPhoneOS,
|
||||
EnvironmentType.simulator => IOSSdkImpl.iPhoneSimulator,
|
||||
@ -23,7 +150,7 @@ IOSSdkImpl getIOSSdk(EnvironmentType environmentType) {
|
||||
}
|
||||
|
||||
/// Extract the [Target] from a [DarwinArch].
|
||||
Target getNativeIOSTarget(DarwinArch darwinArch) {
|
||||
Target _getNativeTarget(DarwinArch darwinArch) {
|
||||
return switch (darwinArch) {
|
||||
DarwinArch.armv7 => Target.iOSArm,
|
||||
DarwinArch.arm64 => Target.iOSArm64,
|
||||
@ -31,13 +158,13 @@ Target getNativeIOSTarget(DarwinArch darwinArch) {
|
||||
};
|
||||
}
|
||||
|
||||
Map<KernelAssetPath, List<NativeCodeAssetImpl>> fatAssetTargetLocationsIOS(
|
||||
List<NativeCodeAssetImpl> nativeAssets) {
|
||||
Map<KernelAssetPath, List<AssetImpl>> _fatAssetTargetLocations(
|
||||
List<AssetImpl> nativeAssets) {
|
||||
final Set<String> alreadyTakenNames = <String>{};
|
||||
final Map<KernelAssetPath, List<NativeCodeAssetImpl>> result =
|
||||
<KernelAssetPath, List<NativeCodeAssetImpl>>{};
|
||||
final Map<KernelAssetPath, List<AssetImpl>> result =
|
||||
<KernelAssetPath, List<AssetImpl>>{};
|
||||
final Map<String, KernelAssetPath> idToPath = <String, KernelAssetPath>{};
|
||||
for (final NativeCodeAssetImpl asset in nativeAssets) {
|
||||
for (final AssetImpl asset in nativeAssets) {
|
||||
// Use same target path for all assets with the same id.
|
||||
final KernelAssetPath path = idToPath[asset.id] ??
|
||||
_targetLocationIOS(
|
||||
@ -45,24 +172,23 @@ Map<KernelAssetPath, List<NativeCodeAssetImpl>> fatAssetTargetLocationsIOS(
|
||||
alreadyTakenNames,
|
||||
).path;
|
||||
idToPath[asset.id] = path;
|
||||
result[path] ??= <NativeCodeAssetImpl>[];
|
||||
result[path] ??= <AssetImpl>[];
|
||||
result[path]!.add(asset);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<NativeCodeAssetImpl, KernelAsset> assetTargetLocationsIOS(
|
||||
List<NativeCodeAssetImpl> nativeAssets) {
|
||||
Map<AssetImpl, KernelAsset> _assetTargetLocations(
|
||||
List<AssetImpl> nativeAssets) {
|
||||
final Set<String> alreadyTakenNames = <String>{};
|
||||
final Map<String, KernelAssetPath> idToPath = <String, KernelAssetPath>{};
|
||||
final Map<NativeCodeAssetImpl, KernelAsset> result =
|
||||
<NativeCodeAssetImpl, KernelAsset>{};
|
||||
for (final NativeCodeAssetImpl asset in nativeAssets) {
|
||||
final KernelAssetPath path =
|
||||
idToPath[asset.id] ?? _targetLocationIOS(asset, alreadyTakenNames).path;
|
||||
final Map<AssetImpl, KernelAsset> result = <AssetImpl, KernelAsset>{};
|
||||
for (final AssetImpl asset in nativeAssets) {
|
||||
final KernelAssetPath path = idToPath[asset.id] ??
|
||||
_targetLocationIOS(asset, alreadyTakenNames).path;
|
||||
idToPath[asset.id] = path;
|
||||
result[asset] = KernelAsset(
|
||||
id: asset.id,
|
||||
id: (asset as NativeCodeAssetImpl).id,
|
||||
target: Target.fromArchitectureAndOS(asset.architecture!, asset.os),
|
||||
path: path,
|
||||
);
|
||||
@ -70,18 +196,17 @@ Map<NativeCodeAssetImpl, KernelAsset> assetTargetLocationsIOS(
|
||||
return result;
|
||||
}
|
||||
|
||||
KernelAsset _targetLocationIOS(
|
||||
NativeCodeAssetImpl asset, Set<String> alreadyTakenNames) {
|
||||
final LinkMode linkMode = asset.linkMode;
|
||||
final KernelAssetPath kernelAssetPath;
|
||||
KernelAsset _targetLocationIOS(AssetImpl asset, Set<String> alreadyTakenNames) {
|
||||
final LinkModeImpl linkMode = (asset as NativeCodeAssetImpl).linkMode;
|
||||
final KernelAssetPath kernelAssetPath;
|
||||
switch (linkMode) {
|
||||
case DynamicLoadingSystem _:
|
||||
case DynamicLoadingSystemImpl _:
|
||||
kernelAssetPath = KernelAssetSystemPath(linkMode.uri);
|
||||
case LookupInExecutable _:
|
||||
case LookupInExecutableImpl _:
|
||||
kernelAssetPath = KernelAssetInExecutable();
|
||||
case LookupInProcess _:
|
||||
case LookupInProcessImpl _:
|
||||
kernelAssetPath = KernelAssetInProcess();
|
||||
case DynamicLoadingBundled _:
|
||||
case DynamicLoadingBundledImpl _:
|
||||
final String fileName = asset.file!.pathSegments.last;
|
||||
kernelAssetPath = KernelAssetAbsolutePath(frameworkUri(
|
||||
fileName,
|
||||
@ -111,11 +236,11 @@ KernelAsset _targetLocationIOS(
|
||||
///
|
||||
/// Code signing is also done here, so that it doesn't have to be done in
|
||||
/// in xcode_backend.dart.
|
||||
Future<void> copyNativeCodeAssetsIOS(
|
||||
Future<void> _copyNativeAssetsIOS(
|
||||
Uri buildUri,
|
||||
Map<KernelAssetPath, List<NativeCodeAssetImpl>> assetTargetLocations,
|
||||
Map<KernelAssetPath, List<AssetImpl>> assetTargetLocations,
|
||||
String? codesignIdentity,
|
||||
build_info.BuildMode buildMode,
|
||||
BuildMode buildMode,
|
||||
FileSystem fileSystem,
|
||||
) async {
|
||||
if (assetTargetLocations.isNotEmpty) {
|
||||
@ -125,12 +250,11 @@ Future<void> copyNativeCodeAssetsIOS(
|
||||
final Map<String, String> oldToNewInstallNames = <String, String>{};
|
||||
final List<(File, String, Directory)> dylibs = <(File, String, Directory)>[];
|
||||
|
||||
for (final MapEntry<KernelAssetPath, List<NativeCodeAssetImpl>> assetMapping
|
||||
for (final MapEntry<KernelAssetPath, List<AssetImpl>> assetMapping
|
||||
in assetTargetLocations.entries) {
|
||||
final Uri target = (assetMapping.key as KernelAssetAbsolutePath).uri;
|
||||
final List<File> sources = <File>[
|
||||
for (final NativeCodeAssetImpl source in assetMapping.value)
|
||||
fileSystem.file(source.file)
|
||||
for (final AssetImpl source in assetMapping.value) fileSystem.file(source.file)
|
||||
];
|
||||
final Uri targetUri = buildUri.resolveUri(target);
|
||||
final File dylibFile = fileSystem.file(targetUri);
|
||||
@ -141,8 +265,7 @@ Future<void> copyNativeCodeAssetsIOS(
|
||||
await lipoDylibs(dylibFile, sources);
|
||||
|
||||
final String dylibFileName = dylibFile.basename;
|
||||
final String newInstallName =
|
||||
'@rpath/$dylibFileName.framework/$dylibFileName';
|
||||
final String newInstallName = '@rpath/$dylibFileName.framework/$dylibFileName';
|
||||
final Set<String> oldInstallNames = await getInstallNamesDylib(dylibFile);
|
||||
for (final String oldInstallName in oldInstallNames) {
|
||||
oldToNewInstallNames[oldInstallName] = newInstallName;
|
||||
|
@ -2,12 +2,70 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:native_assets_builder/native_assets_builder.dart'
|
||||
hide NativeAssetsBuildRunner;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart';
|
||||
|
||||
import '../../../base/common.dart';
|
||||
import '../../../base/file_system.dart';
|
||||
import '../../../base/io.dart';
|
||||
import '../../../build_info.dart';
|
||||
import '../../../globals.dart' as globals;
|
||||
import '../native_assets.dart';
|
||||
|
||||
/// Dry run the native builds.
|
||||
///
|
||||
/// This does not build native assets, it only simulates what the final paths
|
||||
/// of all assets will be so that this can be embedded in the kernel file.
|
||||
Future<Uri?> dryRunNativeAssetsLinux({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
required Uri projectUri,
|
||||
bool flutterTester = false,
|
||||
required FileSystem fileSystem,
|
||||
}) {
|
||||
return dryRunNativeAssetsSingleArchitecture(
|
||||
buildRunner: buildRunner,
|
||||
projectUri: projectUri,
|
||||
flutterTester: flutterTester,
|
||||
fileSystem: fileSystem,
|
||||
os: OSImpl.linux,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Iterable<KernelAsset>> dryRunNativeAssetsLinuxInternal(
|
||||
FileSystem fileSystem,
|
||||
Uri projectUri,
|
||||
bool flutterTester,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) {
|
||||
return dryRunNativeAssetsSingleArchitectureInternal(
|
||||
fileSystem,
|
||||
projectUri,
|
||||
flutterTester,
|
||||
buildRunner,
|
||||
OSImpl.linux,
|
||||
);
|
||||
}
|
||||
|
||||
Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)> buildNativeAssetsLinux({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
TargetPlatform? targetPlatform,
|
||||
required Uri projectUri,
|
||||
required BuildMode buildMode,
|
||||
bool flutterTester = false,
|
||||
Uri? yamlParentDirectory,
|
||||
required FileSystem fileSystem,
|
||||
}) {
|
||||
return buildNativeAssetsSingleArchitecture(
|
||||
buildRunner: buildRunner,
|
||||
targetPlatform: targetPlatform,
|
||||
projectUri: projectUri,
|
||||
buildMode: buildMode,
|
||||
flutterTester: flutterTester,
|
||||
yamlParentDirectory: yamlParentDirectory,
|
||||
fileSystem: fileSystem,
|
||||
);
|
||||
}
|
||||
|
||||
/// Flutter expects `clang++` to be on the path on Linux hosts.
|
||||
///
|
||||
|
@ -2,21 +2,179 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:native_assets_builder/native_assets_builder.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli.dart';
|
||||
import 'package:native_assets_builder/native_assets_builder.dart'
|
||||
hide NativeAssetsBuildRunner;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart';
|
||||
|
||||
import '../../../base/file_system.dart';
|
||||
import '../../../build_info.dart' hide BuildMode;
|
||||
import '../../../build_info.dart' as build_info;
|
||||
import '../../../build_info.dart';
|
||||
import '../../../globals.dart' as globals;
|
||||
import '../native_assets.dart';
|
||||
import 'native_assets_host.dart';
|
||||
|
||||
// TODO(dcharkes): Fetch minimum MacOS version from somewhere. https://github.com/flutter/flutter/issues/145104
|
||||
const int targetMacOSVersion = 13;
|
||||
/// Dry run the native builds.
|
||||
///
|
||||
/// This does not build native assets, it only simulates what the final paths
|
||||
/// of all assets will be so that this can be embedded in the kernel file and
|
||||
/// the Xcode project.
|
||||
Future<Uri?> dryRunNativeAssetsMacOS({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
required Uri projectUri,
|
||||
bool flutterTester = false,
|
||||
required FileSystem fileSystem,
|
||||
}) async {
|
||||
if (!await nativeBuildRequired(buildRunner)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Uri buildUri = nativeAssetsBuildUri(projectUri, OSImpl.macOS);
|
||||
final Iterable<KernelAsset> nativeAssetPaths = await dryRunNativeAssetsMacOSInternal(
|
||||
fileSystem,
|
||||
projectUri,
|
||||
flutterTester,
|
||||
buildRunner,
|
||||
);
|
||||
final Uri nativeAssetsUri = await writeNativeAssetsYaml(
|
||||
KernelAssets(nativeAssetPaths),
|
||||
buildUri,
|
||||
fileSystem,
|
||||
);
|
||||
return nativeAssetsUri;
|
||||
}
|
||||
|
||||
Future<Iterable<KernelAsset>> dryRunNativeAssetsMacOSInternal(
|
||||
FileSystem fileSystem,
|
||||
Uri projectUri,
|
||||
bool flutterTester,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) async {
|
||||
const OSImpl targetOS = OSImpl.macOS;
|
||||
final Uri buildUri = nativeAssetsBuildUri(projectUri, targetOS);
|
||||
|
||||
globals.logger.printTrace('Dry running native assets for $targetOS.');
|
||||
final BuildDryRunResult buildDryRunResult = await buildRunner.buildDryRun(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
targetOS: targetOS,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
);
|
||||
ensureNativeAssetsBuildDryRunSucceed(buildDryRunResult);
|
||||
// No link hooks in JIT mode.
|
||||
final List<AssetImpl> nativeAssets = buildDryRunResult.assets;
|
||||
globals.logger.printTrace('Dry running native assets for $targetOS done.');
|
||||
final Uri? absolutePath = flutterTester ? buildUri : null;
|
||||
final Map<AssetImpl, KernelAsset> assetTargetLocations =
|
||||
_assetTargetLocations(
|
||||
nativeAssets,
|
||||
absolutePath,
|
||||
);
|
||||
return assetTargetLocations.values;
|
||||
}
|
||||
|
||||
/// Builds native assets.
|
||||
///
|
||||
/// If [darwinArchs] is omitted, the current target architecture is used.
|
||||
///
|
||||
/// If [flutterTester] is true, absolute paths are emitted in the native
|
||||
/// assets mapping. This can be used for JIT mode without sandbox on the host.
|
||||
/// This is used in `flutter test` and `flutter run -d flutter-tester`.
|
||||
Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)> buildNativeAssetsMacOS({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
List<DarwinArch>? darwinArchs,
|
||||
required Uri projectUri,
|
||||
required BuildMode buildMode,
|
||||
bool flutterTester = false,
|
||||
String? codesignIdentity,
|
||||
Uri? yamlParentDirectory,
|
||||
required FileSystem fileSystem,
|
||||
}) async {
|
||||
const OSImpl targetOS = OSImpl.macOS;
|
||||
final Uri buildUri = nativeAssetsBuildUri(projectUri, targetOS);
|
||||
if (!await nativeBuildRequired(buildRunner)) {
|
||||
final Uri nativeAssetsYaml = await writeNativeAssetsYaml(
|
||||
KernelAssets(),
|
||||
yamlParentDirectory ?? buildUri,
|
||||
fileSystem,
|
||||
);
|
||||
return (nativeAssetsYaml, <Uri>[]);
|
||||
}
|
||||
|
||||
final List<Target> targets = darwinArchs != null
|
||||
? darwinArchs.map(_getNativeTarget).toList()
|
||||
: <Target>[Target.current];
|
||||
final BuildModeImpl buildModeCli =
|
||||
nativeAssetsBuildMode(buildMode);
|
||||
final bool linkingEnabled = buildModeCli == BuildModeImpl.release;
|
||||
|
||||
globals.logger
|
||||
.printTrace('Building native assets for $targets $buildModeCli.');
|
||||
final List<AssetImpl> nativeAssets = <AssetImpl>[];
|
||||
final Set<Uri> dependencies = <Uri>{};
|
||||
for (final Target target in targets) {
|
||||
final BuildResult buildResult = await buildRunner.build(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
target: target,
|
||||
buildMode: buildModeCli,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
cCompilerConfig: await buildRunner.cCompilerConfig,
|
||||
// TODO(dcharkes): Fetch minimum MacOS version from somewhere. https://github.com/flutter/flutter/issues/145104
|
||||
targetMacOSVersion: 13,
|
||||
linkingEnabled: linkingEnabled,
|
||||
);
|
||||
ensureNativeAssetsBuildSucceed(buildResult);
|
||||
nativeAssets.addAll(buildResult.assets);
|
||||
dependencies.addAll(buildResult.dependencies);
|
||||
if (linkingEnabled) {
|
||||
final LinkResult linkResult = await buildRunner.link(
|
||||
linkModePreference: LinkModePreferenceImpl.dynamic,
|
||||
target: target,
|
||||
buildMode: buildModeCli,
|
||||
workingDirectory: projectUri,
|
||||
includeParentEnvironment: true,
|
||||
cCompilerConfig: await buildRunner.cCompilerConfig,
|
||||
buildResult: buildResult,
|
||||
// TODO(dcharkes): Fetch minimum MacOS version from somewhere. https://github.com/flutter/flutter/issues/145104
|
||||
targetMacOSVersion: 13,
|
||||
);
|
||||
ensureNativeAssetsLinkSucceed(linkResult);
|
||||
nativeAssets.addAll(linkResult.assets);
|
||||
dependencies.addAll(linkResult.dependencies);
|
||||
}
|
||||
}
|
||||
globals.logger.printTrace('Building native assets for $targets done.');
|
||||
final Uri? absolutePath = flutterTester ? buildUri : null;
|
||||
final Map<AssetImpl, KernelAsset> assetTargetLocations =
|
||||
_assetTargetLocations(nativeAssets, absolutePath);
|
||||
final Map<KernelAssetPath, List<AssetImpl>> fatAssetTargetLocations =
|
||||
_fatAssetTargetLocations(nativeAssets, absolutePath);
|
||||
if (flutterTester) {
|
||||
await _copyNativeAssetsMacOSFlutterTester(
|
||||
buildUri,
|
||||
fatAssetTargetLocations,
|
||||
codesignIdentity,
|
||||
buildMode,
|
||||
fileSystem,
|
||||
);
|
||||
} else {
|
||||
await _copyNativeAssetsMacOS(
|
||||
buildUri,
|
||||
fatAssetTargetLocations,
|
||||
codesignIdentity,
|
||||
buildMode,
|
||||
fileSystem,
|
||||
);
|
||||
}
|
||||
final Uri nativeAssetsUri = await writeNativeAssetsYaml(
|
||||
KernelAssets(assetTargetLocations.values),
|
||||
yamlParentDirectory ?? buildUri,
|
||||
fileSystem,
|
||||
);
|
||||
return (nativeAssetsUri, dependencies.toList());
|
||||
}
|
||||
|
||||
/// Extract the [Target] from a [DarwinArch].
|
||||
Target getNativeMacOSTarget(DarwinArch darwinArch) {
|
||||
Target _getNativeTarget(DarwinArch darwinArch) {
|
||||
return switch (darwinArch) {
|
||||
DarwinArch.arm64 => Target.macOSArm64,
|
||||
DarwinArch.x86_64 => Target.macOSX64,
|
||||
@ -24,15 +182,15 @@ Target getNativeMacOSTarget(DarwinArch darwinArch) {
|
||||
};
|
||||
}
|
||||
|
||||
Map<KernelAssetPath, List<NativeCodeAssetImpl>> fatAssetTargetLocationsMacOS(
|
||||
List<NativeCodeAssetImpl> nativeAssets,
|
||||
Map<KernelAssetPath, List<AssetImpl>> _fatAssetTargetLocations(
|
||||
List<AssetImpl> nativeAssets,
|
||||
Uri? absolutePath,
|
||||
) {
|
||||
final Set<String> alreadyTakenNames = <String>{};
|
||||
final Map<KernelAssetPath, List<NativeCodeAssetImpl>> result =
|
||||
<KernelAssetPath, List<NativeCodeAssetImpl>>{};
|
||||
final Map<KernelAssetPath, List<AssetImpl>> result =
|
||||
<KernelAssetPath, List<AssetImpl>>{};
|
||||
final Map<String, KernelAssetPath> idToPath = <String, KernelAssetPath>{};
|
||||
for (final NativeCodeAssetImpl asset in nativeAssets) {
|
||||
for (final AssetImpl asset in nativeAssets) {
|
||||
// Use same target path for all assets with the same id.
|
||||
final KernelAssetPath path = idToPath[asset.id] ??
|
||||
_targetLocationMacOS(
|
||||
@ -41,25 +199,25 @@ Map<KernelAssetPath, List<NativeCodeAssetImpl>> fatAssetTargetLocationsMacOS(
|
||||
alreadyTakenNames,
|
||||
).path;
|
||||
idToPath[asset.id] = path;
|
||||
result[path] ??= <NativeCodeAssetImpl>[];
|
||||
result[path] ??= <AssetImpl>[];
|
||||
result[path]!.add(asset);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<NativeCodeAssetImpl, KernelAsset> assetTargetLocationsMacOS(
|
||||
List<NativeCodeAssetImpl> nativeAssets,
|
||||
Map<AssetImpl, KernelAsset> _assetTargetLocations(
|
||||
List<AssetImpl> nativeAssets,
|
||||
Uri? absolutePath,
|
||||
) {
|
||||
final Set<String> alreadyTakenNames = <String>{};
|
||||
final Map<String, KernelAssetPath> idToPath = <String, KernelAssetPath>{};
|
||||
final Map<NativeCodeAssetImpl, KernelAsset> result = <NativeCodeAssetImpl, KernelAsset>{};
|
||||
for (final NativeCodeAssetImpl asset in nativeAssets) {
|
||||
final Map<AssetImpl, KernelAsset> result = <AssetImpl, KernelAsset>{};
|
||||
for (final AssetImpl asset in nativeAssets) {
|
||||
final KernelAssetPath path = idToPath[asset.id] ??
|
||||
_targetLocationMacOS(asset, absolutePath, alreadyTakenNames).path;
|
||||
idToPath[asset.id] = path;
|
||||
result[asset] = KernelAsset(
|
||||
id: asset.id,
|
||||
id: (asset as NativeCodeAssetImpl).id,
|
||||
target: Target.fromArchitectureAndOS(asset.architecture!, asset.os),
|
||||
path: path,
|
||||
);
|
||||
@ -68,20 +226,20 @@ Map<NativeCodeAssetImpl, KernelAsset> assetTargetLocationsMacOS(
|
||||
}
|
||||
|
||||
KernelAsset _targetLocationMacOS(
|
||||
NativeCodeAssetImpl asset,
|
||||
AssetImpl asset,
|
||||
Uri? absolutePath,
|
||||
Set<String> alreadyTakenNames,
|
||||
) {
|
||||
final LinkMode linkMode = asset.linkMode;
|
||||
final LinkModeImpl linkMode = (asset as NativeCodeAssetImpl).linkMode;
|
||||
final KernelAssetPath kernelAssetPath;
|
||||
switch (linkMode) {
|
||||
case DynamicLoadingSystem _:
|
||||
case DynamicLoadingSystemImpl _:
|
||||
kernelAssetPath = KernelAssetSystemPath(linkMode.uri);
|
||||
case LookupInExecutable _:
|
||||
case LookupInExecutableImpl _:
|
||||
kernelAssetPath = KernelAssetInExecutable();
|
||||
case LookupInProcess _:
|
||||
case LookupInProcessImpl _:
|
||||
kernelAssetPath = KernelAssetInProcess();
|
||||
case DynamicLoadingBundled _:
|
||||
case DynamicLoadingBundledImpl _:
|
||||
final String fileName = asset.file!.pathSegments.last;
|
||||
Uri uri;
|
||||
if (absolutePath != null) {
|
||||
@ -121,11 +279,11 @@ KernelAsset _targetLocationMacOS(
|
||||
///
|
||||
/// Code signing is also done here, so that it doesn't have to be done in
|
||||
/// in macos_assemble.sh.
|
||||
Future<void> copyNativeCodeAssetsMacOS(
|
||||
Future<void> _copyNativeAssetsMacOS(
|
||||
Uri buildUri,
|
||||
Map<KernelAssetPath, List<NativeCodeAssetImpl>> assetTargetLocations,
|
||||
Map<KernelAssetPath, List<AssetImpl>> assetTargetLocations,
|
||||
String? codesignIdentity,
|
||||
build_info.BuildMode buildMode,
|
||||
BuildMode buildMode,
|
||||
FileSystem fileSystem,
|
||||
) async {
|
||||
if (assetTargetLocations.isNotEmpty) {
|
||||
@ -136,11 +294,11 @@ Future<void> copyNativeCodeAssetsMacOS(
|
||||
final Map<String, String> oldToNewInstallNames = <String, String>{};
|
||||
final List<(File, String, Directory)> dylibs = <(File, String, Directory)>[];
|
||||
|
||||
for (final MapEntry<KernelAssetPath, List<NativeCodeAssetImpl>> assetMapping
|
||||
for (final MapEntry<KernelAssetPath, List<AssetImpl>> assetMapping
|
||||
in assetTargetLocations.entries) {
|
||||
final Uri target = (assetMapping.key as KernelAssetAbsolutePath).uri;
|
||||
final List<File> sources = <File>[
|
||||
for (final NativeCodeAssetImpl source in assetMapping.value) fileSystem.file(source.file),
|
||||
for (final AssetImpl source in assetMapping.value) fileSystem.file(source.file),
|
||||
];
|
||||
final Uri targetUri = buildUri.resolveUri(target);
|
||||
final String name = targetUri.pathSegments.last;
|
||||
@ -215,11 +373,11 @@ Future<void> copyNativeCodeAssetsMacOS(
|
||||
/// so that the referenced library can be found the dynamic linker.
|
||||
///
|
||||
/// Code signing is also done here.
|
||||
Future<void> copyNativeCodeAssetsMacOSFlutterTester(
|
||||
Future<void> _copyNativeAssetsMacOSFlutterTester(
|
||||
Uri buildUri,
|
||||
Map<KernelAssetPath, List<NativeCodeAssetImpl>> assetTargetLocations,
|
||||
Map<KernelAssetPath, List<AssetImpl>> assetTargetLocations,
|
||||
String? codesignIdentity,
|
||||
build_info.BuildMode buildMode,
|
||||
BuildMode buildMode,
|
||||
FileSystem fileSystem,
|
||||
) async {
|
||||
if (assetTargetLocations.isNotEmpty) {
|
||||
@ -230,11 +388,11 @@ Future<void> copyNativeCodeAssetsMacOSFlutterTester(
|
||||
final Map<String, String> oldToNewInstallNames = <String, String>{};
|
||||
final List<(File, String)> dylibs = <(File, String)>[];
|
||||
|
||||
for (final MapEntry<KernelAssetPath, List<NativeCodeAssetImpl>> assetMapping
|
||||
for (final MapEntry<KernelAssetPath, List<AssetImpl>> assetMapping
|
||||
in assetTargetLocations.entries) {
|
||||
final Uri target = (assetMapping.key as KernelAssetAbsolutePath).uri;
|
||||
final List<File> sources = <File>[
|
||||
for (final NativeCodeAssetImpl source in assetMapping.value) fileSystem.file(source.file),
|
||||
for (final AssetImpl source in assetMapping.value) fileSystem.file(source.file),
|
||||
];
|
||||
final Uri targetUri = buildUri.resolveUri(target);
|
||||
final File dylibFile = fileSystem.file(targetUri);
|
||||
|
@ -4,13 +4,13 @@
|
||||
|
||||
// Shared logic between iOS and macOS implementations of native assets.
|
||||
|
||||
import 'package:native_assets_cli/native_assets_cli.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli.dart' show Architecture;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart';
|
||||
|
||||
import '../../../base/common.dart';
|
||||
import '../../../base/file_system.dart';
|
||||
import '../../../base/io.dart';
|
||||
import '../../../build_info.dart' as build_info;
|
||||
import '../../../build_info.dart';
|
||||
import '../../../convert.dart';
|
||||
import '../../../globals.dart' as globals;
|
||||
|
||||
@ -99,13 +99,13 @@ Future<void> setInstallNamesDylib(
|
||||
String newInstallName,
|
||||
Map<String, String> oldToNewInstallNames,
|
||||
) async {
|
||||
final ProcessResult setInstallNamesResult = await globals.processManager.run(
|
||||
final ProcessResult setInstallNamesResult = await globals.processManager.run(
|
||||
<String>[
|
||||
'install_name_tool',
|
||||
'-id',
|
||||
newInstallName,
|
||||
for (final MapEntry<String, String> entry in oldToNewInstallNames
|
||||
.entries) ...<String>['-change', entry.key, entry.value],
|
||||
for (final MapEntry<String, String> entry in oldToNewInstallNames.entries)
|
||||
...<String>['-change', entry.key, entry.value],
|
||||
dylibFile.path,
|
||||
],
|
||||
);
|
||||
@ -135,16 +135,18 @@ Future<Set<String>> getInstallNamesDylib(File dylibFile) async {
|
||||
|
||||
return <String>{
|
||||
for (final List<String> architectureSection
|
||||
in parseOtoolArchitectureSections(installNameResult.stdout as String).values)
|
||||
in parseOtoolArchitectureSections(installNameResult.stdout as String).values)
|
||||
// For each architecture, a separate install name is reported, which are
|
||||
// not necessarily the same.
|
||||
architectureSection.single,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future<void> codesignDylib(
|
||||
String? codesignIdentity,
|
||||
build_info.BuildMode buildMode,
|
||||
BuildMode buildMode,
|
||||
FileSystemEntity target,
|
||||
) async {
|
||||
if (codesignIdentity == null || codesignIdentity.isEmpty) {
|
||||
@ -155,7 +157,7 @@ Future<void> codesignDylib(
|
||||
'--force',
|
||||
'--sign',
|
||||
codesignIdentity,
|
||||
if (buildMode != build_info.BuildMode.release) ...<String>[
|
||||
if (buildMode != BuildMode.release) ...<String>[
|
||||
// Mimic Xcode's timestamp codesigning behavior on non-release binaries.
|
||||
'--timestamp=none',
|
||||
],
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,12 +6,16 @@
|
||||
|
||||
import 'package:native_assets_cli/native_assets_cli.dart';
|
||||
|
||||
import '../../../base/os.dart';
|
||||
import '../../../base/platform.dart';
|
||||
import '../../../build_info.dart';
|
||||
import '../../../globals.dart' as globals;
|
||||
import '../../../native_assets.dart';
|
||||
import '../../../project.dart';
|
||||
import '../linux/native_assets.dart';
|
||||
import '../macos/native_assets.dart';
|
||||
import '../native_assets.dart';
|
||||
import '../windows/native_assets.dart';
|
||||
|
||||
class TestCompilerNativeAssetsBuilderImpl
|
||||
implements TestCompilerNativeAssetsBuilder {
|
||||
@ -27,36 +31,57 @@ class TestCompilerNativeAssetsBuilderImpl
|
||||
}
|
||||
|
||||
Future<Uri?> testCompilerBuildNativeAssets(BuildInfo buildInfo) async {
|
||||
Uri? nativeAssetsYaml;
|
||||
if (!buildInfo.buildNativeAssets) {
|
||||
return null;
|
||||
}
|
||||
final Uri projectUri = FlutterProject.current().directory.uri;
|
||||
final FlutterNativeAssetsBuildRunner buildRunner = FlutterNativeAssetsBuildRunnerImpl(
|
||||
projectUri,
|
||||
buildInfo.packageConfigPath,
|
||||
buildInfo.packageConfig,
|
||||
globals.fs,
|
||||
globals.logger,
|
||||
);
|
||||
|
||||
if (!globals.platform.isMacOS &&
|
||||
!globals.platform.isLinux &&
|
||||
!globals.platform.isWindows) {
|
||||
await ensureNoNativeAssetsOrOsIsSupported(
|
||||
nativeAssetsYaml = null;
|
||||
} else {
|
||||
final Uri projectUri = FlutterProject.current().directory.uri;
|
||||
final NativeAssetsBuildRunner buildRunner = NativeAssetsBuildRunnerImpl(
|
||||
projectUri,
|
||||
const LocalPlatform().operatingSystem,
|
||||
buildInfo.packageConfigPath,
|
||||
buildInfo.packageConfig,
|
||||
globals.fs,
|
||||
buildRunner,
|
||||
globals.logger,
|
||||
);
|
||||
return null;
|
||||
if (globals.platform.isMacOS) {
|
||||
(nativeAssetsYaml, _) = await buildNativeAssetsMacOS(
|
||||
buildMode: buildInfo.mode,
|
||||
projectUri: projectUri,
|
||||
flutterTester: true,
|
||||
fileSystem: globals.fs,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
} else if (globals.platform.isLinux) {
|
||||
(nativeAssetsYaml, _) = await buildNativeAssetsLinux(
|
||||
buildMode: buildInfo.mode,
|
||||
projectUri: projectUri,
|
||||
flutterTester: true,
|
||||
fileSystem: globals.fs,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
} else if (globals.platform.isWindows) {
|
||||
final TargetPlatform targetPlatform;
|
||||
if (globals.os.hostPlatform == HostPlatform.windows_x64) {
|
||||
targetPlatform = TargetPlatform.windows_x64;
|
||||
} else {
|
||||
targetPlatform = TargetPlatform.windows_arm64;
|
||||
}
|
||||
(nativeAssetsYaml, _) = await buildNativeAssetsWindows(
|
||||
buildMode: buildInfo.mode,
|
||||
targetPlatform: targetPlatform,
|
||||
projectUri: projectUri,
|
||||
flutterTester: true,
|
||||
fileSystem: globals.fs,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
} else {
|
||||
await ensureNoNativeAssetsOrOsIsSupported(
|
||||
projectUri,
|
||||
const LocalPlatform().operatingSystem,
|
||||
globals.fs,
|
||||
buildRunner,
|
||||
);
|
||||
}
|
||||
}
|
||||
final (_, Uri nativeAssetsYaml) = await runFlutterSpecificDartBuild(
|
||||
environmentDefines: <String, String>{
|
||||
kBuildMode: buildInfo.mode.cliName,
|
||||
},
|
||||
buildRunner: buildRunner,
|
||||
targetPlatform: TargetPlatform.tester,
|
||||
projectUri: projectUri,
|
||||
fileSystem: globals.fs);
|
||||
return nativeAssetsYaml;
|
||||
}
|
||||
|
@ -2,10 +2,70 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:native_assets_builder/native_assets_builder.dart'
|
||||
hide NativeAssetsBuildRunner;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart';
|
||||
|
||||
import '../../../base/file_system.dart';
|
||||
import '../../../build_info.dart';
|
||||
import '../../../globals.dart' as globals;
|
||||
import '../../../windows/visual_studio.dart';
|
||||
import '../native_assets.dart';
|
||||
|
||||
/// Dry run the native builds.
|
||||
///
|
||||
/// This does not build native assets, it only simulates what the final paths
|
||||
/// of all assets will be so that this can be embedded in the kernel file.
|
||||
Future<Uri?> dryRunNativeAssetsWindows({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
required Uri projectUri,
|
||||
bool flutterTester = false,
|
||||
required FileSystem fileSystem,
|
||||
}) {
|
||||
return dryRunNativeAssetsSingleArchitecture(
|
||||
buildRunner: buildRunner,
|
||||
projectUri: projectUri,
|
||||
flutterTester: flutterTester,
|
||||
fileSystem: fileSystem,
|
||||
os: OSImpl.windows,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Iterable<KernelAsset>> dryRunNativeAssetsWindowsInternal(
|
||||
FileSystem fileSystem,
|
||||
Uri projectUri,
|
||||
bool flutterTester,
|
||||
NativeAssetsBuildRunner buildRunner,
|
||||
) {
|
||||
return dryRunNativeAssetsSingleArchitectureInternal(
|
||||
fileSystem,
|
||||
projectUri,
|
||||
flutterTester,
|
||||
buildRunner,
|
||||
OSImpl.windows,
|
||||
);
|
||||
}
|
||||
|
||||
Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)>
|
||||
buildNativeAssetsWindows({
|
||||
required NativeAssetsBuildRunner buildRunner,
|
||||
TargetPlatform? targetPlatform,
|
||||
required Uri projectUri,
|
||||
required BuildMode buildMode,
|
||||
bool flutterTester = false,
|
||||
Uri? yamlParentDirectory,
|
||||
required FileSystem fileSystem,
|
||||
}) {
|
||||
return buildNativeAssetsSingleArchitecture(
|
||||
buildRunner: buildRunner,
|
||||
targetPlatform: targetPlatform,
|
||||
projectUri: projectUri,
|
||||
buildMode: buildMode,
|
||||
flutterTester: flutterTester,
|
||||
yamlParentDirectory: yamlParentDirectory,
|
||||
fileSystem: fileSystem,
|
||||
);
|
||||
}
|
||||
|
||||
Future<CCompilerConfigImpl> cCompilerConfigWindows() async {
|
||||
final VisualStudio visualStudio = VisualStudio(
|
||||
|
@ -5,7 +5,6 @@
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:file_testing/file_testing.dart';
|
||||
import 'package:flutter_tools/src/android/gradle_utils.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
@ -15,7 +14,7 @@ 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:flutter_tools/src/isolated/native_assets/android/native_assets.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart';
|
||||
import 'package:package_config/package_config_types.dart';
|
||||
|
||||
@ -49,6 +48,173 @@ void main() {
|
||||
projectUri = environment.projectDir.uri;
|
||||
});
|
||||
|
||||
testUsingContext('dry run with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
expect(
|
||||
await dryRunNativeAssetsAndroid(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 {
|
||||
await buildNativeAssetsAndroid(
|
||||
androidArchs: <AndroidArch>[AndroidArch.arm64_v8a],
|
||||
targetAndroidNdkApi: 21,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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(
|
||||
() => dryRunNativeAssetsAndroid(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.macOS,
|
||||
architecture: ArchitectureImpl.arm64,
|
||||
file: Uri.file('libbar.so'),
|
||||
),
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.macOS,
|
||||
architecture: ArchitectureImpl.x64,
|
||||
file: Uri.file('libbar.so'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
final Uri? nativeAssetsYaml = await dryRunNativeAssetsAndroid(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Dry running native assets for android.',
|
||||
'Dry running native assets for android done.',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/android/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
contains('package:bar/bar.dart'),
|
||||
);
|
||||
expect(buildRunner.buildDryRunInvocations, 1);
|
||||
expect(buildRunner.linkDryRunInvocations, 0);
|
||||
});
|
||||
|
||||
testUsingContext('build with assets but not enabled', () async {
|
||||
final File packageConfig = environment.projectDir.childFile('.dart_tool/package_config.json');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => buildNativeAssetsAndroid(
|
||||
androidArchs: <AndroidArch>[AndroidArch.arm64_v8a],
|
||||
targetAndroidNdkApi: 21,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
await buildNativeAssetsAndroid(
|
||||
androidArchs: <AndroidArch>[AndroidArch.arm64_v8a],
|
||||
targetAndroidNdkApi: 21,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
),
|
||||
);
|
||||
expect(
|
||||
environment.buildDir.childFile('native_assets.yaml'),
|
||||
exists,
|
||||
);
|
||||
});
|
||||
|
||||
for (final BuildMode buildMode in <BuildMode>[
|
||||
BuildMode.debug,
|
||||
BuildMode.release,
|
||||
@ -61,17 +227,17 @@ void main() {
|
||||
}, () 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 File dylibAfterCompiling = fileSystem.file('libbar.so');
|
||||
// The mock doesn't create the file, so create it here.
|
||||
await dylibAfterCompiling.create();
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
final FakeNativeAssetsBuildRunner buildRunner =
|
||||
FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildResult: FakeFlutterNativeAssetsBuilderResult(
|
||||
buildResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
@ -83,25 +249,22 @@ void main() {
|
||||
],
|
||||
),
|
||||
);
|
||||
await runFlutterSpecificDartBuild(
|
||||
environmentDefines: <String, String>{
|
||||
kBuildMode: buildMode.cliName,
|
||||
kMinSdkVersion: minSdkVersion,
|
||||
},
|
||||
targetPlatform: TargetPlatform.android_arm64,
|
||||
await buildNativeAssetsAndroid(
|
||||
androidArchs: <AndroidArch>[AndroidArch.arm64_v8a],
|
||||
targetAndroidNdkApi: 21,
|
||||
projectUri: projectUri,
|
||||
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
||||
buildMode: buildMode,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Building native assets for android_arm64 $buildMode.',
|
||||
'Building native assets for android_arm64 $buildMode done.',
|
||||
'Building native assets for [android_arm64] $buildMode.',
|
||||
'Building native assets for [android_arm64] done.',
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
environment.buildDir.childFile('native_assets.yaml'),
|
||||
exists,
|
||||
@ -124,16 +287,12 @@ void main() {
|
||||
}, () async {
|
||||
final File packageConfig =
|
||||
environment.projectDir.childFile('.dart_tool/package_config.json');
|
||||
final Uri nonFlutterTesterAssetUri = environment.buildDir.childFile('native_assets.yaml').uri;
|
||||
await packageConfig.create(recursive: true);
|
||||
await runFlutterSpecificDartBuild(
|
||||
environmentDefines: <String, String>{
|
||||
kBuildMode: BuildMode.debug.cliName,
|
||||
kMinSdkVersion: minSdkVersion,
|
||||
},
|
||||
targetPlatform: TargetPlatform.android_x64,
|
||||
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
||||
await buildNativeAssetsAndroid(
|
||||
androidArchs: <AndroidArch>[AndroidArch.x86_64],
|
||||
targetAndroidNdkApi: 21,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: _BuildRunnerWithoutNdk(),
|
||||
);
|
||||
@ -149,19 +308,16 @@ void main() {
|
||||
}, () 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,
|
||||
kMinSdkVersion: minSdkVersion,
|
||||
},
|
||||
targetPlatform: TargetPlatform.android_arm64,
|
||||
() => buildNativeAssetsAndroid(
|
||||
androidArchs: <AndroidArch>[AndroidArch.arm64_v8a],
|
||||
targetAndroidNdkApi: 21,
|
||||
projectUri: projectUri,
|
||||
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: _BuildRunnerWithoutNdk(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
@ -174,9 +330,73 @@ 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(
|
||||
() => dryRunNativeAssetsAndroid(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: const FakeNativeAssetsBuilderResult(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
for (final String hook in <String>['Building', 'Linking']) {
|
||||
expect(
|
||||
() => buildNativeAssetsAndroid(
|
||||
androidArchs: <AndroidArch>[AndroidArch.arm64_v8a],
|
||||
targetAndroidNdkApi: 21,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.release,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildResult: FakeNativeAssetsBuilderResult(
|
||||
success: hook != 'Building',
|
||||
),
|
||||
linkResult: FakeNativeAssetsBuilderResult(
|
||||
success: hook != 'Linking',
|
||||
),
|
||||
),
|
||||
),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'$hook native assets failed. See the logs for more details.',
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class _BuildRunnerWithoutNdk extends FakeFlutterNativeAssetsBuildRunner {
|
||||
class _BuildRunnerWithoutNdk extends FakeNativeAssetsBuildRunner {
|
||||
_BuildRunnerWithoutNdk({
|
||||
super.packagesWithNativeAssetsResult = const <Package>[],
|
||||
});
|
||||
|
@ -76,29 +76,21 @@ void main() {
|
||||
|
||||
iosEnvironment.defines.remove(kIosArchs);
|
||||
|
||||
final FlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner();
|
||||
final NativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner();
|
||||
await NativeAssets(buildRunner: buildRunner).build(iosEnvironment);
|
||||
|
||||
final File nativeAssetsYaml =
|
||||
iosEnvironment.buildDir.childFile('native_assets.yaml');
|
||||
|
||||
final File depsFile = iosEnvironment.buildDir.childFile('native_assets.d');
|
||||
expect(depsFile, exists);
|
||||
expect(nativeAssetsYaml, exists);
|
||||
});
|
||||
|
||||
testUsingContext('NativeAssets throws error if missing sdk root', overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
}, () async {
|
||||
testUsingContext('NativeAssets throws error if missing sdk root', () async {
|
||||
await createPackageConfig(iosEnvironment);
|
||||
|
||||
final FlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('foo', iosEnvironment.projectDir.uri),
|
||||
]);
|
||||
|
||||
iosEnvironment.defines.remove(kSdkRoot);
|
||||
expect(NativeAssets(buildRunner: buildRunner).build(iosEnvironment), throwsA(isA<MissingDefineException>()));
|
||||
expect(const NativeAssets().build(iosEnvironment), throwsA(isA<MissingDefineException>()));
|
||||
});
|
||||
|
||||
// The NativeAssets Target should _always_ be creating a yaml an d file.
|
||||
@ -117,7 +109,7 @@ void main() {
|
||||
() async {
|
||||
await createPackageConfig(iosEnvironment);
|
||||
|
||||
final FlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner();
|
||||
final NativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner();
|
||||
await NativeAssets(buildRunner: buildRunner).build(iosEnvironment);
|
||||
|
||||
expect(iosEnvironment.buildDir.childFile('native_assets.d'), exists);
|
||||
@ -190,9 +182,9 @@ void main() {
|
||||
() async {
|
||||
await createPackageConfig(iosEnvironment);
|
||||
|
||||
final FlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
final NativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[Package('foo', iosEnvironment.buildDir.uri)],
|
||||
buildResult: FakeFlutterNativeAssetsBuilderResult(
|
||||
buildResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <native_assets_cli.AssetImpl>[
|
||||
native_assets_cli.NativeCodeAssetImpl(
|
||||
id: 'package:foo/foo.dart',
|
||||
@ -251,11 +243,11 @@ void main() {
|
||||
await createPackageConfig(androidEnvironment);
|
||||
await fileSystem.file('libfoo.so').create();
|
||||
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
final FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('foo', androidEnvironment.buildDir.uri)
|
||||
],
|
||||
buildResult: FakeFlutterNativeAssetsBuilderResult(
|
||||
buildResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <native_assets_cli.AssetImpl>[
|
||||
if (hasAssets)
|
||||
native_assets_cli.NativeCodeAssetImpl(
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
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';
|
||||
@ -15,15 +14,15 @@ import 'package:package_config/package_config_types.dart';
|
||||
|
||||
/// Mocks all logic instead of using `package:native_assets_builder`, which
|
||||
/// relies on doing process calls to `pub` and the local file system.
|
||||
class FakeFlutterNativeAssetsBuildRunner implements FlutterNativeAssetsBuildRunner {
|
||||
FakeFlutterNativeAssetsBuildRunner({
|
||||
class FakeNativeAssetsBuildRunner implements NativeAssetsBuildRunner {
|
||||
FakeNativeAssetsBuildRunner({
|
||||
this.hasPackageConfigResult = true,
|
||||
this.packagesWithNativeAssetsResult = const <Package>[],
|
||||
this.onBuild,
|
||||
this.buildDryRunResult = const FakeFlutterNativeAssetsBuilderResult(),
|
||||
this.buildResult = const FakeFlutterNativeAssetsBuilderResult(),
|
||||
this.linkResult = const FakeFlutterNativeAssetsBuilderResult(),
|
||||
this.linkDryRunResult = const FakeFlutterNativeAssetsBuilderResult(),
|
||||
this.buildDryRunResult = const FakeNativeAssetsBuilderResult(),
|
||||
this.buildResult = const FakeNativeAssetsBuilderResult(),
|
||||
this.linkResult = const FakeNativeAssetsBuilderResult(),
|
||||
this.linkDryRunResult = const FakeNativeAssetsBuilderResult(),
|
||||
CCompilerConfigImpl? cCompilerConfigResult,
|
||||
CCompilerConfigImpl? ndkCCompilerConfigImplResult,
|
||||
}) : cCompilerConfigResult = cCompilerConfigResult ?? CCompilerConfigImpl(),
|
||||
@ -97,6 +96,18 @@ class FakeFlutterNativeAssetsBuildRunner implements FlutterNativeAssetsBuildRunn
|
||||
return buildDryRunResult;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<native_assets_builder.LinkDryRunResult> linkDryRun({
|
||||
required bool includeParentEnvironment,
|
||||
required LinkModePreferenceImpl linkModePreference,
|
||||
required OSImpl targetOS,
|
||||
required Uri workingDirectory,
|
||||
required native_assets_builder.BuildDryRunResult buildDryRunResult,
|
||||
}) async {
|
||||
linkDryRunInvocations++;
|
||||
return linkDryRunResult;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> hasPackageConfig() async {
|
||||
hasPackageConfigInvocations++;
|
||||
@ -118,13 +129,13 @@ class FakeFlutterNativeAssetsBuildRunner implements FlutterNativeAssetsBuildRunn
|
||||
cCompilerConfigResult;
|
||||
}
|
||||
|
||||
final class FakeFlutterNativeAssetsBuilderResult
|
||||
final class FakeNativeAssetsBuilderResult
|
||||
implements
|
||||
native_assets_builder.BuildResult,
|
||||
native_assets_builder.BuildDryRunResult,
|
||||
native_assets_builder.LinkResult,
|
||||
native_assets_builder.LinkDryRunResult {
|
||||
const FakeFlutterNativeAssetsBuilderResult({
|
||||
const FakeNativeAssetsBuilderResult({
|
||||
this.assets = const <AssetImpl>[],
|
||||
this.assetsForLinking = const <String, List<AssetImpl>>{},
|
||||
this.dependencies = const <Uri>[],
|
||||
@ -147,7 +158,7 @@ final class FakeFlutterNativeAssetsBuilderResult
|
||||
class FakeHotRunnerNativeAssetsBuilder implements HotRunnerNativeAssetsBuilder {
|
||||
FakeHotRunnerNativeAssetsBuilder(this.buildRunner);
|
||||
|
||||
final FlutterNativeAssetsBuildRunner buildRunner;
|
||||
final NativeAssetsBuildRunner buildRunner;
|
||||
|
||||
@override
|
||||
Future<Uri?> dryRun({
|
||||
@ -158,15 +169,11 @@ class FakeHotRunnerNativeAssetsBuilder implements HotRunnerNativeAssetsBuilder {
|
||||
required PackageConfig packageConfig,
|
||||
required Logger logger,
|
||||
}) {
|
||||
final List<TargetPlatform> targetPlatforms = flutterDevices
|
||||
.map((FlutterDevice d) => d.targetPlatform)
|
||||
.nonNulls
|
||||
.toList();
|
||||
return runFlutterSpecificDartDryRunOnPlatforms(
|
||||
return dryRunNativeAssets(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
targetPlatforms: targetPlatforms,
|
||||
flutterDevices: flutterDevices,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -58,11 +58,11 @@ void main() {
|
||||
|
||||
(fakeFlutterDevice.devFS! as FakeDevFs).baseUri = Uri.parse('file:///base_uri');
|
||||
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
final FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', fileSystem.currentDirectory.uri),
|
||||
],
|
||||
buildDryRunResult: FakeFlutterNativeAssetsBuilderResult(
|
||||
buildDryRunResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
@ -127,11 +127,11 @@ void main() {
|
||||
|
||||
(fakeFlutterDevice.devFS! as FakeDevFs).baseUri = Uri.parse('file:///base_uri');
|
||||
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
final FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', fileSystem.currentDirectory.uri),
|
||||
],
|
||||
buildDryRunResult: FakeFlutterNativeAssetsBuilderResult(
|
||||
buildDryRunResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
|
@ -13,8 +13,9 @@ 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' hide Target;
|
||||
import 'package:flutter_tools/src/isolated/native_assets/ios/native_assets.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart'
|
||||
hide Target;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart'
|
||||
as native_assets_cli;
|
||||
import 'package:package_config/package_config_types.dart';
|
||||
@ -49,6 +50,174 @@ void main() {
|
||||
projectUri = environment.projectDir.uri;
|
||||
});
|
||||
|
||||
testUsingContext('dry run with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
expect(
|
||||
await dryRunNativeAssetsIOS(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 {
|
||||
await buildNativeAssetsIOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64],
|
||||
environmentType: EnvironmentType.simulator,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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(
|
||||
() => dryRunNativeAssetsIOS(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.macOS,
|
||||
architecture: ArchitectureImpl.arm64,
|
||||
file: Uri.file('libbar.dylib'),
|
||||
),
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.macOS,
|
||||
architecture: ArchitectureImpl.x64,
|
||||
file: Uri.file('libbar.dylib'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
final Uri? nativeAssetsYaml = await dryRunNativeAssetsIOS(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Dry running native assets for ios.',
|
||||
'Dry running native assets for ios done.',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/ios/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
contains('package:bar/bar.dart'),
|
||||
);
|
||||
expect(buildRunner.buildDryRunInvocations, 1);
|
||||
expect(buildRunner.linkDryRunInvocations, 0);
|
||||
});
|
||||
|
||||
testUsingContext('build with assets but not enabled', () async {
|
||||
final File packageConfig = environment.projectDir.childFile('.dart_tool/package_config.json');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => buildNativeAssetsIOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64],
|
||||
environmentType: EnvironmentType.simulator,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
await buildNativeAssetsIOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64],
|
||||
environmentType: EnvironmentType.simulator,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
),
|
||||
);
|
||||
expect(
|
||||
environment.buildDir.childFile('native_assets.yaml'),
|
||||
exists,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
for (final BuildMode buildMode in <BuildMode>[
|
||||
BuildMode.debug,
|
||||
BuildMode.release,
|
||||
@ -161,15 +330,15 @@ void main() {
|
||||
}
|
||||
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 FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
final FakeNativeAssetsBuildRunner buildRunner =
|
||||
FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
onBuild: (native_assets_cli.Target target) =>
|
||||
FakeFlutterNativeAssetsBuilderResult(
|
||||
FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
@ -186,25 +355,22 @@ void main() {
|
||||
file: Uri.file('${target.architecture}/libbuz.dylib'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
await runFlutterSpecificDartBuild(
|
||||
environmentDefines: <String, String>{
|
||||
kBuildMode: buildMode.cliName,
|
||||
kSdkRoot: '.../iPhone Simulator',
|
||||
kIosArchs: 'arm64 x86_64',
|
||||
},
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
await buildNativeAssetsIOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64, DarwinArch.x86_64],
|
||||
environmentType: EnvironmentType.simulator,
|
||||
projectUri: projectUri,
|
||||
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
||||
buildMode: buildMode,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Building native assets for [ios_arm64, ios_x64] $buildMode.',
|
||||
'Building native assets for [ios_arm64, ios_x64] $buildMode done.',
|
||||
'Building native assets for [ios_arm64, ios_x64] done.',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
@ -219,4 +385,69 @@ 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(
|
||||
() => dryRunNativeAssetsIOS(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: const FakeNativeAssetsBuilderResult(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
for (final String hook in <String>['Building', 'Linking']) {
|
||||
expect(
|
||||
() => buildNativeAssetsIOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64],
|
||||
environmentType: EnvironmentType.simulator,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.release,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildResult: FakeNativeAssetsBuilderResult(
|
||||
success: hook != 'Building',
|
||||
),
|
||||
linkResult: FakeNativeAssetsBuilderResult(
|
||||
success: hook != 'Linking',
|
||||
),
|
||||
),
|
||||
),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'$hook native assets failed. See the logs for more details.',
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
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/common.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
@ -14,6 +15,7 @@ import 'package:flutter_tools/src/build_system/build_system.dart';
|
||||
import 'package:flutter_tools/src/dart/package_map.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/linux/native_assets.dart';
|
||||
import 'package:flutter_tools/src/isolated/native_assets/native_assets.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart'
|
||||
hide Target;
|
||||
@ -49,21 +51,51 @@ void main() {
|
||||
projectUri = environment.projectDir.uri;
|
||||
});
|
||||
|
||||
testUsingContext('dry run with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
expect(
|
||||
await dryRunNativeAssetsLinux(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 {
|
||||
await buildNativeAssetsLinux(
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
hasPackageConfigResult: false,
|
||||
),
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
contains('No package config found. Skipping native assets compilation.'),
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('does not throw if clang not present but no native assets present', 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.create(recursive: true);
|
||||
|
||||
await runFlutterSpecificDartBuild(
|
||||
environmentDefines: <String, String>{
|
||||
kBuildMode: BuildMode.debug.cliName,
|
||||
},
|
||||
targetPlatform: TargetPlatform.linux_x64,
|
||||
await buildNativeAssetsLinux(
|
||||
projectUri: projectUri,
|
||||
nativeAssetsYamlUri: nonFlutterTesterAssetUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: _BuildRunnerWithoutClang(),
|
||||
);
|
||||
@ -73,6 +105,300 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('dry run for multiple OSes with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
await dryRunNativeAssetsMultipleOSes(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetPlatforms: <TargetPlatform>[
|
||||
TargetPlatform.darwin,
|
||||
TargetPlatform.ios,
|
||||
],
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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(
|
||||
() => dryRunNativeAssetsLinux(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.linux,
|
||||
architecture: ArchitectureImpl.x64,
|
||||
file: Uri.file('libbar.so'),
|
||||
),
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.linux,
|
||||
architecture: ArchitectureImpl.arm64,
|
||||
file: Uri.file('libbar.so'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
final Uri? nativeAssetsYaml = await dryRunNativeAssetsLinux(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Dry running native assets for linux.',
|
||||
'Dry running native assets for linux done.',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/linux/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
contains('package:bar/bar.dart'),
|
||||
);
|
||||
expect(buildRunner.buildDryRunInvocations, 1);
|
||||
expect(buildRunner.linkDryRunInvocations, 0);
|
||||
});
|
||||
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => buildNativeAssetsLinux(
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
final (Uri? nativeAssetsYaml, _) = await buildNativeAssetsLinux(
|
||||
targetPlatform: TargetPlatform.linux_x64,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/linux/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
isNot(contains('package:bar/bar.dart')),
|
||||
);
|
||||
expect(
|
||||
environment.projectDir
|
||||
.childDirectory('build')
|
||||
.childDirectory('native_assets')
|
||||
.childDirectory('linux'),
|
||||
exists,
|
||||
);
|
||||
});
|
||||
|
||||
for (final bool flutterTester in <bool>[false, true]) {
|
||||
String testName = '';
|
||||
if (flutterTester) {
|
||||
testName += ' flutter tester';
|
||||
}
|
||||
for (final BuildMode buildMode in <BuildMode>[
|
||||
BuildMode.debug,
|
||||
BuildMode.release,
|
||||
]) {
|
||||
testUsingContext('build with assets $buildMode$testName',
|
||||
overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
final File packageConfig = environment.projectDir
|
||||
.childDirectory('.dart_tool')
|
||||
.childFile('package_config.json');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
final File dylibAfterCompiling = fileSystem.file('libbar.so');
|
||||
// The mock doesn't create the file, so create it here.
|
||||
await dylibAfterCompiling.create();
|
||||
final FakeNativeAssetsBuildRunner buildRunner =
|
||||
FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.linux,
|
||||
architecture: ArchitectureImpl.x64,
|
||||
file: dylibAfterCompiling.uri,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
final (Uri? nativeAssetsYaml, _) = await buildNativeAssetsLinux(
|
||||
targetPlatform: TargetPlatform.linux_x64,
|
||||
projectUri: projectUri,
|
||||
buildMode: buildMode,
|
||||
fileSystem: fileSystem,
|
||||
flutterTester: flutterTester,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Building native assets for linux_x64 $buildMode.',
|
||||
'Building native assets for linux_x64 done.',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/linux/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
stringContainsInOrder(<String>[
|
||||
'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/linux/libbar.so').toFilePath()}'
|
||||
else
|
||||
// Apps are a bundle with the dylibs on their dlopen path.
|
||||
'- libbar.so',
|
||||
]),
|
||||
);
|
||||
expect(buildRunner.buildInvocations, 1);
|
||||
expect(
|
||||
buildRunner.linkInvocations,
|
||||
buildMode == BuildMode.release ? 1 : 0,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
() => dryRunNativeAssetsLinux(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: const FakeNativeAssetsBuilderResult(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => buildNativeAssetsLinux(
|
||||
targetPlatform: TargetPlatform.linux_x64,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildResult: const FakeNativeAssetsBuilderResult(
|
||||
success: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'Building native assets failed. See the logs for more details.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
// This logic is mocked in the other tests to avoid having test order
|
||||
// randomization causing issues with what processes are invoked.
|
||||
// Exercise the parsing of the process output in this separate test.
|
||||
@ -110,14 +436,14 @@ void main() {
|
||||
packageConfigFile,
|
||||
logger: environment.logger,
|
||||
);
|
||||
final FlutterNativeAssetsBuildRunner runner =
|
||||
FlutterNativeAssetsBuildRunnerImpl(projectUri, packageConfigFile.path, packageConfig, fileSystem, logger);
|
||||
final NativeAssetsBuildRunner runner =
|
||||
NativeAssetsBuildRunnerImpl(projectUri, packageConfigFile.path, packageConfig, fileSystem, logger);
|
||||
final CCompilerConfigImpl result = await runner.cCompilerConfig;
|
||||
expect(result.compiler, Uri.file('/some/path/to/clang'));
|
||||
});
|
||||
}
|
||||
|
||||
class _BuildRunnerWithoutClang extends FakeFlutterNativeAssetsBuildRunner {
|
||||
class _BuildRunnerWithoutClang extends FakeNativeAssetsBuildRunner {
|
||||
@override
|
||||
Future<CCompilerConfigImpl> get cCompilerConfig async =>
|
||||
throwToolExit('Failed to find clang++ on the PATH.');
|
||||
|
@ -13,8 +13,10 @@ import 'package:flutter_tools/src/build_system/build_system.dart';
|
||||
import 'package:flutter_tools/src/dart/package_map.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/macos/native_assets.dart';
|
||||
import 'package:flutter_tools/src/isolated/native_assets/native_assets.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart' hide Target;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart'
|
||||
hide Target;
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart'
|
||||
as native_assets_cli;
|
||||
import 'package:package_config/package_config_types.dart';
|
||||
@ -49,9 +51,207 @@ void main() {
|
||||
projectUri = environment.projectDir.uri;
|
||||
});
|
||||
|
||||
for (final bool flutterTester in <bool>[false, true]) {
|
||||
final bool isArm64 = native_assets_cli.ArchitectureImpl.current == ArchitectureImpl.arm64;
|
||||
testUsingContext('dry run with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
expect(
|
||||
await dryRunNativeAssetsMacOS(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 {
|
||||
await buildNativeAssetsMacOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64],
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 dryRunNativeAssetsMultipleOSes(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetPlatforms: <TargetPlatform>[
|
||||
TargetPlatform.darwin,
|
||||
TargetPlatform.ios,
|
||||
],
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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(
|
||||
() => dryRunNativeAssetsMacOS(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.macOS,
|
||||
architecture: ArchitectureImpl.arm64,
|
||||
file: Uri.file('libbar.dylib'),
|
||||
),
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
linkMode: DynamicLoadingBundledImpl(),
|
||||
os: OSImpl.macOS,
|
||||
architecture: ArchitectureImpl.x64,
|
||||
file: Uri.file('libbar.dylib'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
final Uri? nativeAssetsYaml = await dryRunNativeAssetsMacOS(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Dry running native assets for macos.',
|
||||
'Dry running native assets for macos done.',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/macos/native_assets.yaml'),
|
||||
);
|
||||
final String nativeAssetsYamlContents =
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString();
|
||||
expect(
|
||||
nativeAssetsYamlContents,
|
||||
contains('package:bar/bar.dart'),
|
||||
);
|
||||
expect(buildRunner.buildDryRunInvocations, 1);
|
||||
expect(buildRunner.linkDryRunInvocations, 0);
|
||||
// Check that the framework uri is identical for both archs.
|
||||
final String pathSeparator = const LocalPlatform().pathSeparator;
|
||||
expect(
|
||||
nativeAssetsYamlContents,
|
||||
stringContainsInOrder(
|
||||
<String>[
|
||||
'bar.framework${pathSeparator}bar',
|
||||
'bar.framework${pathSeparator}bar',
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => buildNativeAssetsMacOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64],
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
final (Uri? nativeAssetsYaml, _) = await buildNativeAssetsMacOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64],
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/macos/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
isNot(contains('package:bar/bar.dart')),
|
||||
);
|
||||
});
|
||||
|
||||
for (final bool flutterTester in <bool>[false, true]) {
|
||||
String testName = '';
|
||||
if (flutterTester) {
|
||||
testName += ' flutter tester';
|
||||
@ -76,7 +276,7 @@ void main() {
|
||||
}
|
||||
for (final BuildMode buildMode in <BuildMode>[
|
||||
BuildMode.debug,
|
||||
if (!flutterTester) BuildMode.release,
|
||||
BuildMode.release,
|
||||
]) {
|
||||
testUsingContext('build with assets $buildMode$testName', overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
@ -89,7 +289,8 @@ void main() {
|
||||
'-create',
|
||||
'-output',
|
||||
dylibPathBar,
|
||||
'${isArm64 ? 'arm64' : 'x64'}/libbar.dylib',
|
||||
'arm64/libbar.dylib',
|
||||
'x64/libbar.dylib',
|
||||
],
|
||||
),
|
||||
FakeCommand(
|
||||
@ -111,7 +312,8 @@ void main() {
|
||||
'-create',
|
||||
'-output',
|
||||
dylibPathBuz,
|
||||
'${isArm64 ? 'arm64' : 'x64'}/libbuz.dylib',
|
||||
'arm64/libbuz.dylib',
|
||||
'x64/libbuz.dylib',
|
||||
],
|
||||
),
|
||||
FakeCommand(
|
||||
@ -121,7 +323,9 @@ void main() {
|
||||
dylibPathBuz,
|
||||
],
|
||||
stdout: <String>[
|
||||
'$dylibPathBuz (architecture ${isArm64 ? 'arm64' : 'x86_64'}):',
|
||||
'$dylibPathBuz (architecture x86_64):',
|
||||
'@rpath/libbuz.dylib',
|
||||
'$dylibPathBuz (architecture arm64):',
|
||||
'@rpath/libbuz.dylib',
|
||||
].join('\n'),
|
||||
),
|
||||
@ -145,7 +349,8 @@ void main() {
|
||||
'--force',
|
||||
'--sign',
|
||||
'-',
|
||||
if (buildMode == BuildMode.debug) '--timestamp=none',
|
||||
if (buildMode == BuildMode.debug)
|
||||
'--timestamp=none',
|
||||
signPathBar,
|
||||
],
|
||||
),
|
||||
@ -156,7 +361,7 @@ void main() {
|
||||
dylibPathBuz,
|
||||
'-change',
|
||||
'@rpath/libbar.dylib',
|
||||
dylibPathBar,
|
||||
dylibPathBar,
|
||||
'-change',
|
||||
'@rpath/libbuz.dylib',
|
||||
signPathBuz,
|
||||
@ -169,7 +374,8 @@ void main() {
|
||||
'--force',
|
||||
'--sign',
|
||||
'-',
|
||||
if (buildMode == BuildMode.debug) '--timestamp=none',
|
||||
if (buildMode == BuildMode.debug)
|
||||
'--timestamp=none',
|
||||
signPathBuz,
|
||||
],
|
||||
),
|
||||
@ -255,27 +461,15 @@ void main() {
|
||||
if (const LocalPlatform().isWindows) {
|
||||
return; // Backslashes in commands, but we will never run these commands on Windows.
|
||||
}
|
||||
if (flutterTester && !const LocalPlatform().isMacOS) {
|
||||
// The [runFlutterSpecificDartBuild] will - when given
|
||||
// `TargetPlatform.tester` - enable `flutter test` mode. That means if
|
||||
// this test is run on linux, it's going to do a linux build.
|
||||
// Though this test is mac-specific, so we skip that.
|
||||
//
|
||||
// Running the test in `!flutterTester` mode still works on linux as
|
||||
// we explicitly tell it to do a mac build (instead of letting it
|
||||
// choose the local build).
|
||||
return;
|
||||
}
|
||||
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 FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
final FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
onBuild: (native_assets_cli.Target target) =>
|
||||
FakeFlutterNativeAssetsBuilderResult(
|
||||
FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
@ -292,34 +486,26 @@ void main() {
|
||||
file: Uri.file('${target.architecture}/libbuz.dylib'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
final (_, Uri nativeAssetsYaml) = await runFlutterSpecificDartBuild(
|
||||
environmentDefines: <String, String>{
|
||||
kBuildMode: buildMode.cliName,
|
||||
kDarwinArchs: 'arm64 x86_64',
|
||||
},
|
||||
targetPlatform: flutterTester ? TargetPlatform.tester : TargetPlatform.darwin,
|
||||
final (Uri? nativeAssetsYaml, _) = await buildNativeAssetsMacOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64, DarwinArch.x86_64],
|
||||
projectUri: projectUri,
|
||||
nativeAssetsYamlUri: flutterTester ? null : nonFlutterTesterAssetUri,
|
||||
buildMode: buildMode,
|
||||
fileSystem: fileSystem,
|
||||
flutterTester: flutterTester,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
final String expectedArchsBeingBuilt = flutterTester
|
||||
? (isArm64 ? 'macos_arm64' : 'macos_x64')
|
||||
: '[macos_arm64, macos_x64]';
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Building native assets for $expectedArchsBeingBuilt $buildMode.',
|
||||
'Building native assets for $expectedArchsBeingBuilt $buildMode done.',
|
||||
'Building native assets for [macos_arm64, macos_x64] $buildMode.',
|
||||
'Building native assets for [macos_arm64, macos_x64] done.',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
flutterTester
|
||||
? projectUri.resolve('build/native_assets/macos/native_assets.yaml')
|
||||
: nonFlutterTesterAssetUri
|
||||
projectUri.resolve('build/native_assets/macos/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
@ -327,10 +513,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/macos/libbar.dylib').toFilePath()
|
||||
'- ${projectUri.resolve('build/native_assets/macos/libbar.dylib').toFilePath()}'
|
||||
else
|
||||
// Apps are a bundle with the dylibs on their dlopen path.
|
||||
'bar.framework/bar',
|
||||
'- bar.framework/bar',
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
@ -339,14 +525,14 @@ void main() {
|
||||
'package:buz/buz.dart',
|
||||
if (flutterTester)
|
||||
// Tests run on host system, so the have the full path on the system.
|
||||
projectUri.resolve('build/native_assets/macos/libbuz.dylib').toFilePath()
|
||||
'- ${projectUri.resolve('build/native_assets/macos/libbuz.dylib').toFilePath()}'
|
||||
else
|
||||
// Apps are a bundle with the dylibs on their dlopen path.
|
||||
'buz.framework/buz',
|
||||
'- buz.framework/buz',
|
||||
]),
|
||||
);
|
||||
// Multi arch.
|
||||
expect(buildRunner.buildInvocations, flutterTester ? 1 : 2);
|
||||
expect(buildRunner.buildInvocations, 2);
|
||||
expect(
|
||||
buildRunner.linkInvocations,
|
||||
buildMode == BuildMode.release ? 2 : 0,
|
||||
@ -355,24 +541,82 @@ 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(
|
||||
() => dryRunNativeAssetsMacOS(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: const FakeNativeAssetsBuilderResult(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => buildNativeAssetsMacOS(
|
||||
darwinArchs: <DarwinArch>[DarwinArch.arm64],
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildResult: const FakeNativeAssetsBuilderResult(
|
||||
success: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'Building native assets failed. See the logs for more details.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
// This logic is mocked in the other tests to avoid having test order
|
||||
// randomization causing issues with what processes are invoked.
|
||||
// Exercise the parsing of the process output in this separate test.
|
||||
testUsingContext('NativeAssetsBuildRunnerImpl.cCompilerConfig',
|
||||
overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
ProcessManager: () => FakeProcessManager.list(
|
||||
<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <Pattern>['xcrun', 'clang', '--version'],
|
||||
stdout: '''
|
||||
testUsingContext('NativeAssetsBuildRunnerImpl.cCompilerConfig', overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
ProcessManager: () => FakeProcessManager.list(
|
||||
<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <Pattern>['xcrun', 'clang', '--version'],
|
||||
stdout: '''
|
||||
Apple clang version 14.0.0 (clang-1400.0.29.202)
|
||||
Target: arm64-apple-darwin22.6.0
|
||||
Thread model: posix
|
||||
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin''',
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
}, () async {
|
||||
if (!const LocalPlatform().isMacOS) {
|
||||
return;
|
||||
@ -388,7 +632,7 @@ InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault
|
||||
packageConfigFile,
|
||||
logger: environment.logger,
|
||||
);
|
||||
final FlutterNativeAssetsBuildRunner runner = FlutterNativeAssetsBuildRunnerImpl(
|
||||
final NativeAssetsBuildRunner runner = NativeAssetsBuildRunnerImpl(
|
||||
projectUri,
|
||||
packageConfigFile.path,
|
||||
packageConfig,
|
||||
|
@ -1,308 +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/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.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
}
|
@ -56,7 +56,7 @@ void main() {
|
||||
globals.fs
|
||||
.file(globals.fs.path.join('lib', 'main.dart'))
|
||||
.createSync(recursive: true);
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner();
|
||||
final FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner();
|
||||
final HotRunner residentRunner = HotRunner(
|
||||
<FlutterDevice>[
|
||||
flutterDevice,
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
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';
|
||||
@ -14,8 +15,9 @@ import 'package:flutter_tools/src/dart/package_map.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:native_assets_cli/native_assets_cli_internal.dart' as native_assets_cli;
|
||||
import 'package:flutter_tools/src/isolated/native_assets/windows/native_assets.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli_internal.dart'
|
||||
hide Target;
|
||||
import 'package:package_config/package_config_types.dart';
|
||||
|
||||
import '../../../src/common.dart';
|
||||
@ -48,6 +50,187 @@ void main() {
|
||||
projectUri = environment.projectDir.uri;
|
||||
});
|
||||
|
||||
testUsingContext('dry run with no package config', overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
expect(
|
||||
await dryRunNativeAssetsWindows(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 {
|
||||
await buildNativeAssetsWindows(
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 dryRunNativeAssetsMultipleOSes(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
targetPlatforms: <TargetPlatform>[
|
||||
TargetPlatform.windows_x64,
|
||||
],
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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(
|
||||
() => dryRunNativeAssetsWindows(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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 FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: FakeNativeAssetsBuilderResult(
|
||||
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 dryRunNativeAssetsWindows(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
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);
|
||||
expect(buildRunner.linkDryRunInvocations, 0);
|
||||
});
|
||||
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => buildNativeAssetsWindows(
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
final (Uri? nativeAssetsYaml, _) = await buildNativeAssetsWindows(
|
||||
targetPlatform: TargetPlatform.windows_x64,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
),
|
||||
);
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/windows/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
isNot(contains('package:bar/bar.dart')),
|
||||
);
|
||||
expect(
|
||||
environment.projectDir.childDirectory('build').childDirectory('native_assets').childDirectory('windows'),
|
||||
exists,
|
||||
);
|
||||
});
|
||||
|
||||
for (final bool flutterTester in <bool>[false, true]) {
|
||||
String testName = '';
|
||||
if (flutterTester) {
|
||||
@ -55,33 +238,23 @@ void main() {
|
||||
}
|
||||
for (final BuildMode buildMode in <BuildMode>[
|
||||
BuildMode.debug,
|
||||
if (!flutterTester) BuildMode.release,
|
||||
BuildMode.release,
|
||||
]) {
|
||||
if (flutterTester && !const LocalPlatform().isWindows) {
|
||||
// When calling [runFlutterSpecificDartBuild] with the flutter tester
|
||||
// target platform, it will perform a build for the local machine. That
|
||||
// means e.g. running this test on MacOS will cause it to run a MacOS
|
||||
// build - which in return requires a special [ProcessManager] that can
|
||||
// simulate output of `otool` invocations.
|
||||
continue;
|
||||
}
|
||||
|
||||
testUsingContext('build with assets $buildMode$testName', overrides: <Type, Generator>{
|
||||
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
}, () async {
|
||||
final File packageConfig = environment.projectDir.childDirectory('.dart_tool').childFile('package_config.json');
|
||||
final Uri nonFlutterTesterAssetUri = environment.buildDir.childFile('native_assets.yaml').uri;
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
final File dylibAfterCompiling = fileSystem.file('bar.dll');
|
||||
// The mock doesn't create the file, so create it here.
|
||||
await dylibAfterCompiling.create();
|
||||
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
|
||||
final FakeNativeAssetsBuildRunner buildRunner = FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildResult: FakeFlutterNativeAssetsBuilderResult(
|
||||
buildResult: FakeNativeAssetsBuilderResult(
|
||||
assets: <AssetImpl>[
|
||||
NativeCodeAssetImpl(
|
||||
id: 'package:bar/bar.dart',
|
||||
@ -93,35 +266,24 @@ void main() {
|
||||
],
|
||||
),
|
||||
);
|
||||
final (_, Uri nativeAssetsYaml) = await runFlutterSpecificDartBuild(
|
||||
environmentDefines: <String, String>{
|
||||
kBuildMode: buildMode.cliName,
|
||||
},
|
||||
targetPlatform: flutterTester
|
||||
? TargetPlatform.tester
|
||||
: TargetPlatform.windows_x64,
|
||||
final (Uri? nativeAssetsYaml, _) = await buildNativeAssetsWindows(
|
||||
targetPlatform: TargetPlatform.windows_x64,
|
||||
projectUri: projectUri,
|
||||
nativeAssetsYamlUri: flutterTester ? null : nonFlutterTesterAssetUri,
|
||||
buildMode: buildMode,
|
||||
fileSystem: fileSystem,
|
||||
flutterTester: flutterTester,
|
||||
buildRunner: buildRunner,
|
||||
);
|
||||
final String expectedOS = flutterTester
|
||||
? native_assets_cli.Target.current.toString()
|
||||
: 'windows_x64';
|
||||
expect(
|
||||
(globals.logger as BufferLogger).traceText,
|
||||
stringContainsInOrder(<String>[
|
||||
'Building native assets for $expectedOS $buildMode.',
|
||||
'Building native assets for $expectedOS $buildMode done.',
|
||||
'Building native assets for windows_x64 $buildMode.',
|
||||
'Building native assets for windows_x64 done.',
|
||||
]),
|
||||
);
|
||||
final String expectedDirectory = flutterTester
|
||||
? native_assets_cli.OSImpl.current.toString()
|
||||
: 'windows';
|
||||
expect(nativeAssetsYaml,
|
||||
flutterTester
|
||||
? projectUri.resolve('build/native_assets/$expectedDirectory/native_assets.yaml')
|
||||
: nonFlutterTesterAssetUri
|
||||
expect(
|
||||
nativeAssetsYaml,
|
||||
projectUri.resolve('build/native_assets/windows/native_assets.yaml'),
|
||||
);
|
||||
expect(
|
||||
await fileSystem.file(nativeAssetsYaml).readAsString(),
|
||||
@ -129,21 +291,80 @@ 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/windows/bar.dll').toFilePath()}'
|
||||
else
|
||||
// Apps are a bundle with the dylibs on their dlopen path.
|
||||
'bar.dll',
|
||||
'- bar.dll',
|
||||
]),
|
||||
);
|
||||
expect(buildRunner.buildInvocations, 1);
|
||||
expect(
|
||||
buildRunner.linkInvocations,
|
||||
buildMode == BuildMode.release ? 1 : 0,
|
||||
buildMode == BuildMode.release ? 1 :0,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
() => dryRunNativeAssetsWindows(
|
||||
projectUri: projectUri,
|
||||
fileSystem: fileSystem,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildDryRunResult: const FakeNativeAssetsBuilderResult(
|
||||
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');
|
||||
await packageConfig.parent.create();
|
||||
await packageConfig.create();
|
||||
expect(
|
||||
() => buildNativeAssetsWindows(
|
||||
targetPlatform: TargetPlatform.windows_x64,
|
||||
projectUri: projectUri,
|
||||
buildMode: BuildMode.debug,
|
||||
fileSystem: fileSystem,
|
||||
yamlParentDirectory: environment.buildDir.uri,
|
||||
buildRunner: FakeNativeAssetsBuildRunner(
|
||||
packagesWithNativeAssetsResult: <Package>[
|
||||
Package('bar', projectUri),
|
||||
],
|
||||
buildResult: const FakeNativeAssetsBuilderResult(
|
||||
success: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'Building native assets failed. See the logs for more details.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
// This logic is mocked in the other tests to avoid having test order
|
||||
// randomization causing issues with what processes are invoked.
|
||||
// Exercise the parsing of the process output in this separate test.
|
||||
@ -232,14 +453,17 @@ void main() {
|
||||
fileSystem.directory(r'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\bin\Hostx64\x64');
|
||||
await msvcBinDir.create(recursive: true);
|
||||
|
||||
final File packageConfigFile = fileSystem.directory(projectUri).childDirectory('.dart_tool').childFile('package_config.json');
|
||||
final File packageConfigFile = fileSystem
|
||||
.directory(projectUri)
|
||||
.childDirectory('.dart_tool')
|
||||
.childFile('package_config.json');
|
||||
await packageConfigFile.parent.create();
|
||||
await packageConfigFile.create();
|
||||
final PackageConfig packageConfig = await loadPackageConfigWithLogging(
|
||||
packageConfigFile,
|
||||
logger: environment.logger,
|
||||
);
|
||||
final FlutterNativeAssetsBuildRunner runner = FlutterNativeAssetsBuildRunnerImpl(
|
||||
final NativeAssetsBuildRunner runner = NativeAssetsBuildRunnerImpl(
|
||||
projectUri,
|
||||
packageConfigFile.path,
|
||||
packageConfig,
|
||||
|
Loading…
x
Reference in New Issue
Block a user