[native assets] Roll dependencies (#162017)

This PR rolls in a number of breaking changes for native assets:

* Pub workspaces are now supported, this requires a refactoring to how
the `NativeAssetsBuildRunner` is used. Most notably it requires being
explicit about the `runPackageName`. Flutter does not seem to have that
value, but it does have the `projectUri` which can be used to find the
package name via the package config.
* The API for build hooks has been redesigned. This PR updates the
project template, test project files, and test project strings.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
Daco Harkes 2025-01-23 10:22:36 +01:00 committed by GitHub
parent 97ca57cf08
commit 9ded795e63
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 185 additions and 184 deletions

View File

@ -8,13 +8,13 @@ import 'package:native_assets_cli/code_assets_builder.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
void main(List<String> args) async {
await build(args, (BuildConfig config, BuildOutputBuilder output) async {
if (!config.buildAssetTypes.contains(CodeAsset.type)) {
await build(args, (BuildInput input, BuildOutputBuilder output) async {
if (!input.config.buildAssetTypes.contains(CodeAsset.type)) {
return;
}
final String assetName;
if (config.linkingEnabled) {
if (input.config.linkingEnabled) {
// The link hook will be run. So emit an asset with a name that is
// not used, so that the link hook can rename it.
// This will ensure the test fails if the link-hooks are not run
@ -23,9 +23,9 @@ void main(List<String> args) async {
} else {
// The link hook will not be run, so immediately emit an asset for
// bundling.
assetName = '${config.packageName}_bindings_generated.dart';
assetName = '${input.packageName}_bindings_generated.dart';
}
final String packageName = config.packageName;
final String packageName = input.packageName;
final CBuilder cbuilder = CBuilder.library(
name: packageName,
assetName: assetName,
@ -34,19 +34,19 @@ void main(List<String> args) async {
);
final BuildOutputBuilder outputCatcher = BuildOutputBuilder();
await cbuilder.run(
config: config,
input: input,
output: outputCatcher,
logger:
Logger('')
..level = Level.ALL
..onRecord.listen((LogRecord record) => print(record.message)),
);
final BuildOutput catchedOutput = BuildOutput(outputCatcher.json);
output.addDependencies(catchedOutput.dependencies);
final BuildOutput caughtOutput = BuildOutput(outputCatcher.json);
output.addDependencies(caughtOutput.dependencies);
// Send the asset to hook/link.dart or immediately for bundling.
output.codeAssets.add(
catchedOutput.codeAssets.single,
linkInPackage: config.linkingEnabled ? 'link_hook' : null,
output.assets.code.add(
caughtOutput.assets.code.single,
linkInPackage: input.config.linkingEnabled ? 'link_hook' : null,
);
});
}

View File

@ -5,13 +5,13 @@
import 'package:native_assets_cli/code_assets.dart';
void main(List<String> args) async {
await link(args, (LinkConfig config, LinkOutputBuilder output) async {
if (!config.buildAssetTypes.contains(CodeAsset.type)) {
await link(args, (LinkInput input, LinkOutputBuilder output) async {
if (!input.config.buildAssetTypes.contains(CodeAsset.type)) {
return;
}
final CodeAsset asset = config.codeAssets.single;
final String packageName = config.packageName;
output.codeAssets.add(
final CodeAsset asset = input.assets.code.single;
final String packageName = input.packageName;
output.assets.code.add(
CodeAsset(
package: packageName,
// Change the asset id to something that is used.
@ -22,6 +22,5 @@ void main(List<String> args) async {
file: asset.file,
),
);
output.addDependency(config.packageRoot.resolve('hook/link.dart'));
});
}

View File

@ -7,8 +7,8 @@ environment:
dependencies:
logging: 1.3.0
native_assets_cli: 0.10.0
native_toolchain_c: 0.7.0
native_assets_cli: 0.11.0
native_toolchain_c: 0.8.0
async: 2.12.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
collection: 1.19.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@ -68,4 +68,4 @@ dev_dependencies:
webkit_inspection_protocol: 1.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
yaml_edit: 2.2.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
# PUBSPEC CHECKSUM: 566e
# PUBSPEC CHECKSUM: d670

View File

@ -39,6 +39,8 @@ abstract class DartBuild extends Target {
logger: environment.logger,
);
final Uri projectUri = environment.projectDir.uri;
final String? runPackageName =
packageConfig.packages.where((Package p) => p.root == projectUri).firstOrNull?.name;
final FlutterNativeAssetsBuildRunner buildRunner =
_buildRunner ??
FlutterNativeAssetsBuildRunnerImpl(
@ -46,6 +48,7 @@ abstract class DartBuild extends Target {
packageConfig,
fileSystem,
environment.logger,
runPackageName!,
);
result = await runFlutterSpecificDartBuild(
environmentDefines: environment.defines,

View File

@ -7,7 +7,6 @@
import 'package:logging/logging.dart' as logging;
import 'package:native_assets_builder/native_assets_builder.dart';
import 'package:native_assets_cli/code_assets_builder.dart';
import 'package:native_assets_cli/native_assets_cli_internal.dart';
import 'package:package_config/package_config_types.dart';
import '../../base/common.dart';
@ -151,13 +150,13 @@ Future<void> installCodeAssets({
/// It also enables mocking native toolchain discovery via [cCompilerConfig].
abstract interface class FlutterNativeAssetsBuildRunner {
/// All packages in the transitive dependencies that have a `build.dart`.
Future<List<Package>> packagesWithNativeAssets();
Future<List<String>> packagesWithNativeAssets();
/// Runs all [packagesWithNativeAssets] `build.dart`.
Future<BuildResult?> build({
required List<String> buildAssetTypes,
required BuildConfigValidator configValidator,
required BuildConfigCreator configCreator,
required BuildInputValidator inputValidator,
required BuildInputCreator inputCreator,
required BuildValidator buildValidator,
required ApplicationAssetValidator applicationAssetValidator,
required Uri workingDirectory,
@ -167,8 +166,8 @@ abstract interface class FlutterNativeAssetsBuildRunner {
/// Runs all [packagesWithNativeAssets] `link.dart`.
Future<LinkResult?> link({
required List<String> buildAssetTypes,
required LinkConfigValidator configValidator,
required LinkConfigCreator configCreator,
required LinkInputValidator inputValidator,
required LinkInputCreator inputCreator,
required LinkValidator linkValidator,
required ApplicationAssetValidator applicationAssetValidator,
required Uri workingDirectory,
@ -189,12 +188,14 @@ class FlutterNativeAssetsBuildRunnerImpl implements FlutterNativeAssetsBuildRunn
this.packageConfig,
this.fileSystem,
this.logger,
this.runPackageName,
);
final String packageConfigPath;
final PackageConfig packageConfig;
final FileSystem fileSystem;
final Logger logger;
final String runPackageName;
late final logging.Logger _logger = logging.Logger('')
..onRecord.listen((logging.LogRecord record) {
@ -221,48 +222,44 @@ class FlutterNativeAssetsBuildRunnerImpl implements FlutterNativeAssetsBuildRunn
.uri
.resolve('bin/cache/dart-sdk/bin/dart');
late final PackageLayout packageLayout = PackageLayout.fromPackageConfig(
fileSystem,
packageConfig,
Uri.file(packageConfigPath),
runPackageName,
);
late final NativeAssetsBuildRunner _buildRunner = NativeAssetsBuildRunner(
logger: _logger,
dartExecutable: _dartExecutable,
fileSystem: fileSystem,
packageLayout: packageLayout,
);
@override
Future<List<Package>> packagesWithNativeAssets() async {
final PackageLayout packageLayout = PackageLayout.fromPackageConfig(
fileSystem,
packageConfig,
Uri.file(packageConfigPath),
);
Future<List<String>> packagesWithNativeAssets() async {
// 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);
return _buildRunner.packagesWithBuildHooks();
}
@override
Future<BuildResult?> build({
required List<String> buildAssetTypes,
required BuildConfigValidator configValidator,
required BuildConfigCreator configCreator,
required BuildInputValidator inputValidator,
required BuildInputCreator inputCreator,
required BuildValidator buildValidator,
required ApplicationAssetValidator applicationAssetValidator,
required Uri workingDirectory,
required bool linkingEnabled,
}) {
final PackageLayout packageLayout = PackageLayout.fromPackageConfig(
fileSystem,
packageConfig,
Uri.file(packageConfigPath),
);
return _buildRunner.build(
buildAssetTypes: buildAssetTypes,
configCreator: configCreator,
configValidator: configValidator,
inputCreator: inputCreator,
inputValidator: inputValidator,
buildValidator: buildValidator,
applicationAssetValidator: applicationAssetValidator,
workingDirectory: workingDirectory,
packageLayout: packageLayout,
linkingEnabled: linkingEnabled,
);
}
@ -270,26 +267,19 @@ class FlutterNativeAssetsBuildRunnerImpl implements FlutterNativeAssetsBuildRunn
@override
Future<LinkResult?> link({
required List<String> buildAssetTypes,
required LinkConfigValidator configValidator,
required LinkConfigCreator configCreator,
required LinkInputValidator inputValidator,
required LinkInputCreator inputCreator,
required LinkValidator linkValidator,
required ApplicationAssetValidator applicationAssetValidator,
required Uri workingDirectory,
required BuildResult buildResult,
}) {
final PackageLayout packageLayout = PackageLayout.fromPackageConfig(
fileSystem,
packageConfig,
Uri.file(packageConfigPath),
);
return _buildRunner.link(
buildAssetTypes: buildAssetTypes,
configCreator: configCreator,
configValidator: configValidator,
inputCreator: inputCreator,
inputValidator: inputValidator,
linkValidator: linkValidator,
applicationAssetValidator: applicationAssetValidator,
workingDirectory: workingDirectory,
packageLayout: packageLayout,
buildResult: buildResult,
);
}
@ -373,7 +363,7 @@ bool _nativeAssetsLinkingEnabled(BuildMode buildMode) {
}
Future<bool> _nativeBuildRequired(FlutterNativeAssetsBuildRunner buildRunner) async {
final List<Package> packagesWithNativeAssets = await buildRunner.packagesWithNativeAssets();
final List<String> packagesWithNativeAssets = await buildRunner.packagesWithNativeAssets();
if (packagesWithNativeAssets.isEmpty) {
globals.logger.printTrace(
'No packages with native assets. Skipping native assets compilation.',
@ -382,7 +372,7 @@ Future<bool> _nativeBuildRequired(FlutterNativeAssetsBuildRunner buildRunner) as
}
if (!featureFlags.isNativeAssetsEnabled) {
final String packageNames = packagesWithNativeAssets.map((Package p) => p.name).join(' ');
final String packageNames = packagesWithNativeAssets.join(' ');
throwToolExit(
'Package(s) $packageNames require the native assets feature to be enabled. '
'Enable using `flutter config --enable-native-assets`.',
@ -401,14 +391,14 @@ Future<void> ensureNoNativeAssetsOrOsIsSupported(
FileSystem fileSystem,
FlutterNativeAssetsBuildRunner buildRunner,
) async {
final List<Package> packagesWithNativeAssets = await buildRunner.packagesWithNativeAssets();
final List<String> packagesWithNativeAssets = await buildRunner.packagesWithNativeAssets();
if (packagesWithNativeAssets.isEmpty) {
globals.logger.printTrace(
'No packages with native assets. Skipping native assets compilation.',
);
return;
}
final String packageNames = packagesWithNativeAssets.map((Package p) => p.name).join(' ');
final String packageNames = packagesWithNativeAssets.join(' ');
throwToolExit(
'Package(s) $packageNames require the native assets feature. '
'This feature has not yet been implemented for `$os`. '
@ -599,34 +589,35 @@ Future<DartBuildResult> _runDartBuild({
final String? codesignIdentity = environmentDefines[kCodesignIdentity];
assert(codesignIdentity == null || targetOS == OS.iOS || targetOS == OS.macOS);
final AndroidConfig? androidConfig =
final AndroidCodeConfig? androidConfig =
targetOS == OS.android
? AndroidConfig(targetNdkApi: targetAndroidNdkApi(environmentDefines))
? AndroidCodeConfig(targetNdkApi: targetAndroidNdkApi(environmentDefines))
: null;
final IOSConfig? iosConfig =
final IOSCodeConfig? iosConfig =
targetOS == OS.iOS
? IOSConfig(targetVersion: targetIOSVersion, targetSdk: getIOSSdk(environmentType!))
? IOSCodeConfig(targetVersion: targetIOSVersion, targetSdk: getIOSSdk(environmentType!))
: null;
final MacOSConfig? macOSConfig =
targetOS == OS.macOS ? MacOSConfig(targetVersion: targetMacOSVersion) : null;
final MacOSCodeConfig? macOSConfig =
targetOS == OS.macOS ? MacOSCodeConfig(targetVersion: targetMacOSVersion) : null;
for (final Architecture architecture in architectures) {
final BuildResult? buildResult = await buildRunner.build(
buildAssetTypes: <String>[CodeAsset.type],
configCreator:
inputCreator:
() =>
BuildConfigBuilder()..setupCodeConfig(
BuildInputBuilder()
..config.setupCode(
targetArchitecture: architecture,
linkModePreference: LinkModePreference.dynamic,
cCompilerConfig: cCompilerConfig,
cCompiler: cCompilerConfig,
targetOS: targetOS!,
androidConfig: androidConfig,
iOSConfig: iosConfig,
macOSConfig: macOSConfig,
android: androidConfig,
iOS: iosConfig,
macOS: macOSConfig,
),
configValidator:
(BuildConfig config) async => <String>[...await validateCodeAssetBuildConfig(config)],
inputValidator:
(BuildInput config) async => <String>[...await validateCodeAssetBuildInput(config)],
buildValidator:
(BuildConfig config, BuildOutput output) async => <String>[
(BuildInput config, BuildOutput output) async => <String>[
...await validateCodeAssetBuildOutput(config, output),
],
applicationAssetValidator:
@ -645,21 +636,22 @@ Future<DartBuildResult> _runDartBuild({
} else {
final LinkResult? linkResult = await buildRunner.link(
buildAssetTypes: <String>[CodeAsset.type],
configCreator:
inputCreator:
() =>
LinkConfigBuilder()..setupCodeConfig(
LinkInputBuilder()
..config.setupCode(
targetArchitecture: architecture,
linkModePreference: LinkModePreference.dynamic,
cCompilerConfig: cCompilerConfig,
cCompiler: cCompilerConfig,
targetOS: targetOS!,
androidConfig: androidConfig,
iOSConfig: iosConfig,
macOSConfig: macOSConfig,
android: androidConfig,
iOS: iosConfig,
macOS: macOSConfig,
),
configValidator:
(LinkConfig config) async => <String>[...await validateCodeAssetLinkConfig(config)],
inputValidator:
(LinkInput config) async => <String>[...await validateCodeAssetLinkInput(config)],
linkValidator:
(LinkConfig config, LinkOutput output) async => <String>[
(LinkInput config, LinkOutput output) async => <String>[
...await validateCodeAssetLinkOutput(config, output),
],
applicationAssetValidator:

View File

@ -5,6 +5,7 @@
// Logic for native assets shared between all host OSes.
import 'package:native_assets_cli/code_assets.dart' show OS;
import 'package:package_config/package_config_types.dart';
import '../../../base/platform.dart';
import '../../../build_info.dart';
@ -29,11 +30,14 @@ Future<Uri?> testCompilerBuildNativeAssets(BuildInfo buildInfo) async {
return null;
}
final Uri projectUri = FlutterProject.current().directory.uri;
final String runPackageName =
buildInfo.packageConfig.packages.firstWhere((Package p) => p.root == projectUri).name;
final FlutterNativeAssetsBuildRunner buildRunner = FlutterNativeAssetsBuildRunnerImpl(
buildInfo.packageConfigPath,
buildInfo.packageConfig,
globals.fs,
globals.logger,
runPackageName,
);
if (!globals.platform.isMacOS && !globals.platform.isLinux && !globals.platform.isWindows) {

View File

@ -30,8 +30,9 @@ Future<CCompilerConfig?> cCompilerConfigWindows() async {
compiler: compiler,
archiver: archiver,
linker: linker,
envScript: envScript,
envScriptArgs: <String>[],
windows: WindowsCCompilerConfig(
developerCommandPrompt: DeveloperCommandPrompt(script: envScript, arguments: <String>[]),
),
);
}

View File

@ -27,9 +27,9 @@ const Map<String, String> kManuallyPinnedDependencies = <String, String>{
'intl':
'0.19.0', // 0.20.0 introduces new transitive dependencies that are not (yet) cleared in Flutter's allow list.
'native_assets_builder':
'0.10.2', // Under active development with breaking changes until 1.0.0. Manually rolled by @dcharkes.
'0.11.0', // Under active development with breaking changes until 1.0.0. Manually rolled by @dcharkes.
'native_assets_cli':
'0.10.0', // Under active development with breaking changes until 1.0.0. Manually rolled by @dcharkes.
'0.11.0', // Under active development with breaking changes until 1.0.0. Manually rolled by @dcharkes.
'material_color_utilities': '0.11.1', // Keep pinned to latest until 1.0.0.
'leak_tracker': '10.0.8', // https://github.com/flutter/devtools/issues/3951
'leak_tracker_testing': '3.0.1', // https://github.com/flutter/devtools/issues/3951

View File

@ -54,8 +54,8 @@ dependencies:
unified_analytics: 7.0.1
graphs: 2.3.2
native_assets_builder: 0.10.2
native_assets_cli: 0.10.0
native_assets_builder: 0.11.0
native_assets_cli: 0.11.0
# We depend on very specific internal implementation details of the
# 'test' package, which change between versions, so when upgrading
@ -121,4 +121,4 @@ dartdoc:
# Exclude this package from the hosted API docs.
nodoc: true
# PUBSPEC CHECKSUM: 6539
# PUBSPEC CHECKSUM: 3b39

View File

@ -3,8 +3,8 @@ import 'package:logging/logging.dart';
import 'package:native_assets_cli/native_assets_cli.dart';
void main(List<String> args) async {
await build(args, (config, output) async {
final packageName = config.packageName;
await build(args, (input, output) async {
final packageName = input.packageName;
final cbuilder = CBuilder.library(
name: packageName,
assetName: '${packageName}_bindings_generated.dart',
@ -13,7 +13,7 @@ void main(List<String> args) async {
],
);
await cbuilder.run(
config: config,
input: input,
output: output,
logger: Logger('')
..level = Level.ALL

View File

@ -8,8 +8,8 @@ environment:
dependencies:
logging: ^1.2.0
native_assets_cli: ^0.10.0
native_toolchain_c: ^0.7.0
native_assets_cli: ^0.11.0
native_toolchain_c: ^0.8.0
dev_dependencies:
ffi: ^2.1.3

View File

@ -18,7 +18,6 @@ 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/code_assets_builder.dart';
import 'package:package_config/package_config_types.dart';
import '../../../src/common.dart';
import '../../../src/context.dart';
@ -82,7 +81,7 @@ void main() {
),
];
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
buildResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(codeAssets: codeAssets),
linkResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(codeAssets: codeAssets),
);
@ -164,9 +163,7 @@ void main() {
targetPlatform: TargetPlatform.android_arm64,
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: _BuildRunnerWithoutNdk(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
),
buildRunner: _BuildRunnerWithoutNdk(packagesWithNativeAssetsResult: <String>['bar']),
),
throwsToolExit(message: 'Android NDK Clang could not be found.'),
);
@ -175,7 +172,7 @@ void main() {
}
class _BuildRunnerWithoutNdk extends FakeFlutterNativeAssetsBuildRunner {
_BuildRunnerWithoutNdk({super.packagesWithNativeAssetsResult = const <Package>[]});
_BuildRunnerWithoutNdk({super.packagesWithNativeAssetsResult = const <String>[]});
@override
Future<CCompilerConfig> get ndkCCompilerConfig async =>

View File

@ -14,7 +14,6 @@ import 'package:flutter_tools/src/build_system/targets/native_assets.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/isolated/native_assets/native_assets.dart';
import 'package:native_assets_cli/code_assets_builder.dart';
import 'package:package_config/package_config.dart' show Package;
import '../../../../src/common.dart';
import '../../../../src/context.dart';
@ -94,7 +93,7 @@ void main() {
await createPackageConfig(iosEnvironment);
final FlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('foo', iosEnvironment.projectDir.uri)],
packagesWithNativeAssetsResult: <String>['foo'],
);
iosEnvironment.defines.remove(kSdkRoot);
@ -200,7 +199,7 @@ void main() {
),
];
final FlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('foo', iosEnvironment.buildDir.uri)],
packagesWithNativeAssetsResult: <String>['foo'],
buildResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: codeAssets,
dependencies: <Uri>[Uri.file('src/foo.c')],
@ -268,9 +267,7 @@ void main() {
),
];
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[
Package('foo', androidEnvironment.buildDir.uri),
],
packagesWithNativeAssetsResult: <String>['foo'],
buildResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: codeAssets,
dependencies: <Uri>[Uri.file('src/foo.c')],

View File

@ -5,7 +5,6 @@
import 'package:flutter_tools/src/isolated/native_assets/native_assets.dart';
import 'package:native_assets_builder/native_assets_builder.dart';
import 'package:native_assets_cli/code_assets_builder.dart';
import 'package:package_config/package_config_types.dart';
export 'package:native_assets_cli/code_assets_builder.dart' show CodeAsset, DynamicLoadingBundled;
@ -13,7 +12,7 @@ export 'package:native_assets_cli/code_assets_builder.dart' show CodeAsset, Dyna
/// relies on doing process calls to `pub` and the local file system.
class FakeFlutterNativeAssetsBuildRunner implements FlutterNativeAssetsBuildRunner {
FakeFlutterNativeAssetsBuildRunner({
this.packagesWithNativeAssetsResult = const <Package>[],
this.packagesWithNativeAssetsResult = const <String>[],
this.onBuild,
this.onLink,
this.buildResult = const FakeFlutterNativeAssetsBuilderResult(),
@ -22,11 +21,12 @@ class FakeFlutterNativeAssetsBuildRunner implements FlutterNativeAssetsBuildRunn
this.ndkCCompilerConfigResult,
});
final BuildResult? Function(BuildConfig)? onBuild;
final LinkResult? Function(LinkConfig)? onLink;
// TODO(dcharkes): Cleanup this fake https://github.com/flutter/flutter/issues/162061
final BuildResult? Function(BuildInput)? onBuild;
final LinkResult? Function(LinkInput)? onLink;
final BuildResult? buildResult;
final LinkResult? linkResult;
final List<Package> packagesWithNativeAssetsResult;
final List<String> packagesWithNativeAssetsResult;
final CCompilerConfig? cCompilerConfigResult;
final CCompilerConfig? ndkCCompilerConfigResult;
@ -37,28 +37,28 @@ class FakeFlutterNativeAssetsBuildRunner implements FlutterNativeAssetsBuildRunn
@override
Future<BuildResult?> build({
required List<String> buildAssetTypes,
required BuildConfigValidator configValidator,
required BuildConfigCreator configCreator,
required BuildInputValidator inputValidator,
required BuildInputCreator inputCreator,
required BuildValidator buildValidator,
required ApplicationAssetValidator applicationAssetValidator,
required Uri workingDirectory,
required bool linkingEnabled,
}) async {
BuildResult? result = buildResult;
for (final Package package in packagesWithNativeAssetsResult) {
final BuildConfigBuilder configBuilder =
configCreator()
..setupHookConfig(
packageRoot: package.root,
packageName: package.name,
buildAssetTypes: buildAssetTypes,
)
..setupBuildConfig(dryRun: false, linkingEnabled: linkingEnabled)
..setupBuildRunConfig(
for (final String package in packagesWithNativeAssetsResult) {
final BuildInputBuilder configBuilder =
inputCreator()
..setupShared(
packageRoot: Uri.parse('$package/'),
packageName: package,
outputDirectory: Uri.parse('build-out-dir'),
outputDirectoryShared: Uri.parse('build-out-dir-shared'),
);
final BuildConfig buildConfig = BuildConfig(configBuilder.json);
outputFile: Uri.file('output.json'),
)
..setupBuildInput()
..config.setupShared(buildAssetTypes: buildAssetTypes)
..config.setupBuild(dryRun: false, linkingEnabled: linkingEnabled);
final BuildInput buildConfig = BuildInput(configBuilder.json);
if (onBuild != null) {
result = onBuild!(buildConfig);
}
@ -70,28 +70,27 @@ class FakeFlutterNativeAssetsBuildRunner implements FlutterNativeAssetsBuildRunn
@override
Future<LinkResult?> link({
required List<String> buildAssetTypes,
required LinkConfigCreator configCreator,
required LinkConfigValidator configValidator,
required LinkInputCreator inputCreator,
required LinkInputValidator inputValidator,
required LinkValidator linkValidator,
required ApplicationAssetValidator applicationAssetValidator,
required Uri workingDirectory,
required BuildResult buildResult,
}) async {
LinkResult? result = linkResult;
for (final Package package in packagesWithNativeAssetsResult) {
final LinkConfigBuilder configBuilder =
configCreator()
..setupHookConfig(
packageRoot: package.root,
packageName: package.name,
buildAssetTypes: buildAssetTypes,
)
..setupLinkRunConfig(
for (final String package in packagesWithNativeAssetsResult) {
final LinkInputBuilder configBuilder =
inputCreator()
..setupShared(
packageRoot: Uri.parse('$package/'),
packageName: package,
outputDirectory: Uri.parse('build-out-dir'),
outputDirectoryShared: Uri.parse('build-out-dir-shared'),
recordedUsesFile: null,
);
final LinkConfig buildConfig = LinkConfig(configBuilder.json);
outputFile: Uri.file('output.json'),
)
..setupLink(assets: buildResult.encodedAssets, recordedUsesFile: null)
..config.setupShared(buildAssetTypes: buildAssetTypes);
final LinkInput buildConfig = LinkInput(configBuilder.json);
if (onLink != null) {
result = onLink!(buildConfig);
}
@ -101,7 +100,7 @@ class FakeFlutterNativeAssetsBuildRunner implements FlutterNativeAssetsBuildRunn
}
@override
Future<List<Package>> packagesWithNativeAssets() async {
Future<List<String>> packagesWithNativeAssets() async {
packagesWithNativeAssetsInvocations++;
return packagesWithNativeAssetsResult;
}

View File

@ -16,7 +16,6 @@ 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/code_assets_builder.dart';
import 'package:package_config/package_config_types.dart';
import '../../../src/common.dart';
import '../../../src/context.dart';
@ -182,17 +181,17 @@ void main() {
),
];
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
onBuild:
(BuildConfig config) => FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: codeAssets(config.codeConfig.targetOS, config.codeConfig),
(BuildInput input) => FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: codeAssets(input.config.code.targetOS, input.config.code),
),
onLink:
(LinkConfig config) =>
(LinkInput input) =>
buildMode == BuildMode.debug
? null
: FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: codeAssets(config.codeConfig.targetOS, config.codeConfig),
codeAssets: codeAssets(input.config.code.targetOS, input.config.code),
),
);
final Map<String, String> environmentDefines = <String, String>{

View File

@ -30,6 +30,7 @@ void main() {
late FileSystem fileSystem;
late BufferLogger logger;
late Uri projectUri;
late String runPackageName;
setUp(() {
processManager = FakeProcessManager.empty();
@ -46,6 +47,7 @@ void main() {
);
environment.buildDir.createSync(recursive: true);
projectUri = environment.projectDir.uri;
runPackageName = environment.projectDir.basename;
});
testUsingContext(
@ -116,6 +118,7 @@ void main() {
packageConfig,
fileSystem,
logger,
runPackageName,
);
final CCompilerConfig result = (await runner.cCompilerConfig)!;
expect(result.compiler, Uri.file('/some/path/to/clang'));

View File

@ -30,6 +30,7 @@ void main() {
late FileSystem fileSystem;
late BufferLogger logger;
late Uri projectUri;
late String runPackageName;
setUp(() {
processManager = FakeProcessManager.empty();
@ -46,6 +47,7 @@ void main() {
);
environment.buildDir.createSync(recursive: true);
projectUri = environment.projectDir.uri;
runPackageName = environment.projectDir.basename;
});
for (final bool flutterTester in <bool>[false, true]) {
@ -278,17 +280,17 @@ void main() {
),
];
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
onBuild:
(BuildConfig config) => FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: codeAssets(config.codeConfig.targetOS, config.codeConfig),
(BuildInput input) => FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: codeAssets(input.config.code.targetOS, input.config.code),
),
onLink:
(LinkConfig config) =>
(LinkInput input) =>
buildMode == BuildMode.debug
? null
: FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: codeAssets(config.codeConfig.targetOS, config.codeConfig),
codeAssets: codeAssets(input.config.code.targetOS, input.config.code),
),
);
final Map<String, String> environmentDefines = <String, String>{
@ -401,6 +403,7 @@ InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault
packageConfig,
fileSystem,
logger,
runPackageName,
);
final CCompilerConfig result = (await runner.cCompilerConfig)!;
expect(

View File

@ -14,7 +14,6 @@ import 'package:flutter_tools/src/build_system/targets/native_assets.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/isolated/native_assets/native_assets.dart';
import 'package:native_assets_cli/code_assets_builder.dart';
import 'package:package_config/package_config_types.dart';
import '../../src/common.dart';
import '../../src/context.dart';
@ -84,7 +83,7 @@ void main() {
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
buildResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(codeAssets: codeAssets),
linkResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(codeAssets: codeAssets),
),
@ -115,7 +114,7 @@ void main() {
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
),
),
throwsToolExit(
@ -149,7 +148,7 @@ void main() {
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
),
);
await installCodeAssets(
@ -191,7 +190,7 @@ void main() {
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
buildResult: null,
),
),
@ -236,7 +235,7 @@ void main() {
projectUri: projectUri,
fileSystem: fileSystem,
buildRunner: FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
buildResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(
codeAssets: <CodeAsset>[
makeCodeAsset('direct', directSoFile.uri, DynamicLoadingBundled()),

View File

@ -31,6 +31,7 @@ void main() {
late FileSystem fileSystem;
late BufferLogger logger;
late Uri projectUri;
late String runPackageName;
setUp(() {
processManager = FakeProcessManager.empty();
@ -47,6 +48,7 @@ void main() {
);
environment.buildDir.createSync(recursive: true);
projectUri = environment.projectDir.uri;
runPackageName = environment.projectDir.basename;
});
for (final bool flutterTester in <bool>[false, true]) {
@ -96,7 +98,7 @@ void main() {
),
];
final FakeFlutterNativeAssetsBuildRunner buildRunner = FakeFlutterNativeAssetsBuildRunner(
packagesWithNativeAssetsResult: <Package>[Package('bar', projectUri)],
packagesWithNativeAssetsResult: <String>['bar'],
buildResult: FakeFlutterNativeAssetsBuilderResult.fromAssets(codeAssets: codeAssets),
linkResult:
buildMode == BuildMode.debug
@ -268,13 +270,14 @@ void main() {
packageConfig,
fileSystem,
logger,
runPackageName,
);
final CCompilerConfig result = (await runner.cCompilerConfig)!;
expect(result.compiler.toFilePath(), msvcBinDir.childFile('cl.exe').uri.toFilePath());
expect(result.archiver.toFilePath(), msvcBinDir.childFile('lib.exe').uri.toFilePath());
expect(result.linker.toFilePath(), msvcBinDir.childFile('link.exe').uri.toFilePath());
expect(result.envScript, isNotNull);
expect(result.envScriptArgs, isNotNull);
expect(result.windows.developerCommandPrompt?.script, isNotNull);
expect(result.windows.developerCommandPrompt?.arguments, isNotNull);
},
);
}

View File

@ -456,7 +456,7 @@ void expectDylibIsBundledWithFrameworks(Directory appDirectory, String buildMode
/// This inspects the build configuration to see if the C compiler was configured.
void expectCCompilerIsConfigured(Directory appDirectory) {
final Directory nativeAssetsBuilderDir = appDirectory.childDirectory(
'.dart_tool/native_assets_builder/',
'.dart_tool/native_assets_builder/$packageName/',
);
for (final Directory subDir in nativeAssetsBuilderDir.listSync().whereType<Directory>()) {
// We only want to look at build/link hook invocation directories. The
@ -466,14 +466,16 @@ void expectCCompilerIsConfigured(Directory appDirectory) {
continue;
}
final File configFile = subDir.childFile('config.json');
expect(configFile, exists);
final Map<String, Object?> config =
json.decode(configFile.readAsStringSync()) as Map<String, Object?>;
if (!(config['supported_asset_types']! as List<dynamic>).contains(CodeAsset.type)) {
final File inputFile = subDir.childFile('input.json');
expect(inputFile, exists);
final Map<String, Object?> inputContents =
json.decode(inputFile.readAsStringSync()) as Map<String, Object?>;
final BuildInput input = BuildInput(inputContents);
final BuildConfig config = input.config;
if (!config.buildCodeAssets) {
continue;
}
expect((config['c_compiler']! as Map<String, Object?>)['cc'], isNotNull);
expect(config.code.cCompiler?.compiler, isNot(isNull));
}
}

View File

@ -186,10 +186,10 @@ import 'package:native_assets_cli/code_assets.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
void main(List<String> args) async {
await build(args, (config, output) async {
final packageName = config.packageName;
await build(args, (input, output) async {
final packageName = input.packageName;
if (!config.buildAssetTypes.contains(CodeAsset.type)) {
if (!input.config.buildAssetTypes.contains(CodeAsset.type)) {
return;
}
final builders = [
@ -202,7 +202,7 @@ void main(List<String> args) async {
name: packageName,
assetName: '${packageName}_bindings_generated.dart',
sources: ['src/$packageName.c'],
flags: config.dynamicLinkingFlags('add'),
flags: input.dynamicLinkingFlags('add'),
),
];
@ -212,7 +212,7 @@ void main(List<String> args) async {
for (final builder in builders) {
await builder.run(
config: config,
input: input,
output: output,
logger: logger,
);
@ -220,8 +220,8 @@ void main(List<String> args) async {
});
}
extension on BuildConfig {
List<String> dynamicLinkingFlags(String libraryName) => switch (codeConfig.targetOS) {
extension on BuildInput {
List<String> dynamicLinkingFlags(String libraryName) => switch (config.code.targetOS) {
OS.macOS || OS.iOS => [
'-L${outputDirectory.toFilePath()}',
'-l$libraryName',
@ -234,7 +234,7 @@ extension on BuildConfig {
OS.windows => [
outputDirectory.resolve('$libraryName.lib').toFilePath()
],
_ => throw UnimplementedError('Unsupported OS: ${codeConfig.targetOS}'),
_ => throw UnimplementedError('Unsupported OS: ${config.code.targetOS}'),
};
}
''';