[native_assets] Add support for link hooks (#148474)

This PR adds support invoking `link.dart` hooks.

Link hooks can add new assets. Link hooks can transform assets sent to link hook from build hooks.

This PR does not yet add support for getting tree-shake information in the link hooks. This is pending on defining the `resources.json` format (https://github.com/dart-lang/sdk/issues/55494).

Issue:

* https://github.com/flutter/flutter/issues/146263

## Implementation considerations

The build hooks could be run before Dart compilation and the link hooks after Dart compilation. (This is how it's done in Dart standalone.) However, due to the way the `Target`s are set up, this would require two targets and serializing and deserializing the `BuildResult` in between these. This would lead to more code but no benefits. Currently there is nothing that mandates running build hooks before Dart compilation.

## Testing

* The unit tests verify that the native_assets_builder `link` and `linkDryRun` would be invoked with help of the existing fake.
* The native assets integration test now also invokes an FFI call of a package that adds the asset during the link hook instead of the build hook.
  * In order to keep coverage of the `flutter create --template=package_ffi`, `flutter create` is still run and the extra dependency is added and an extra ffi call is added. (Open to alternative suggestions.)
This commit is contained in:
Daco Harkes 2024-05-22 18:02:00 +02:00 committed by GitHub
parent 8f227fee7c
commit 1f16d9121c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 1054 additions and 421 deletions

View File

@ -0,0 +1,30 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/

View File

@ -0,0 +1,3 @@
# link_hook
Test project for the native assets test to exercise adding assets during a link hook.

View File

@ -0,0 +1,20 @@
# Run with `dart run ffigen --config ffigen.yaml`.
name: LinkHookBindings
description: |
Bindings for `src/link_hook.h`.
Regenerate bindings with `dart run ffigen --config ffigen.yaml`.
output: 'lib/link_hook_bindings_generated.dart'
headers:
entry-points:
- 'src/link_hook.h'
include-directives:
- 'src/link_hook.h'
ffi-native:
preamble: |
// ignore_for_file: always_specify_types
// ignore_for_file: camel_case_types
// ignore_for_file: non_constant_identifier_names
comments:
style: any
length: full

View File

@ -0,0 +1,36 @@
// 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:logging/logging.dart';
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
void main(List<String> args) async {
await build(args, (BuildConfig config, BuildOutput output) async {
final String packageName = config.packageName;
final CBuilder cbuilder = CBuilder.library(
name: packageName,
assetName: 'some_asset_name_that_is_not_used',
sources: <String>[
'src/$packageName.c',
],
dartBuildFiles: <String>['hook/build.dart'],
);
final BuildOutput outputCatcher = BuildOutput();
await cbuilder.run(
buildConfig: config,
buildOutput: outputCatcher,
logger: Logger('')
..level = Level.ALL
..onRecord.listen((LogRecord record) => print(record.message)),
);
output.addDependencies(outputCatcher.dependencies);
// Send the asset to hook/link.dart.
output.addAsset(
outputCatcher.assets.single,
linkInPackage: 'link_hook',
);
});
}

View File

@ -0,0 +1,22 @@
// 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:native_assets_cli/native_assets_cli.dart';
void main(List<String> args) async {
await link(args, (LinkConfig config, LinkOutput output) async {
final NativeCodeAsset asset = config.assets.single as NativeCodeAsset;
final String packageName = config.packageName;
output.addAsset(NativeCodeAsset(
package: packageName,
// Change the asset id to something that is used.
name: '${packageName}_bindings_generated.dart',
linkMode: asset.linkMode,
os: asset.os,
architecture: asset.architecture,
file: asset.file,
));
output.addDependency(config.packageRoot.resolve('hook/link.dart'));
});
}

View File

@ -0,0 +1,8 @@
// 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 'link_hook_bindings_generated.dart' as bindings;
/// A very short-lived native function.
int difference(int a, int b) => bindings.difference(a, b);

View File

@ -0,0 +1,19 @@
// 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.
// ignore_for_file: always_specify_types
// ignore_for_file: camel_case_types
// ignore_for_file: non_constant_identifier_names
// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;
/// A very short-lived native function.
@ffi.Native<ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr)>()
external int difference(
int a,
int b,
);

View File

@ -0,0 +1,70 @@
name: link_hook
description: "A new Dart FFI package project."
version: 0.0.1
environment:
sdk: '>=3.5.0-154.0.dev <4.0.0'
dependencies:
cli_config: 0.2.0
logging: 1.2.0
native_assets_cli: 0.6.0
native_toolchain_c: 0.4.2
args: 2.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
async: 2.11.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
collection: 1.18.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
crypto: 3.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
file: 7.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
glob: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
meta: 1.14.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
path: 1.9.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
pub_semver: 2.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_span: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
string_scanner: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
term_glyph: 1.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
typed_data: 1.3.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
yaml: 3.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
dev_dependencies:
ffi: 2.1.2
ffigen: 12.0.0
flutter_lints: 4.0.0
test: 1.25.5
_fe_analyzer_shared: 68.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
analyzer: 6.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
boolean_selector: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
cli_util: 0.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
convert: 3.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
coverage: 1.8.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
frontend_server_client: 4.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
http_multi_server: 3.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
http_parser: 4.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
io: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
js: 0.7.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
lints: 4.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
matcher: 0.12.16+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
mime: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
node_preamble: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
package_config: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
pool: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
quiver: 3.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
shelf: 1.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
shelf_packages_handler: 3.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
shelf_static: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
shelf_web_socket: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_map_stack_trace: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_maps: 0.10.12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
stack_trace: 1.11.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
stream_channel: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
test_api: 0.7.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
test_core: 0.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
vm_service: 14.2.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
watcher: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
web: 0.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
web_socket_channel: 2.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
webkit_inspection_protocol: 1.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
yaml_edit: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
# PUBSPEC CHECKSUM: e03f

View File

@ -0,0 +1,12 @@
// 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.
#include "link_hook.h"
// A very short-lived native function.
//
// For very short-lived functions, it is fine to call them on the main isolate.
// They will block the Dart execution while running the native function, so
// only do this for native functions which are guaranteed to be short-lived.
FFI_PLUGIN_EXPORT intptr_t difference(intptr_t a, intptr_t b) { return a - b; }

View File

@ -0,0 +1,22 @@
// 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.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#if _WIN32
#include <windows.h>
#else
#include <pthread.h>
#include <unistd.h>
#endif
#if _WIN32
#define FFI_PLUGIN_EXPORT __declspec(dllexport)
#else
#define FFI_PLUGIN_EXPORT
#endif
FFI_PLUGIN_EXPORT intptr_t difference(intptr_t a, intptr_t b);

View File

@ -0,0 +1,13 @@
// 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:link_hook/link_hook.dart';
import 'package:test/test.dart';
void main() {
test('invoke native function', () {
// Tests are run in debug mode.
expect(difference(24, 18), 24 - 18);
});
}

View File

@ -50,14 +50,25 @@ Future<Iterable<KernelAsset>> dryRunNativeAssetsAndroidInternal(
const OSImpl targetOS = OSImpl.android;
globals.logger.printTrace('Dry running native assets for $targetOS.');
final DryRunResult dryRunResult = await buildRunner.dryRun(
final BuildDryRunResult buildDryRunResult = await buildRunner.buildDryRun(
linkModePreference: LinkModePreferenceImpl.dynamic,
targetOS: targetOS,
workingDirectory: projectUri,
includeParentEnvironment: true,
);
ensureNativeAssetsBuildSucceed(dryRunResult);
final List<AssetImpl> nativeAssets = dryRunResult.assets;
ensureNativeAssetsBuildDryRunSucceed(buildDryRunResult);
final LinkDryRunResult linkDryRunResult = await buildRunner.linkDryRun(
linkModePreference: LinkModePreferenceImpl.dynamic,
targetOS: targetOS,
workingDirectory: projectUri,
includeParentEnvironment: true,
buildDryRunResult: buildDryRunResult,
);
ensureNativeAssetsLinkDryRunSucceed(linkDryRunResult);
final List<AssetImpl> nativeAssets = <AssetImpl>[
...buildDryRunResult.assets,
...linkDryRunResult.assets,
];
ensureNoLinkModeStatic(nativeAssets);
globals.logger.printTrace('Dry running native assets for $targetOS done.');
final Map<AssetImpl, KernelAsset> assetTargetLocations =
@ -97,7 +108,7 @@ Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)>
final List<AssetImpl> nativeAssets = <AssetImpl>[];
final Set<Uri> dependencies = <Uri>{};
for (final Target target in targets) {
final BuildResult result = await buildRunner.build(
final BuildResult buildResult = await buildRunner.build(
linkModePreference: LinkModePreferenceImpl.dynamic,
target: target,
buildMode: buildModeCli,
@ -106,9 +117,22 @@ Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)>
cCompilerConfig: await buildRunner.ndkCCompilerConfigImpl,
targetAndroidNdkApi: targetAndroidNdkApi,
);
ensureNativeAssetsBuildSucceed(result);
nativeAssets.addAll(result.assets);
dependencies.addAll(result.dependencies);
ensureNativeAssetsBuildSucceed(buildResult);
nativeAssets.addAll(buildResult.assets);
dependencies.addAll(buildResult.dependencies);
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);
}
ensureNoLinkModeStatic(nativeAssets);
globals.logger.printTrace('Building native assets for $targets done.');

View File

@ -48,14 +48,25 @@ Future<Iterable<KernelAsset>> dryRunNativeAssetsIOSInternal(
) async {
const OSImpl targetOS = OSImpl.iOS;
globals.logger.printTrace('Dry running native assets for $targetOS.');
final DryRunResult dryRunResult = await buildRunner.dryRun(
final BuildDryRunResult buildDryRunResult = await buildRunner.buildDryRun(
linkModePreference: LinkModePreferenceImpl.dynamic,
targetOS: targetOS,
workingDirectory: projectUri,
includeParentEnvironment: true,
);
ensureNativeAssetsBuildSucceed(dryRunResult);
final List<AssetImpl> nativeAssets = dryRunResult.assets;
ensureNativeAssetsBuildDryRunSucceed(buildDryRunResult);
final LinkDryRunResult linkDryRunResult = await buildRunner.linkDryRun(
linkModePreference: LinkModePreferenceImpl.dynamic,
targetOS: targetOS,
workingDirectory: projectUri,
includeParentEnvironment: true,
buildDryRunResult: buildDryRunResult,
);
ensureNativeAssetsLinkDryRunSucceed(linkDryRunResult);
final List<AssetImpl> nativeAssets = <AssetImpl>[
...buildDryRunResult.assets,
...linkDryRunResult.assets,
];
ensureNoLinkModeStatic(nativeAssets);
globals.logger.printTrace('Dry running native assets for $targetOS done.');
return _assetTargetLocations(nativeAssets).values;
@ -88,7 +99,7 @@ Future<List<Uri>> buildNativeAssetsIOS({
final List<AssetImpl> nativeAssets = <AssetImpl>[];
final Set<Uri> dependencies = <Uri>{};
for (final Target target in targets) {
final BuildResult result = await buildRunner.build(
final BuildResult buildResult = await buildRunner.build(
linkModePreference: LinkModePreferenceImpl.dynamic,
target: target,
targetIOSSdkImpl: iosSdk,
@ -97,9 +108,22 @@ Future<List<Uri>> buildNativeAssetsIOS({
includeParentEnvironment: true,
cCompilerConfig: await buildRunner.cCompilerConfig,
);
ensureNativeAssetsBuildSucceed(result);
nativeAssets.addAll(result.assets);
dependencies.addAll(result.dependencies);
ensureNativeAssetsBuildSucceed(buildResult);
nativeAssets.addAll(buildResult.assets);
dependencies.addAll(buildResult.dependencies);
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,
);
ensureNativeAssetsLinkSucceed(linkResult);
nativeAssets.addAll(linkResult.assets);
dependencies.addAll(linkResult.dependencies);
}
ensureNoLinkModeStatic(nativeAssets);
globals.logger.printTrace('Building native assets for $targets done.');

View File

@ -52,14 +52,25 @@ Future<Iterable<KernelAsset>> dryRunNativeAssetsMacOSInternal(
final Uri buildUri = nativeAssetsBuildUri(projectUri, targetOS);
globals.logger.printTrace('Dry running native assets for $targetOS.');
final DryRunResult dryRunResult = await buildRunner.dryRun(
final BuildDryRunResult buildDryRunResult = await buildRunner.buildDryRun(
linkModePreference: LinkModePreferenceImpl.dynamic,
targetOS: targetOS,
workingDirectory: projectUri,
includeParentEnvironment: true,
);
ensureNativeAssetsBuildSucceed(dryRunResult);
final List<AssetImpl> nativeAssets = dryRunResult.assets;
ensureNativeAssetsBuildDryRunSucceed(buildDryRunResult);
final LinkDryRunResult linkDryRunResult = await buildRunner.linkDryRun(
linkModePreference: LinkModePreferenceImpl.dynamic,
targetOS: targetOS,
workingDirectory: projectUri,
includeParentEnvironment: true,
buildDryRunResult: buildDryRunResult,
);
ensureNativeAssetsLinkDryRunSucceed(linkDryRunResult);
final List<AssetImpl> nativeAssets = <AssetImpl>[
...buildDryRunResult.assets,
...linkDryRunResult.assets,
];
ensureNoLinkModeStatic(nativeAssets);
globals.logger.printTrace('Dry running native assets for $targetOS done.');
final Uri? absolutePath = flutterTester ? buildUri : null;
@ -110,7 +121,7 @@ Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)> buildNativeAssetsMacOS({
final List<AssetImpl> nativeAssets = <AssetImpl>[];
final Set<Uri> dependencies = <Uri>{};
for (final Target target in targets) {
final BuildResult result = await buildRunner.build(
final BuildResult buildResult = await buildRunner.build(
linkModePreference: LinkModePreferenceImpl.dynamic,
target: target,
buildMode: buildModeCli,
@ -118,9 +129,21 @@ Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)> buildNativeAssetsMacOS({
includeParentEnvironment: true,
cCompilerConfig: await buildRunner.cCompilerConfig,
);
ensureNativeAssetsBuildSucceed(result);
nativeAssets.addAll(result.assets);
dependencies.addAll(result.dependencies);
ensureNativeAssetsBuildSucceed(buildResult);
nativeAssets.addAll(buildResult.assets);
dependencies.addAll(buildResult.dependencies);
final LinkResult linkResult = await buildRunner.link(
linkModePreference: LinkModePreferenceImpl.dynamic,
target: target,
buildMode: buildModeCli,
workingDirectory: projectUri,
includeParentEnvironment: true,
cCompilerConfig: await buildRunner.cCompilerConfig,
buildResult: buildResult,
);
ensureNativeAssetsLinkSucceed(linkResult);
nativeAssets.addAll(linkResult.assets);
dependencies.addAll(linkResult.dependencies);
}
ensureNoLinkModeStatic(nativeAssets);
globals.logger.printTrace('Building native assets for $targets done.');

View File

@ -38,14 +38,14 @@ abstract class NativeAssetsBuildRunner {
/// Whether the project has a `.dart_tools/package_config.json`.
///
/// If there is no package config, [packagesWithNativeAssets], [build], and
/// [dryRun] must not be invoked.
/// [buildDryRun] must not be invoked.
Future<bool> hasPackageConfig();
/// All packages in the transitive dependencies that have a `build.dart`.
Future<List<Package>> packagesWithNativeAssets();
/// Runs all [packagesWithNativeAssets] `build.dart` in dry run.
Future<DryRunResult> dryRun({
Future<BuildDryRunResult> buildDryRun({
required bool includeParentEnvironment,
required LinkModePreferenceImpl linkModePreference,
required OSImpl targetOS,
@ -64,6 +64,28 @@ abstract class NativeAssetsBuildRunner {
IOSSdkImpl? targetIOSSdkImpl,
});
/// Runs all [packagesWithNativeAssets] `link.dart` in dry run.
Future<LinkDryRunResult> linkDryRun({
required bool includeParentEnvironment,
required LinkModePreferenceImpl linkModePreference,
required OSImpl targetOS,
required Uri workingDirectory,
required BuildDryRunResult buildDryRunResult,
});
/// Runs all [packagesWithNativeAssets] `link.dart`.
Future<LinkResult> link({
required bool includeParentEnvironment,
required BuildModeImpl buildMode,
required LinkModePreferenceImpl linkModePreference,
required Target target,
required Uri workingDirectory,
required BuildResult buildResult,
CCompilerConfigImpl? cCompilerConfig,
int? targetAndroidNdkApi,
IOSSdkImpl? targetIOSSdkImpl,
});
/// The C compiler config to use for compilation.
Future<CCompilerConfigImpl> get cCompilerConfig;
@ -120,11 +142,14 @@ class NativeAssetsBuildRunnerImpl implements NativeAssetsBuildRunner {
packageConfig,
projectUri.resolve('.dart_tool/package_config.json'),
);
return packageLayout.packagesWithNativeAssets;
// It suffices to only check for build hooks. If no packages have a build
// hook. Then no build hook will output any assets for any link hook, and
// thus the link hooks will never be run.
return packageLayout.packagesWithAssets(Hook.build);
}
@override
Future<DryRunResult> dryRun({
Future<BuildDryRunResult> buildDryRun({
required bool includeParentEnvironment,
required LinkModePreferenceImpl linkModePreference,
required OSImpl targetOS,
@ -134,7 +159,7 @@ class NativeAssetsBuildRunnerImpl implements NativeAssetsBuildRunner {
packageConfig,
projectUri.resolve('.dart_tool/package_config.json'),
);
return _buildRunner.dryRun(
return _buildRunner.buildDryRun(
includeParentEnvironment: includeParentEnvironment,
linkModePreference: linkModePreference,
targetOS: targetOS,
@ -171,6 +196,59 @@ class NativeAssetsBuildRunnerImpl implements NativeAssetsBuildRunner {
);
}
@override
Future<LinkDryRunResult> linkDryRun({
required bool includeParentEnvironment,
required LinkModePreferenceImpl linkModePreference,
required OSImpl targetOS,
required Uri workingDirectory,
required BuildDryRunResult buildDryRunResult,
}) {
final PackageLayout packageLayout = PackageLayout.fromPackageConfig(
packageConfig,
projectUri.resolve('.dart_tool/package_config.json'),
);
return _buildRunner.linkDryRun(
includeParentEnvironment: includeParentEnvironment,
linkModePreference: linkModePreference,
targetOS: targetOS,
workingDirectory: workingDirectory,
packageLayout: packageLayout,
buildDryRunResult: buildDryRunResult,
);
}
@override
Future<LinkResult> link({
required bool includeParentEnvironment,
required BuildModeImpl buildMode,
required LinkModePreferenceImpl linkModePreference,
required Target target,
required Uri workingDirectory,
required BuildResult buildResult,
CCompilerConfigImpl? cCompilerConfig,
int? targetAndroidNdkApi,
IOSSdkImpl? targetIOSSdkImpl,
}) {
final PackageLayout packageLayout = PackageLayout.fromPackageConfig(
packageConfig,
projectUri.resolve('.dart_tool/package_config.json'),
);
return _buildRunner.link(
buildMode: buildMode,
cCompilerConfig: cCompilerConfig,
includeParentEnvironment: includeParentEnvironment,
linkModePreference: linkModePreference,
target: target,
targetAndroidNdkApi: targetAndroidNdkApi,
targetIOSSdk: targetIOSSdkImpl,
workingDirectory: workingDirectory,
packageLayout: packageLayout,
buildResult: buildResult,
);
}
@override
late final Future<CCompilerConfigImpl> cCompilerConfig = () {
if (globals.platform.isMacOS || globals.platform.isIOS) {
@ -560,14 +638,25 @@ Future<Iterable<KernelAsset>> dryRunNativeAssetsSingleArchitectureInternal(
globals.logger.printTrace('Dry running native assets for $targetOS.');
final DryRunResult dryRunResult = await buildRunner.dryRun(
final BuildDryRunResult buildDryRunResult = await buildRunner.buildDryRun(
linkModePreference: LinkModePreferenceImpl.dynamic,
targetOS: targetOS,
workingDirectory: projectUri,
includeParentEnvironment: true,
);
ensureNativeAssetsBuildSucceed(dryRunResult);
final List<AssetImpl> nativeAssets = dryRunResult.assets;
ensureNativeAssetsBuildDryRunSucceed(buildDryRunResult);
final LinkDryRunResult linkDryRunResult = await buildRunner.linkDryRun(
linkModePreference: LinkModePreferenceImpl.dynamic,
targetOS: targetOS,
workingDirectory: projectUri,
includeParentEnvironment: true,
buildDryRunResult: buildDryRunResult,
);
ensureNativeAssetsLinkDryRunSucceed(linkDryRunResult);
final List<AssetImpl> nativeAssets = <AssetImpl>[
...buildDryRunResult.assets,
...linkDryRunResult.assets,
];
ensureNoLinkModeStatic(nativeAssets);
globals.logger.printTrace('Dry running native assets for $targetOS done.');
final Uri? absolutePath = flutterTester ? buildUri : null;
@ -615,7 +704,7 @@ Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)> buildNativeAssetsSingleA
final BuildModeImpl buildModeCli = nativeAssetsBuildMode(buildMode);
globals.logger.printTrace('Building native assets for $target $buildModeCli.');
final BuildResult result = await buildRunner.build(
final BuildResult buildResult = await buildRunner.build(
linkModePreference: LinkModePreferenceImpl.dynamic,
target: target,
buildMode: buildModeCli,
@ -623,9 +712,25 @@ Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)> buildNativeAssetsSingleA
includeParentEnvironment: true,
cCompilerConfig: await buildRunner.cCompilerConfig,
);
ensureNativeAssetsBuildSucceed(result);
final List<AssetImpl> nativeAssets = result.assets;
final Set<Uri> dependencies = result.dependencies.toSet();
ensureNativeAssetsBuildSucceed(buildResult);
final LinkResult linkResult = await buildRunner.link(
linkModePreference: LinkModePreferenceImpl.dynamic,
target: target,
buildMode: buildModeCli,
workingDirectory: projectUri,
includeParentEnvironment: true,
cCompilerConfig: await buildRunner.ndkCCompilerConfigImpl,
buildResult: buildResult,
);
ensureNativeAssetsLinkSucceed(linkResult);
final List<AssetImpl> nativeAssets = <AssetImpl>[
...buildResult.assets,
...linkResult.assets,
];
final Set<Uri> dependencies = <Uri>{
...buildResult.dependencies,
...linkResult.dependencies,
};
ensureNoLinkModeStatic(nativeAssets);
globals.logger.printTrace('Building native assets for $target done.');
final Uri? absolutePath = flutterTester ? buildUri : null;
@ -751,10 +856,34 @@ Future<void> _copyNativeAssetsSingleArchitecture(
}
}
void ensureNativeAssetsBuildSucceed(DryRunResult result) {
void ensureNativeAssetsBuildDryRunSucceed(BuildDryRunResult result) {
if (!result.success) {
throwToolExit(
'Building (dry run) native assets failed. See the logs for more details.',
);
}
}
void ensureNativeAssetsBuildSucceed(BuildResult result) {
if (!result.success) {
throwToolExit(
'Building native assets failed. See the logs for more details.',
);
}
}
void ensureNativeAssetsLinkDryRunSucceed(LinkDryRunResult result) {
if (!result.success) {
throwToolExit(
'Linking (dry run) native assets failed. See the logs for more details.',
);
}
}
void ensureNativeAssetsLinkSucceed(LinkResult result) {
if (!result.success) {
throwToolExit(
'Linking native assets failed. See the logs for more details.',
);
}
}

View File

@ -56,8 +56,8 @@ dependencies:
cli_config: 0.2.0
graphs: 2.3.1
native_assets_builder: 0.6.1
native_assets_cli: 0.5.4
native_assets_builder: 0.7.0
native_assets_cli: 0.6.0
# We depend on very specific internal implementation details of the
# 'test' package, which change between versions, so when upgrading
@ -120,4 +120,4 @@ dartdoc:
# Exclude this package from the hosted API docs.
nodoc: true
# PUBSPEC CHECKSUM: d60f
# PUBSPEC CHECKSUM: 3f0c

View File

@ -9,11 +9,11 @@ environment:
dependencies:
cli_config: ^0.2.0
logging: ^1.2.0
native_assets_cli: ^0.5.3
native_toolchain_c: ^0.4.1
native_assets_cli: ^0.6.0
native_toolchain_c: ^0.4.2
dev_dependencies:
ffi: ^2.1.0
ffigen: ^11.0.0
ffi: ^2.1.2
ffigen: ^12.0.0
flutter_lints: ^4.0.0
test: ^1.24.9

View File

@ -117,32 +117,33 @@ void main() {
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: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
dryRunResult: 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'),
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -159,6 +160,8 @@ void main() {
await fileSystem.file(nativeAssetsYaml).readAsString(),
contains('package:bar/bar.dart'),
);
expect(buildRunner.buildDryRunInvocations, 1);
expect(buildRunner.linkDryRunInvocations, 1);
});
testUsingContext('build with assets but not enabled', () async {
@ -224,6 +227,22 @@ void main() {
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.android,
architecture: ArchitectureImpl.arm64,
file: Uri.file('libbar.so'),
),
],
),
);
await buildNativeAssetsAndroid(
androidArchs: <AndroidArch>[AndroidArch.arm64_v8a],
targetAndroidNdkApi: 21,
@ -231,22 +250,7 @@ void main() {
buildMode: BuildMode.debug,
fileSystem: fileSystem,
yamlParentDirectory: environment.buildDir.uri,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
buildResult: FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
linkMode: DynamicLoadingBundledImpl(),
os: OSImpl.android,
architecture: ArchitectureImpl.arm64,
file: Uri.file('libbar.so'),
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -259,6 +263,8 @@ void main() {
environment.buildDir.childFile('native_assets.yaml'),
exists,
);
expect(buildRunner.buildInvocations, 1);
expect(buildRunner.linkInvocations, 1);
});
// Ensure no exceptions for a non installed NDK are thrown if no native
@ -314,7 +320,6 @@ void main() {
);
});
testUsingContext('Native assets dry run error', overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isNativeAssetsEnabled: true),
ProcessManager: () => FakeProcessManager.empty(),
@ -323,24 +328,29 @@ void main() {
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),
],
dryRunResult: const FakeNativeAssetsBuilderResult(
success: false,
for (final String hook in <String>['Building', 'Linking']) {
expect(
() => dryRunNativeAssetsAndroid(
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
buildDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook (dry run) native assets failed. See the logs for more details.',
),
);
}
});
testUsingContext('Native assets build error', overrides: <Type, Generator>{
@ -351,28 +361,33 @@ void main() {
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),
],
buildResult: const FakeNativeAssetsBuilderResult(
success: false,
for (final String hook in <String>['Building', 'Linking']) {
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),
],
buildResult: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook native assets failed. See the logs for more details.',
),
);
}
});
}

View File

@ -19,8 +19,10 @@ class FakeNativeAssetsBuildRunner implements NativeAssetsBuildRunner {
this.hasPackageConfigResult = true,
this.packagesWithNativeAssetsResult = const <Package>[],
this.onBuild,
this.dryRunResult = const FakeNativeAssetsBuilderResult(),
this.buildDryRunResult = const FakeNativeAssetsBuilderResult(),
this.buildResult = const FakeNativeAssetsBuilderResult(),
this.linkResult = const FakeNativeAssetsBuilderResult(),
this.linkDryRunResult = const FakeNativeAssetsBuilderResult(),
CCompilerConfigImpl? cCompilerConfigResult,
CCompilerConfigImpl? ndkCCompilerConfigImplResult,
}) : cCompilerConfigResult = cCompilerConfigResult ?? CCompilerConfigImpl(),
@ -29,14 +31,18 @@ class FakeNativeAssetsBuildRunner implements NativeAssetsBuildRunner {
final native_assets_builder.BuildResult Function(Target)? onBuild;
final native_assets_builder.BuildResult buildResult;
final native_assets_builder.DryRunResult dryRunResult;
final native_assets_builder.LinkResult linkResult;
final native_assets_builder.BuildDryRunResult buildDryRunResult;
final native_assets_builder.LinkDryRunResult linkDryRunResult;
final bool hasPackageConfigResult;
final List<Package> packagesWithNativeAssetsResult;
final CCompilerConfigImpl cCompilerConfigResult;
final CCompilerConfigImpl ndkCCompilerConfigImplResult;
int buildInvocations = 0;
int dryRunInvocations = 0;
int buildDryRunInvocations = 0;
int linkInvocations = 0;
int linkDryRunInvocations = 0;
int hasPackageConfigInvocations = 0;
int packagesWithNativeAssetsInvocations = 0;
BuildModeImpl? lastBuildMode;
@ -58,14 +64,43 @@ class FakeNativeAssetsBuildRunner implements NativeAssetsBuildRunner {
}
@override
Future<native_assets_builder.DryRunResult> dryRun({
Future<native_assets_builder.LinkResult> link({
required bool includeParentEnvironment,
required BuildModeImpl buildMode,
required LinkModePreferenceImpl linkModePreference,
required Target target,
required Uri workingDirectory,
required native_assets_builder.BuildResult buildResult,
CCompilerConfigImpl? cCompilerConfig,
int? targetAndroidNdkApi,
IOSSdkImpl? targetIOSSdkImpl,
}) async {
linkInvocations++;
lastBuildMode = buildMode;
return linkResult;
}
@override
Future<native_assets_builder.BuildDryRunResult> buildDryRun({
required bool includeParentEnvironment,
required LinkModePreferenceImpl linkModePreference,
required OSImpl targetOS,
required Uri workingDirectory,
}) async {
dryRunInvocations++;
return dryRunResult;
buildDryRunInvocations++;
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
@ -90,9 +125,14 @@ class FakeNativeAssetsBuildRunner implements NativeAssetsBuildRunner {
}
final class FakeNativeAssetsBuilderResult
implements native_assets_builder.BuildResult {
implements
native_assets_builder.BuildResult,
native_assets_builder.BuildDryRunResult,
native_assets_builder.LinkResult,
native_assets_builder.LinkDryRunResult {
const FakeNativeAssetsBuilderResult({
this.assets = const <AssetImpl>[],
this.assetsForLinking = const <String, List<AssetImpl>>{},
this.dependencies = const <Uri>[],
this.success = true,
});
@ -100,6 +140,9 @@ final class FakeNativeAssetsBuilderResult
@override
final List<AssetImpl> assets;
@override
final Map<String, List<AssetImpl>> assetsForLinking;
@override
final List<Uri> dependencies;

View File

@ -62,7 +62,7 @@ void main() {
packagesWithNativeAssetsResult: <Package>[
Package('bar', fileSystem.currentDirectory.uri),
],
dryRunResult: FakeNativeAssetsBuilderResult(
buildDryRunResult: FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
@ -95,7 +95,9 @@ void main() {
// Hot restart does not require rerunning anything for native assets.
// The previous native assets mapping should be used.
expect(buildRunner.buildInvocations, 0);
expect(buildRunner.dryRunInvocations, 0);
expect(buildRunner.buildDryRunInvocations, 0);
expect(buildRunner.linkInvocations, 0);
expect(buildRunner.linkDryRunInvocations, 0);
expect(buildRunner.hasPackageConfigInvocations, 0);
expect(buildRunner.packagesWithNativeAssetsInvocations, 0);
}, overrides: <Type, Generator>{
@ -129,7 +131,7 @@ void main() {
packagesWithNativeAssetsResult: <Package>[
Package('bar', fileSystem.currentDirectory.uri),
],
dryRunResult: FakeNativeAssetsBuilderResult(
buildDryRunResult: FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',

View File

@ -119,32 +119,33 @@ void main() {
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: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
dryRunResult: 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'),
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -161,6 +162,8 @@ void main() {
await fileSystem.file(nativeAssetsYaml).readAsString(),
contains('package:bar/bar.dart'),
);
expect(buildRunner.buildDryRunInvocations, 1);
expect(buildRunner.linkDryRunInvocations, 1);
});
testUsingContext('build with assets but not enabled', () async {
@ -255,6 +258,23 @@ void main() {
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),
],
onBuild: (native_assets_cli.Target target) =>
FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
linkMode: DynamicLoadingBundledImpl(),
os: target.os,
architecture: target.architecture,
file: Uri.file('${target.architecture}/libbar.dylib'),
),
],
),
);
await buildNativeAssetsIOS(
darwinArchs: <DarwinArch>[DarwinArch.arm64, DarwinArch.x86_64],
environmentType: EnvironmentType.simulator,
@ -262,22 +282,7 @@ void main() {
buildMode: BuildMode.debug,
fileSystem: fileSystem,
yamlParentDirectory: environment.buildDir.uri,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
onBuild: (native_assets_cli.Target target) => FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
linkMode: DynamicLoadingBundledImpl(),
os: target.os,
architecture: target.architecture,
file: Uri.file('${target.architecture}/libbar.dylib'),
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -290,6 +295,9 @@ void main() {
environment.buildDir.childFile('native_assets.yaml'),
exists,
);
// Two archs.
expect(buildRunner.buildInvocations, 2);
expect(buildRunner.linkInvocations, 2);
});
testUsingContext('Native assets dry run error', overrides: <Type, Generator>{
@ -300,24 +308,29 @@ void main() {
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),
],
dryRunResult: const FakeNativeAssetsBuilderResult(
success: false,
for (final String hook in <String>['Building', 'Linking']) {
expect(
() => dryRunNativeAssetsIOS(
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
buildDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook (dry run) native assets failed. See the logs for more details.',
),
);
}
});
testUsingContext('Native assets build error', overrides: <Type, Generator>{
@ -328,27 +341,32 @@ void main() {
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),
],
buildResult: const FakeNativeAssetsBuilderResult(
success: false,
for (final String hook in <String>['Building', 'Linking']) {
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),
],
buildResult: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook native assets failed. See the logs for more details.',
),
);
}
});
}

View File

@ -155,32 +155,33 @@ void main() {
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: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
dryRunResult: 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'),
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -197,6 +198,8 @@ void main() {
await fileSystem.file(nativeAssetsYaml).readAsString(),
contains('package:bar/bar.dart'),
);
expect(buildRunner.buildDryRunInvocations, 1);
expect(buildRunner.linkDryRunInvocations, 1);
});
testUsingContext('build with assets but not enabled', overrides: <Type, Generator>{
@ -273,28 +276,29 @@ void main() {
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.debug,
fileSystem: fileSystem,
flutterTester: flutterTester,
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,
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -319,6 +323,8 @@ void main() {
'- libbar.so',
]),
);
expect(buildRunner.buildInvocations, 1);
expect(buildRunner.linkInvocations, 1);
});
}
@ -337,7 +343,7 @@ void main() {
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
dryRunResult: FakeNativeAssetsBuilderResult(
buildDryRunResult: FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
@ -373,24 +379,29 @@ void main() {
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),
],
dryRunResult: const FakeNativeAssetsBuilderResult(
success: false,
for (final String hook in <String>['Building', 'Linking']) {
expect(
() => dryRunNativeAssetsLinux(
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
buildDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook (dry run) native assets failed. See the logs for more details.',
),
);
}
});
testUsingContext('Native assets build error', overrides: <Type, Generator>{
@ -401,27 +412,32 @@ void main() {
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,
for (final String hook in <String>['Building', 'Linking']) {
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: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook native assets failed. See the logs for more details.',
),
);
}
});
// This logic is mocked in the other tests to avoid having test order

View File

@ -138,32 +138,33 @@ void main() {
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: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
dryRunResult: 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'),
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -180,6 +181,8 @@ void main() {
await fileSystem.file(nativeAssetsYaml).readAsString(),
contains('package:bar/bar.dart'),
);
expect(buildRunner.buildDryRunInvocations, 1);
expect(buildRunner.linkDryRunInvocations, 1);
});
testUsingContext('build with assets but not enabled', overrides: <Type, Generator>{
@ -293,28 +296,30 @@ void main() {
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),
],
onBuild: (native_assets_cli.Target target) =>
FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
linkMode: DynamicLoadingBundledImpl(),
os: target.os,
architecture: target.architecture,
file: Uri.file('${target.architecture}/libbar.dylib'),
),
],
),
);
final (Uri? nativeAssetsYaml, _) = await buildNativeAssetsMacOS(
darwinArchs: <DarwinArch>[DarwinArch.arm64, DarwinArch.x86_64],
projectUri: projectUri,
buildMode: BuildMode.debug,
fileSystem: fileSystem,
flutterTester: flutterTester,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
onBuild: (native_assets_cli.Target target) => FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
linkMode: DynamicLoadingBundledImpl(),
os: target.os,
architecture: target.architecture,
file: Uri.file('${target.architecture}/libbar.dylib'),
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -339,6 +344,9 @@ void main() {
'- bar.framework/bar',
]),
);
// Multi arch.
expect(buildRunner.buildInvocations, 2);
expect(buildRunner.linkInvocations, 2);
});
}
@ -357,7 +365,7 @@ void main() {
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
dryRunResult: FakeNativeAssetsBuilderResult(
buildDryRunResult: FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
@ -395,24 +403,29 @@ void main() {
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),
],
dryRunResult: const FakeNativeAssetsBuilderResult(
success: false,
for (final String hook in <String>['Building', 'Linking']) {
expect(
() => dryRunNativeAssetsMacOS(
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
buildDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook (dry run) native assets failed. See the logs for more details.',
),
);
}
});
testUsingContext('Native assets build error', overrides: <Type, Generator>{
@ -423,27 +436,32 @@ void main() {
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,
for (final String hook in <String>['Building', 'Linking']) {
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: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook native assets failed. See the logs for more details.',
),
);
}
});
// This logic is mocked in the other tests to avoid having test order

View File

@ -81,7 +81,9 @@ void main() {
expect(result, 0);
expect(buildRunner.buildInvocations, 0);
expect(buildRunner.dryRunInvocations, 0);
expect(buildRunner.buildDryRunInvocations, 0);
expect(buildRunner.linkInvocations, 0);
expect(buildRunner.linkDryRunInvocations, 0);
expect(buildRunner.hasPackageConfigInvocations, 0);
expect(buildRunner.packagesWithNativeAssetsInvocations, 0);

View File

@ -135,25 +135,26 @@ void main() {
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: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
dryRunResult: FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
linkMode: DynamicLoadingBundledImpl(),
os: OSImpl.windows,
architecture: ArchitectureImpl.x64,
file: Uri.file('bar.dll'),
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -170,6 +171,8 @@ void main() {
await fileSystem.file(nativeAssetsYaml).readAsString(),
contains('package:bar/bar.dart'),
);
expect(buildRunner.buildDryRunInvocations, 1);
expect(buildRunner.linkDryRunInvocations, 1);
});
testUsingContext('build with assets but not enabled', overrides: <Type, Generator>{
@ -243,28 +246,29 @@ void main() {
final File dylibAfterCompiling = fileSystem.file('bar.dll');
// 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.windows,
architecture: ArchitectureImpl.x64,
file: dylibAfterCompiling.uri,
),
],
),
);
final (Uri? nativeAssetsYaml, _) = await buildNativeAssetsWindows(
targetPlatform: TargetPlatform.windows_x64,
projectUri: projectUri,
buildMode: BuildMode.debug,
fileSystem: fileSystem,
flutterTester: flutterTester,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
buildResult: FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
linkMode: DynamicLoadingBundledImpl(),
os: OSImpl.windows,
architecture: ArchitectureImpl.x64,
file: dylibAfterCompiling.uri,
),
],
),
),
buildRunner: buildRunner,
);
expect(
(globals.logger as BufferLogger).traceText,
@ -289,6 +293,8 @@ void main() {
'- bar.dll',
]),
);
expect(buildRunner.buildInvocations, 1);
expect(buildRunner.linkInvocations, 1);
});
}
@ -307,7 +313,7 @@ void main() {
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
dryRunResult: FakeNativeAssetsBuilderResult(
buildDryRunResult: FakeNativeAssetsBuilderResult(
assets: <AssetImpl>[
NativeCodeAssetImpl(
id: 'package:bar/bar.dart',
@ -338,24 +344,29 @@ void main() {
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),
],
dryRunResult: const FakeNativeAssetsBuilderResult(
success: false,
for (final String hook in <String>['Building', 'Linking']) {
expect(
() => dryRunNativeAssetsWindows(
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('bar', projectUri),
],
buildDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkDryRunResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook (dry run) native assets failed. See the logs for more details.',
),
);
}
});
testUsingContext('Native assets build error', overrides: <Type, Generator>{
@ -366,27 +377,32 @@ void main() {
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,
for (final String hook in <String>['Building', 'Linking']) {
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: FakeNativeAssetsBuilderResult(
success: hook != 'Building',
),
linkResult: FakeNativeAssetsBuilderResult(
success: hook != 'Linking',
),
),
),
),
throwsToolExit(
message:
'Building native assets failed. See the logs for more details.',
),
);
throwsToolExit(
message:
'$hook native assets failed. See the logs for more details.',
),
);
}
});
// This logic is mocked in the other tests to avoid having test order

View File

@ -550,6 +550,8 @@ Future<Directory> createTestProject(String packageName, Directory tempDirectory)
await pinDependencies(
packageDirectory.childDirectory('example').childFile('pubspec.yaml'));
await addLinkHookDepedendency(packageDirectory);
final ProcessResult result2 = await processManager.run(
<String>[
flutterBin,
@ -563,6 +565,52 @@ Future<Directory> createTestProject(String packageName, Directory tempDirectory)
return packageDirectory;
}
Future<void> addLinkHookDepedendency(Directory packageDirectory) async {
final Directory flutterDirectory = fileSystem.currentDirectory.parent.parent;
final Directory linkHookDirectory = flutterDirectory
.childDirectory('dev')
.childDirectory('integration_tests')
.childDirectory('link_hook');
expect(linkHookDirectory, exists);
final File pubspecFile = packageDirectory.childFile('pubspec.yaml');
final String pubspecOld =
(await pubspecFile.readAsString()).replaceAll('\r\n', '\n');
final String pubspecNew = pubspecOld.replaceFirst('''
dependencies:
''', '''
dependencies:
link_hook:
path: ${linkHookDirectory.path}
''');
expect(pubspecNew, isNot(pubspecOld));
await pubspecFile.writeAsString(pubspecNew);
final File dartFile =
packageDirectory.childDirectory('lib').childFile('$packageName.dart');
final String dartFileOld =
(await dartFile.readAsString()).replaceAll('\r\n', '\n');
// Replace with something that results in the same resulting int, so that the
// tests don't have to be updated.
final String dartFileNew = dartFileOld.replaceFirst(
'''
import '${packageName}_bindings_generated.dart' as bindings;
''',
'''
import 'package:link_hook/link_hook.dart' as l;
import '${packageName}_bindings_generated.dart' as bindings;
''',
);
expect(dartFileNew, isNot(dartFileOld));
final String dartFileNew2 = dartFileNew.replaceFirst(
'int sum(int a, int b) => bindings.sum(a, b);',
'int sum(int a, int b) => bindings.sum(a, b) + l.difference(2, 1) - 1;',
);
expect(dartFileNew2, isNot(dartFileNew));
await dartFile.writeAsString(dartFileNew2);
}
Future<void> pinDependencies(File pubspecFile) async {
expect(pubspecFile, exists);
final String oldPubspec = await pubspecFile.readAsString();