From 9a009603918f927053893ecf56bd1728f5ec9b0b Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Thu, 3 Oct 2024 13:46:16 +0200 Subject: [PATCH 1/7] (not to be committed yet / not done yet) Allow custom build/link configuration This PR allows users of `package:native_assets_builder` to supply custom build/link configuration. This allows e.g. flutter to add additional configuration to `hook/{build,link}.dart` scripts that require flutter specific things. As opposed to earlier PRs that merged `Foo` and `FooImpl` we have a different approach for build/link config/output as they are something different: The current API (even before the recent refactoring to it) allows read and write access to e.g. assets, ...). We remove this capability as this is conceptually problematic: - Currently those API classes are both mutable and at the same time support operator==/hashCode: => This is problematic as inserting such an object into a set/map and then modifying it means one can later on not find it anymore. Mutable objects can have operator==/hashCode iff it doesn't change (e.g. the default implementation based on identity). Otherwise objects should be immutable if they want to support operator==/hashCode. => For our puroses we have no need for operator==/hashCode and therefore remove this (problematic) capability. - Currently those API classes are serving both the hook writers and the bundling tool. The bundling tool would use Impl versions of those, but in the end operate on the same structures. We now change this to be using the builder pattern: The code that * creates build/link config/output will use a builder object that allows mutationonly * consumes build/link config/output will uses a view object that only allows read access We then make those build/link config/output objects flexible in the sense that * a bundling tool can add more configuration to build/link configuration * a hook can consume this additional configuration To support this we a) Make the builders operate on a json map that allows incrementally add more things to the build/link config. => The bundling tool gives `package:native_assets_builder` a function that creates the initial configuration which allows it to add bundling-tool specific configs (e.g. flutter specific things). => Initializing the configs is split up into groups that belong together => Named with `{Build,Link}ConfigBuilder.setup*()` methods which initialize things that conceptually belong together. => A bundling tool can then e.g. add code asset specifics via `configBuilder.setupCodeConfig(...)` b) Make the hooks operate on a json map that allows viewing this additional information via extension methods. => A hook can use e.g. `config.codeConfig.cCompiler` Since not all bundling tools may want support code assets (web builds), the code asset specific configuration is now moved out of the core packages and is one such bundling-tool specific configuration. => Hook writers can now access it via `config.codeConfig.*` => This sets up the stage to change the CLI protocol to move those code-asset specific things into a subtree of the config (e.g. json['code_asset_config']) => Then we can allow hook writers to easily detect it by introducing a `config.hasCodeConfig` getter. We make various smaller other changes, e.g. * The `package:native_assets_builder` APIs now either return a result on successfull build or `null` in case of error. => This makes callers have to check (due to nullable type of result) whether build/link succeeded or not (easy to forget to check for a `result.success` boolean - as evidenced a number of tests that didn't check this `success` boolean) => It avoids returning a result that is only partial (i.e. has some assets but not all due to some builds failing) * The `Architecture` is now moved to be a code-asset specific configuration => It makes sense for code assets. => It wouldn't make sense for e.g. web builds where there's no code assets available. => For now we keep the target operating system, but even that's somewhat problematic for web builds. * We no longer need the (temporary) `output.{code,data}Assets.all` getters => This is now natural due to the seperation via builder pattern. Overall: * The changes on the bundling tool side are rather minimal: ```diff final buildResult = await nativeAssetsBuildRunner.build( + configCreator: () => BuildConfigBuilder() + ..setupCodeConfig( + linkModePreference: LinkModePreference.dynamic, + targetArchitecture: target.architecture, + targetMacOSVersion: targetMacOSVersion, + cCompilerConfig: _getCCompilerConfig(), + ), workingDirectory: workingDirectory, - target: target, - linkModePreference: LinkModePreference.dynamic, + targetOS: target.os, buildMode: BuildMode.release, includeParentEnvironment: true, - targetMacOSVersion: targetMacOSVersion, linkingEnabled: true, supportedAssetTypes: [ CodeAsset.type, @@ -160,7 +168,7 @@ class BuildCommand extends DartdevCommand { ...await validateCodeAssetsInApplication(assets), ], ); - if (!buildResult.success) { + if (buildResult == null) { stderr.writeln('Native assets build failed.'); return 255; } @ ``` * The changes on the hook writer side are rather minimal as well, e.g.: ``` - final iosVersion = config.targetIOSVersion; + final iosVersion = config.codeConfig.targetIOSVersion; ``` The main changes are all encapsulated within the `package:native_assets_builder` and `package:native_assets_cli` and the *many* tests that need updating. --- .../lib/src/build_runner/build_runner.dart | 615 ++++++++---------- .../lib/src/model/build_dry_run_result.dart | 7 - .../lib/src/model/build_result.dart | 7 - .../lib/src/model/hook_result.dart | 41 +- .../lib/src/model/link_result.dart | 7 - .../build_runner/build_dependencies_test.dart | 4 +- .../build_runner_asset_id_test.dart | 4 +- .../build_runner_build_dry_run_test.dart | 8 +- ...build_runner_build_output_format_test.dart | 2 +- .../build_runner_caching_test.dart | 24 +- .../build_runner/build_runner_cycle_test.dart | 4 +- .../build_runner_failure_test.dart | 10 +- .../build_runner_non_root_package_test.dart | 8 +- .../build_runner_reusability_test.dart | 18 +- .../build_runner_run_in_isolation_test.dart | 4 +- .../test/build_runner/build_runner_test.dart | 8 +- .../concurrency_shared_test_helper.dart | 12 +- .../build_runner/concurrency_test_helper.dart | 10 +- .../build_runner/conflicting_dylib_test.dart | 9 +- .../fail_on_os_sdk_version_test.dart | 6 +- .../test/build_runner/helpers.dart | 107 +-- .../test/build_runner/link_caching_test.dart | 24 +- .../test/build_runner/link_test.dart | 36 +- .../packaging_preference_test.dart | 16 +- .../test/build_runner/resources_test.dart | 4 +- .../test/build_runner/wrong_linker_test.dart | 3 +- .../native_dynamic_linking_test.dart | 38 +- .../test/test_data/transformer_test.dart | 40 +- .../test_data/drop_dylib_link/hook/link.dart | 17 +- .../fail_on_os_sdk_version/hook/build.dart | 7 +- .../hook/link.dart | 7 +- .../native_add_duplicate/hook/build.dart | 5 +- .../package_reading_metadata/hook/build.dart | 30 +- .../test_data/simple_link/hook/link.dart | 2 +- .../wrong_build_output/hook/build.dart | 11 +- .../wrong_build_output_2/hook/build.dart | 11 +- .../wrong_build_output_3/hook/build.dart | 25 +- .../test_data/wrong_linker/hook/build.dart | 13 +- .../wrong_namespace_asset/hook/build.dart | 13 +- .../example/build/local_asset/hook/build.dart | 5 +- .../build/local_asset/test/build_test.dart | 11 +- .../lib/native_assets_cli.dart | 10 +- .../lib/native_assets_cli_internal.dart | 11 +- pkgs/native_assets_cli/lib/src/api/build.dart | 25 +- .../lib/src/api/build_config.dart | 184 ------ .../lib/src/api/build_output.dart | 180 ----- .../lib/src/api/builder.dart | 21 +- .../lib/src/api/hook_config.dart | 153 ----- pkgs/native_assets_cli/lib/src/api/link.dart | 26 +- .../lib/src/api/link_config.dart | 117 ---- .../lib/src/api/link_output.dart | 72 -- .../native_assets_cli/lib/src/api/linker.dart | 5 +- pkgs/native_assets_cli/lib/src/api/test.dart | 134 ---- .../lib/src/code_assets/code_asset.dart | 78 ++- .../src/code_assets/code_asset_bundling.dart | 77 +++ .../lib/src/code_assets/validation.dart | 26 +- pkgs/native_assets_cli/lib/src/config.dart | 538 +++++++++++++++ .../lib/src/data_assets/data_asset.dart | 20 +- .../src/data_assets/data_asset_bundling.dart | 20 + .../lib/src/data_assets/validation.dart | 18 +- .../native_assets_cli/lib/src/json_utils.dart | 1 + pkgs/native_assets_cli/lib/src/link_mode.dart | 2 +- .../lib/src/model/build_config.dart | 210 ------ .../native_assets_cli/lib/src/model/hook.dart | 7 +- .../lib/src/model/hook_config.dart | 548 ---------------- .../lib/src/model/hook_output.dart | 218 ------- .../lib/src/model/link_config.dart | 153 ----- pkgs/native_assets_cli/lib/test.dart | 106 ++- .../test/api/build_config_test.dart | 287 -------- .../test/api/build_output_test.dart | 50 -- .../test/api/build_test.dart | 64 +- .../test/api/link_config_test.dart | 193 ------ .../test/build_config_test.dart | 321 +++++++++ .../test/build_output_test.dart | 92 +++ .../native_assets_cli/test/checksum_test.dart | 107 +++ .../test/example/local_asset_test.dart | 39 +- .../test/example/native_add_library_test.dart | 37 +- .../example/native_dynamic_linking_test.dart | 39 +- .../test/link_config_test.dart | 216 ++++++ .../test/model/build_config_test.dart | 604 ----------------- .../test/model/build_output_test.dart | 313 --------- .../test/model/checksum_test.dart | 110 ---- .../test/model/link_config_test.dart | 517 --------------- .../test/validator/validator_test.dart | 333 ++++------ .../lib/src/cbuilder/cbuilder.dart | 8 +- .../lib/src/cbuilder/clinker.dart | 91 ++- .../lib/src/cbuilder/compiler_resolver.dart | 24 +- .../lib/src/cbuilder/run_cbuilder.dart | 17 +- .../cbuilder/cbuilder_build_failure_test.dart | 34 +- .../cbuilder/cbuilder_cross_android_test.dart | 40 +- .../cbuilder/cbuilder_cross_ios_test.dart | 79 ++- .../cbuilder_cross_linux_host_test.dart | 37 +- .../cbuilder_cross_macos_host_test.dart | 73 ++- .../cbuilder_cross_windows_host_test.dart | 37 +- .../test/cbuilder/cbuilder_test.dart | 286 ++++---- .../test/cbuilder/compiler_resolver_test.dart | 84 ++- .../test/cbuilder/objective_c_test.dart | 34 +- .../test/clinker/build_testfiles.dart | 40 +- .../test/clinker/objects_test.dart | 42 +- .../test/clinker/throws_test.dart | 40 +- .../test/clinker/treeshake_helper.dart | 45 +- 101 files changed, 3060 insertions(+), 5466 deletions(-) delete mode 100644 pkgs/native_assets_cli/lib/src/api/build_config.dart delete mode 100644 pkgs/native_assets_cli/lib/src/api/build_output.dart delete mode 100644 pkgs/native_assets_cli/lib/src/api/hook_config.dart delete mode 100644 pkgs/native_assets_cli/lib/src/api/link_config.dart delete mode 100644 pkgs/native_assets_cli/lib/src/api/link_output.dart delete mode 100644 pkgs/native_assets_cli/lib/src/api/test.dart create mode 100644 pkgs/native_assets_cli/lib/src/code_assets/code_asset_bundling.dart create mode 100644 pkgs/native_assets_cli/lib/src/config.dart create mode 100644 pkgs/native_assets_cli/lib/src/data_assets/data_asset_bundling.dart delete mode 100644 pkgs/native_assets_cli/lib/src/model/build_config.dart delete mode 100644 pkgs/native_assets_cli/lib/src/model/hook_config.dart delete mode 100644 pkgs/native_assets_cli/lib/src/model/hook_output.dart delete mode 100644 pkgs/native_assets_cli/lib/src/model/link_config.dart delete mode 100644 pkgs/native_assets_cli/test/api/build_config_test.dart delete mode 100644 pkgs/native_assets_cli/test/api/build_output_test.dart delete mode 100644 pkgs/native_assets_cli/test/api/link_config_test.dart create mode 100644 pkgs/native_assets_cli/test/build_config_test.dart create mode 100644 pkgs/native_assets_cli/test/build_output_test.dart create mode 100644 pkgs/native_assets_cli/test/checksum_test.dart create mode 100644 pkgs/native_assets_cli/test/link_config_test.dart delete mode 100644 pkgs/native_assets_cli/test/model/build_config_test.dart delete mode 100644 pkgs/native_assets_cli/test/model/build_output_test.dart delete mode 100644 pkgs/native_assets_cli/test/model/checksum_test.dart delete mode 100644 pkgs/native_assets_cli/test/model/link_config_test.dart diff --git a/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart b/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart index 12afbcb11..fce1a52ce 100644 --- a/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart +++ b/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:convert'; import 'dart:io'; import 'package:logging/logging.dart'; @@ -23,8 +24,14 @@ import 'build_planner.dart'; typedef DependencyMetadata = Map; +typedef ConfigCreator = HookConfigBuilder Function(); + +typedef BuildConfigCreator = BuildConfigBuilder Function(); + +typedef LinkConfigCreator = LinkConfigBuilder Function(); + typedef _HookValidator = Future Function( - HookConfig config, HookOutputImpl output); + HookConfig config, HookOutput output); // A callback that validates the output of a `hook/link.dart` invocation is // valid (it may valid asset-type specific information). @@ -72,39 +79,28 @@ class NativeAssetsBuildRunner { /// The native assets build runner does not support reentrancy for identical /// [api.BuildConfig] and [api.LinkConfig]! For more info see: /// https://github.com/dart-lang/native/issues/1319 - Future build({ - required LinkModePreference linkModePreference, - required Target target, - required Uri workingDirectory, - required BuildMode buildMode, + Future build({ + required BuildConfigCreator configCreator, required BuildValidator buildValidator, required ApplicationAssetValidator applicationAssetValidator, - CCompilerConfig? cCompilerConfig, - IOSSdk? targetIOSSdk, - int? targetIOSVersion, - int? targetMacOSVersion, - int? targetAndroidNdkApi, + required OS targetOS, + required BuildMode buildMode, + required Uri workingDirectory, required bool includeParentEnvironment, PackageLayout? packageLayout, String? runPackageName, - required Iterable supportedAssetTypes, + required List supportedAssetTypes, required bool linkingEnabled, }) async => _run( - validator: (HookConfig config, HookOutputImpl output) => + targetOS: targetOS, + buildMode: buildMode, + configCreator: configCreator, + validator: (HookConfig config, HookOutput output) => buildValidator(config as BuildConfig, output as BuildOutput), - applicationAssetValidator: (assets) async => - linkingEnabled ? [] : applicationAssetValidator(assets), + applicationAssetValidator: applicationAssetValidator, hook: Hook.build, - linkModePreference: linkModePreference, - target: target, workingDirectory: workingDirectory, - buildMode: buildMode, - cCompilerConfig: cCompilerConfig, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, includeParentEnvironment: includeParentEnvironment, packageLayout: packageLayout, runPackageName: runPackageName, @@ -123,40 +119,29 @@ class NativeAssetsBuildRunner { /// The native assets build runner does not support reentrancy for identical /// [api.BuildConfig] and [api.LinkConfig]! For more info see: /// https://github.com/dart-lang/native/issues/1319 - Future link({ - required LinkModePreference linkModePreference, - required Target target, - required Uri workingDirectory, - required BuildMode buildMode, + Future link({ + required ConfigCreator configCreator, required LinkValidator linkValidator, + required OS targetOS, + required BuildMode buildMode, + required Uri workingDirectory, required ApplicationAssetValidator applicationAssetValidator, - CCompilerConfig? cCompilerConfig, - IOSSdk? targetIOSSdk, - int? targetIOSVersion, - int? targetMacOSVersion, - int? targetAndroidNdkApi, required bool includeParentEnvironment, PackageLayout? packageLayout, Uri? resourceIdentifiers, String? runPackageName, - required Iterable supportedAssetTypes, + required List supportedAssetTypes, required BuildResult buildResult, }) async => _run( - validator: (HookConfig config, HookOutputImpl output) => + configCreator: configCreator, + validator: (HookConfig config, HookOutput output) => linkValidator(config as LinkConfig, output as LinkOutput), - applicationAssetValidator: (assets) async => - applicationAssetValidator(assets), + applicationAssetValidator: applicationAssetValidator, + targetOS: targetOS, + buildMode: buildMode, hook: Hook.link, - linkModePreference: linkModePreference, - target: target, workingDirectory: workingDirectory, - buildMode: buildMode, - cCompilerConfig: cCompilerConfig, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, includeParentEnvironment: includeParentEnvironment, packageLayout: packageLayout, runPackageName: runPackageName, @@ -166,62 +151,25 @@ class NativeAssetsBuildRunner { ); /// The common method for running building or linking of assets. - Future _run({ - required Hook hook, - required LinkModePreference linkModePreference, - required Target target, - required Uri workingDirectory, - required BuildMode buildMode, + Future _run({ + required ConfigCreator configCreator, required _HookValidator validator, required ApplicationAssetValidator applicationAssetValidator, - CCompilerConfig? cCompilerConfig, - IOSSdk? targetIOSSdk, - int? targetIOSVersion, - int? targetMacOSVersion, - int? targetAndroidNdkApi, + required OS targetOS, + required BuildMode buildMode, + required Hook hook, + required Uri workingDirectory, required bool includeParentEnvironment, PackageLayout? packageLayout, - Uri? resourceIdentifiers, String? runPackageName, - required Iterable supportedAssetTypes, - BuildResult? buildResult, + required List supportedAssetTypes, bool? linkingEnabled, + BuildResult? buildResult, + Uri? resourceIdentifiers, }) async { assert(hook == Hook.link || buildResult == null); assert(hook == Hook.build || linkingEnabled == null); - // Specifically for running our tests on Dart CI with the test runner, we - // recognize specific variables to setup the C Compiler configuration. - if (cCompilerConfig == null) { - final env = Platform.environment; - final cc = env['DART_HOOK_TESTING_C_COMPILER__CC']; - final ar = env['DART_HOOK_TESTING_C_COMPILER__AR']; - final ld = env['DART_HOOK_TESTING_C_COMPILER__LD']; - final envScript = env['DART_HOOK_TESTING_C_COMPILER__ENV_SCRIPT']; - final envScriptArgs = - env['DART_HOOK_TESTING_C_COMPILER__ENV_SCRIPT_ARGUMENTS'] - ?.split(' ') - .map((arg) => arg.trim()) - .where((arg) => arg.isNotEmpty) - .toList(); - final hasEnvScriptArgs = - envScriptArgs != null && envScriptArgs.isNotEmpty; - - if (cc != null || - ar != null || - ld != null || - envScript != null || - hasEnvScriptArgs) { - cCompilerConfig = CCompilerConfig( - archiver: ar != null ? Uri.file(ar) : null, - compiler: cc != null ? Uri.file(cc) : null, - envScript: envScript != null ? Uri.file(envScript) : null, - envScriptArgs: hasEnvScriptArgs ? envScriptArgs : null, - linker: ld != null ? Uri.file(ld) : null, - ); - } - } - packageLayout ??= await PackageLayout.fromRootPackageRoot(workingDirectory); final (buildPlan, packageGraph, planSuccess) = await _makePlan( hook: hook, @@ -230,46 +178,79 @@ class NativeAssetsBuildRunner { runPackageName: runPackageName, ); if (!planSuccess) { - return HookResult.failure(); + return null; } - var hookResult = HookResult(); - if (hook == Hook.link) { - hookResult.encodedAssets.addAll(buildResult!.encodedAssets); - } - final metadata = {}; + var hookResult = (hook == Hook.link) + ? HookResult(encodedAssets: buildResult!.encodedAssets) + : HookResult(); + final globalMetadata = {}; for (final package in buildPlan) { - final DependencyMetadata? dependencyMetadata; - switch (hook) { - case Hook.build: - dependencyMetadata = _metadataForPackage( - packageGraph: packageGraph!, - packageName: package.name, - targetMetadata: metadata, - ); - case Hook.link: - dependencyMetadata = null; - } - final config = await _cliConfig( - package, - packageLayout, - target, - buildMode, - linkModePreference, - dependencyMetadata, - linkingEnabled, - cCompilerConfig, - targetIOSSdk, - targetAndroidNdkApi, - targetIOSVersion, - targetMacOSVersion, - supportedAssetTypes, - hook, - resourceIdentifiers, - buildResult, + final configBuilder = configCreator(); + configBuilder.setupHookConfig( + targetOS: targetOS, + supportedAssetTypes: supportedAssetTypes, + buildMode: buildMode, + packageName: package.name, + packageRoot: packageLayout.packageRoot(package.name), ); + if (hook == Hook.build) { + final metadata = {}; + _metadataForPackage( + packageGraph: packageGraph!, + packageName: package.name, + targetMetadata: globalMetadata, + )?.forEach((key, value) => metadata[key] = value); + (configBuilder as BuildConfigBuilder).setupBuildConfig( + dryRun: false, + linkingEnabled: linkingEnabled!, + metadata: metadata, + ); + } else { + (configBuilder as LinkConfigBuilder).setupLinkConfig( + assets: buildResult!.encodedAssetsForLinking[package.name] ?? []); + } - final (hookOutput, packageSuccess) = await _runHookForPackageCached( + final buildDirName = configBuilder.computeChecksum(); + final buildDirUri = + packageLayout.dartToolNativeAssetsBuilder.resolve('$buildDirName/'); + final outDirUri = buildDirUri.resolve('out/'); + final outDir = Directory.fromUri(outDirUri); + if (!await outDir.exists()) { + // TODO(https://dartbug.com/50565): Purge old or unused folders. + await outDir.create(recursive: true); + } + final outputDirectoryShared = packageLayout.dartToolNativeAssetsBuilder + .resolve('shared/${package.name}/$hook/'); + final outDirShared = Directory.fromUri(outputDirectoryShared); + if (!await outDirShared.exists()) { + // TODO(https://dartbug.com/50565): Purge old or unused folders. + await outDirShared.create(recursive: true); + } + + if (hook == Hook.link) { + File? resourcesFile; + if (resourceIdentifiers != null) { + resourcesFile = File.fromUri(buildDirUri.resolve('resources.json')); + await resourcesFile.create(); + await File.fromUri(resourceIdentifiers).copy(resourcesFile.path); + } + (configBuilder as LinkConfigBuilder).setupLinkRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + recordedUsesFile: resourcesFile?.uri, + ); + } else { + (configBuilder as BuildConfigBuilder).setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + ); + } + + final config = hook == Hook.build + ? BuildConfig(configBuilder.json) + : LinkConfig(configBuilder.json); + final hookOutput = await _runHookForPackageCached( hook, config, validator, @@ -279,9 +260,16 @@ class NativeAssetsBuildRunner { resourceIdentifiers, packageLayout, ); - hookResult = hookResult.copyAdd(hookOutput, packageSuccess); - metadata[config.packageName] = hookOutput.metadata; + if (hookOutput == null) return null; + hookResult = hookResult.copyAdd(hookOutput); + if (hook == Hook.build) { + globalMetadata[package.name] = (hookOutput as BuildOutput).metadata; + } } + // We only perform application wide validation in the final result of + // building all assets (i.e. in the build step if linking is not enabled or + // in the link step if linking is enableD). + if (hook == Hook.build && linkingEnabled!) return hookResult; final errors = await applicationAssetValidator(hookResult.encodedAssets); if (errors.isEmpty) return hookResult; @@ -290,105 +278,7 @@ class NativeAssetsBuildRunner { for (final error in errors) { logger.severe('- $error'); } - return HookResult.failure(); - } - - static Future _cliConfig( - Package package, - PackageLayout packageLayout, - Target target, - BuildMode buildMode, - LinkModePreference linkModePreference, - DependencyMetadata? dependencyMetadata, - bool? linkingEnabled, - CCompilerConfig? cCompilerConfig, - IOSSdk? targetIOSSdk, - int? targetAndroidNdkApi, - int? targetIOSVersion, - int? targetMacOSVersion, - Iterable supportedAssetTypes, - Hook hook, - Uri? resourceIdentifiers, - BuildResult? buildResult, - ) async { - final buildDirName = HookConfigImpl.checksum( - packageName: package.name, - packageRoot: package.root, - targetOS: target.os, - targetArchitecture: target.architecture, - buildMode: buildMode, - linkModePreference: linkModePreference, - targetIOSSdk: targetIOSSdk, - cCompiler: cCompilerConfig, - dependencyMetadata: dependencyMetadata, - targetAndroidNdkApi: targetAndroidNdkApi, - supportedAssetTypes: supportedAssetTypes, - hook: hook, - linkingEnabled: linkingEnabled, - ); - final buildDirUri = - packageLayout.dartToolNativeAssetsBuilder.resolve('$buildDirName/'); - final outputDirectory = buildDirUri.resolve('out/'); - final outDir = Directory.fromUri(outputDirectory); - if (!await outDir.exists()) { - // TODO(https://dartbug.com/50565): Purge old or unused folders. - await outDir.create(recursive: true); - } - - final outputDirectoryShared = packageLayout.dartToolNativeAssetsBuilder - .resolve('shared/${package.name}/$hook/'); - final outDirShared = Directory.fromUri(outputDirectoryShared); - if (!await outDirShared.exists()) { - // TODO(https://dartbug.com/50565): Purge old or unused folders. - await outDirShared.create(recursive: true); - } - - if (hook == Hook.link) { - File? resourcesFile; - if (resourceIdentifiers != null) { - resourcesFile = File.fromUri(buildDirUri.resolve('resources.json')); - await resourcesFile.create(); - await File.fromUri(resourceIdentifiers).copy(resourcesFile.path); - } - - return LinkConfigImpl( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: package.name, - packageRoot: package.root, - targetOS: target.os, - targetArchitecture: target.architecture, - buildMode: buildMode, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - cCompiler: cCompilerConfig, - targetAndroidNdkApi: targetAndroidNdkApi, - recordedUsagesFile: resourcesFile?.uri, - encodedAssets: buildResult!.encodedAssetsForLinking[package.name] ?? [], - supportedAssetTypes: supportedAssetTypes, - linkModePreference: linkModePreference, - ); - } else { - return BuildConfigImpl( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: package.name, - packageRoot: package.root, - targetOS: target.os, - targetArchitecture: target.architecture, - buildMode: buildMode, - linkModePreference: linkModePreference, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - cCompiler: cCompilerConfig, - dependencyMetadata: dependencyMetadata, - linkingEnabled: linkingEnabled, - targetAndroidNdkApi: targetAndroidNdkApi, - supportedAssetTypes: supportedAssetTypes, - ); - } + return null; } /// [workingDirectory] is expected to contain `.dart_tool`. @@ -398,18 +288,43 @@ class NativeAssetsBuildRunner { /// /// If provided, only native assets of all transitive dependencies of /// [runPackageName] are built. - Future buildDryRun({ - required LinkModePreference linkModePreference, + Future buildDryRun({ + required BuildConfigCreator configCreator, + required BuildValidator buildValidator, required OS targetOS, required Uri workingDirectory, - required bool includeParentEnvironment, required bool linkingEnabled, - required BuildValidator buildValidator, + required bool includeParentEnvironment, PackageLayout? packageLayout, String? runPackageName, - required Iterable supportedAssetTypes, + required List supportedAssetTypes, + }) => + _runDryRun( + targetOS: targetOS, + configCreator: configCreator, + validator: (HookConfig config, HookOutput output) => + buildValidator(config as BuildConfig, output as BuildOutput), + workingDirectory: workingDirectory, + includeParentEnvironment: includeParentEnvironment, + packageLayout: packageLayout, + runPackageName: runPackageName, + supportedAssetTypes: supportedAssetTypes, + linkingEnabled: linkingEnabled, + ); + + Future _runDryRun({ + required BuildConfigCreator configCreator, + required _HookValidator validator, + required OS targetOS, + required Uri workingDirectory, + required bool includeParentEnvironment, + PackageLayout? packageLayout, + String? runPackageName, + required bool linkingEnabled, + required List supportedAssetTypes, }) async { const hook = Hook.build; + packageLayout ??= await PackageLayout.fromRootPackageRoot(workingDirectory); final (buildPlan, _, planSuccess) = await _makePlan( hook: hook, @@ -417,38 +332,67 @@ class NativeAssetsBuildRunner { runPackageName: runPackageName, ); if (!planSuccess) { - return HookResult.failure(); + return null; } var hookResult = HookResult(); for (final package in buildPlan) { - final config = await _cliConfigDryRun( - package: package, - packageName: package.name, - packageRoot: packageLayout.packageRoot(package.name), + final configBuilder = configCreator(); + configBuilder.setupHookConfig( targetOS: targetOS, - linkMode: linkModePreference, - buildParentDir: packageLayout.dartToolNativeAssetsBuilder, supportedAssetTypes: supportedAssetTypes, + buildMode: null, // not set in dry-run mode + packageName: package.name, + packageRoot: packageLayout.packageRoot(package.name), + ); + configBuilder.setupBuildConfig( + dryRun: true, linkingEnabled: linkingEnabled, + metadata: const {}, ); + + final buildDirName = configBuilder.computeChecksum(); + final buildDirUri = + packageLayout.dartToolNativeAssetsBuilder.resolve('$buildDirName/'); + final outDirUri = buildDirUri.resolve('out/'); + final outDir = Directory.fromUri(outDirUri); + if (!await outDir.exists()) { + // TODO(https://dartbug.com/50565): Purge old or unused folders. + await outDir.create(recursive: true); + } + final outputDirectoryShared = packageLayout.dartToolNativeAssetsBuilder + .resolve('shared/${package.name}/$hook/'); + final outDirShared = Directory.fromUri(outputDirectoryShared); + if (!await outDirShared.exists()) { + // TODO(https://dartbug.com/50565): Purge old or unused folders. + await outDirShared.create(recursive: true); + } + configBuilder.setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + ); + + final config = hook == Hook.build + ? BuildConfig(configBuilder.json) + : LinkConfig(configBuilder.json); + final packageConfigUri = packageLayout.packageConfigUri; final ( compileSuccess, hookKernelFile, _, ) = await _compileHookForPackageCached( - config, + config.packageName, + config.outputDirectory, + config.packageRoot.resolve('hook/${hook.scriptName}'), packageConfigUri, workingDirectory, includeParentEnvironment, ); - if (!compileSuccess) { - hookResult.copyAdd(HookOutputImpl(), false); - continue; - } + if (!compileSuccess) return null; + // TODO(https://github.com/dart-lang/native/issues/1321): Should dry runs be cached? - final (buildOutput, packageSuccess) = await runUnderDirectoriesLock( + final buildOutput = await runUnderDirectoriesLock( [ Directory.fromUri(config.outputDirectoryShared.parent), Directory.fromUri(config.outputDirectory.parent), @@ -458,8 +402,7 @@ class NativeAssetsBuildRunner { () => _runHookForPackage( hook, config, - (HookConfig config, HookOutputImpl output) => - buildValidator(config as BuildConfig, output as BuildOutput), + validator, packageConfigUri, workingDirectory, includeParentEnvironment, @@ -468,14 +411,15 @@ class NativeAssetsBuildRunner { packageLayout!, ), ); - hookResult = hookResult.copyAdd(buildOutput, packageSuccess); + if (buildOutput == null) return null; + hookResult = hookResult.copyAdd(buildOutput); } return hookResult; } - Future<_PackageBuildRecord> _runHookForPackageCached( + Future _runHookForPackageCached( Hook hook, - HookConfigImpl config, + HookConfig config, _HookValidator validator, Uri packageConfigUri, Uri workingDirectory, @@ -497,20 +441,43 @@ class NativeAssetsBuildRunner { hookKernelFile, hookLastSourceChange, ) = await _compileHookForPackageCached( - config, + config.packageName, + config.outputDirectory, + config.packageRoot.resolve('hook/${hook.scriptName}'), packageConfigUri, workingDirectory, includeParentEnvironment, ); if (!compileSuccess) { - return (HookOutputImpl(), false); + return null; } - final hookOutput = HookOutputImpl.readFromFile(file: config.outputFile); - if (hookOutput != null) { - final lastBuilt = hookOutput.timestamp.roundDownToSeconds(); + final buildOutputFile = + File.fromUri(config.outputDirectory.resolve(hook.outputName)); + if (buildOutputFile.existsSync()) { + late final HookOutput output; + try { + final decode = + const Utf8Decoder().fuse(const JsonDecoder()).convert; + final hookOutputJson = decode(buildOutputFile.readAsBytesSync()) + as Map; + output = hook == Hook.build + ? BuildOutput(hookOutputJson) + : LinkOutput(hookOutputJson); + } on FormatException catch (e) { + logger.severe(''' +Building assets for package:${config.packageName} failed. +${hook.outputName} contained a format error. + +Contents: ${buildOutputFile.readAsStringSync()}. +${e.message} + '''); + return null; + } + + final lastBuilt = output.timestamp.roundDownToSeconds(); final dependenciesLastChange = - await hookOutput.dependenciesModel.lastModified(); + await Dependencies(output.dependencies).lastModified(); if (lastBuilt.isAfter(dependenciesLastChange) && lastBuilt.isAfter(hookLastSourceChange)) { logger.info( @@ -523,7 +490,7 @@ class NativeAssetsBuildRunner { ); // All build flags go into [outDir]. Therefore we do not have to // check here whether the config is equal. - return (hookOutput, true); + return output; } } @@ -542,9 +509,9 @@ class NativeAssetsBuildRunner { ); } - Future<_PackageBuildRecord> _runHookForPackage( + Future _runHookForPackage( Hook hook, - HookConfigImpl config, + HookConfig config, _HookValidator validator, Uri packageConfigUri, Uri workingDirectory, @@ -554,10 +521,12 @@ class NativeAssetsBuildRunner { PackageLayout packageLayout, ) async { final configFile = config.outputDirectory.resolve('../config.json'); - final configFileContents = config.toJsonString(); + final configFileContents = + const JsonEncoder.withIndent(' ').convert(config.json); logger.info('config.json contents: $configFileContents'); await File.fromUri(configFile).writeAsString(configFileContents); - final buildOutputFile = File.fromUri(config.outputFile); + final hookOutputFile = config.outputDirectory.resolve(hook.outputName); + final buildOutputFile = File.fromUri(hookOutputFile); if (await buildOutputFile.exists()) { // Ensure we'll never read outdated build results. await buildOutputFile.delete(); @@ -577,7 +546,7 @@ class NativeAssetsBuildRunner { includeParentEnvironment: includeParentEnvironment, ); - var success = true; + var deleteOutputIfExists = false; if (result.exitCode != 0) { final printWorkingDir = workingDirectory != Directory.current.uri; final commandString = [ @@ -588,8 +557,8 @@ class NativeAssetsBuildRunner { ].join(' '); logger.severe( ''' -Building native assets for package:${config.packageName} failed. -${config.script} returned with exit code: ${result.exitCode}. +Building assets for package:${config.packageName} failed. +${hook.scriptName} returned with exit code: ${result.exitCode}. To reproduce run: $commandString stderr: @@ -598,34 +567,40 @@ stdout: ${result.stdout} ''', ); - success = false; + deleteOutputIfExists = true; + return null; } try { - final output = HookOutputImpl.readFromFile(file: config.outputFile) ?? - HookOutputImpl(); + final decode = const Utf8Decoder().fuse(const JsonDecoder()).convert; + + final hookOutputJson = + decode(buildOutputFile.readAsBytesSync()) as Map; + final output = hook == Hook.build + ? BuildOutput(hookOutputJson) + : LinkOutput(hookOutputJson); final errors = await _validate(config, output, packageLayout, validator); - success &= errors.isEmpty; if (errors.isNotEmpty) { logger.severe('package:${config.packageName}` has invalid output.'); + for (final error in errors) { + logger.severe('- $error'); + } + deleteOutputIfExists = true; + return null; } - for (final error in errors) { - logger.severe('- $error'); - } - return (output, success); + return output; } on FormatException catch (e) { logger.severe(''' -Building native assets for package:${config.packageName} failed. -${config.outputName} contained a format error. +Building assets for package:${config.packageName} failed. +${hook.outputName} contained a format error. -Contents: ${File.fromUri(config.outputFile).readAsStringSync()}. +Contents: ${buildOutputFile.readAsStringSync()}. ${e.message} '''); - success = false; - return (HookOutputImpl(), false); + return null; } finally { - if (!success) { + if (deleteOutputIfExists) { if (await buildOutputFile.exists()) { await buildOutputFile.delete(); } @@ -646,21 +621,23 @@ ${e.message} /// one time too many, then not recompiling when recompilation should have /// happened. /// - /// It does not reuse the cached kernel for different [config]s, due to + /// It does not reuse the cached kernel for different configs due to /// reentrancy requirements. For more info see: /// https://github.com/dart-lang/native/issues/1319 Future<(bool success, File kernelFile, DateTime lastSourceChange)> _compileHookForPackageCached( - HookConfigImpl config, + String packageName, + Uri outputDirectory, + Uri scriptUri, Uri packageConfigUri, Uri workingDirectory, bool includeParentEnvironment, ) async { final kernelFile = File.fromUri( - config.outputDirectory.resolve('../hook.dill'), + outputDirectory.resolve('../hook.dill'), ); final depFile = File.fromUri( - config.outputDirectory.resolve('../hook.dill.d'), + outputDirectory.resolve('../hook.dill.d'), ); final bool mustCompile; final DateTime sourceLastChange; @@ -691,7 +668,8 @@ ${e.message} success = true; } else { success = await _compileHookForPackage( - config, + packageName, + scriptUri, packageConfigUri, workingDirectory, includeParentEnvironment, @@ -703,7 +681,8 @@ ${e.message} } Future _compileHookForPackage( - HookConfigImpl config, + String packageName, + Uri scriptUri, Uri packageConfigUri, Uri workingDirectory, bool includeParentEnvironment, @@ -716,7 +695,7 @@ ${e.message} '--packages=${packageConfigUri.toFilePath()}', '--output=${kernelFile.path}', '--depfile=${depFile.path}', - config.script.toFilePath(), + scriptUri.toFilePath(), ]; final compileResult = await runProcess( workingDirectory: workingDirectory, @@ -736,7 +715,7 @@ ${e.message} ].join(' '); logger.severe( ''' -Building native assets for package:${config.packageName} failed. +Building native assets for package:$packageName failed. Compilation of hook returned with exit code: ${compileResult.exitCode}. To reproduce run: $commandString @@ -751,54 +730,6 @@ ${compileResult.stdout} return success; } - static Future _cliConfigDryRun({ - required Package package, - required String packageName, - required Uri packageRoot, - required OS targetOS, - required LinkModePreference linkMode, - required Uri buildParentDir, - required Iterable supportedAssetTypes, - required bool? linkingEnabled, - }) async { - const hook = Hook.build; - final buildDirName = HookConfigImpl.checksumDryRun( - packageName: package.name, - packageRoot: package.root, - targetOS: targetOS, - linkModePreference: linkMode, - supportedAssetTypes: supportedAssetTypes, - hook: hook, - linkingEnabled: linkingEnabled, - ); - - final outDirUri = buildParentDir.resolve('$buildDirName/out/'); - final outDir = Directory.fromUri(outDirUri); - if (!await outDir.exists()) { - await outDir.create(recursive: true); - } - - // Shared between dry run and wet run. - final outputDirectoryShared = - buildParentDir.resolve('shared/${package.name}/$hook/out/'); - final outDirShared = Directory.fromUri(outputDirectoryShared); - if (!await outDirShared.exists()) { - // TODO(https://dartbug.com/50565): Purge old or unused folders. - await outDirShared.create(recursive: true); - } - - return BuildConfigImpl.dryRun( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRoot, - targetOS: targetOS, - linkModePreference: linkMode, - supportedAssetTypes: supportedAssetTypes, - linkingEnabled: linkingEnabled, - ); - } - DependencyMetadata? _metadataForPackage({ required PackageGraph packageGraph, required String packageName, @@ -815,17 +746,19 @@ ${compileResult.stdout} } Future _validate( - HookConfigImpl config, - HookOutputImpl output, + HookConfig config, + HookOutput output, PackageLayout packageLayout, _HookValidator validator, ) async { - final errors = config is BuildConfigImpl - ? await validateBuildOutput(config, output) - : await validateLinkOutput(config as LinkConfig, output); + final errors = config is BuildConfig + ? await validateBuildOutput(config, output as BuildOutput) + : await validateLinkOutput(config as LinkConfig, output as LinkOutput); errors.addAll(await validator(config, output)); - if (config is BuildConfigImpl) { + if (config is BuildConfig) { + // XXX + output as BuildOutput; final packagesWithLink = (await packageLayout.packagesWithAssets(Hook.link)) .map((p) => p.name); @@ -899,8 +832,6 @@ ${compileResult.stdout} } } -typedef _PackageBuildRecord = (HookOutputImpl, bool success); - extension on DateTime { DateTime roundDownToSeconds() => DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch - diff --git a/pkgs/native_assets_builder/lib/src/model/build_dry_run_result.dart b/pkgs/native_assets_builder/lib/src/model/build_dry_run_result.dart index 6a37448c5..9863d2ba1 100644 --- a/pkgs/native_assets_builder/lib/src/model/build_dry_run_result.dart +++ b/pkgs/native_assets_builder/lib/src/model/build_dry_run_result.dart @@ -4,19 +4,12 @@ import 'package:native_assets_cli/native_assets_cli_internal.dart'; -import '../../native_assets_builder.dart'; - /// The result of executing the build hooks in dry run mode from all packages in /// the dependency tree of the entry point application. abstract interface class BuildDryRunResult { /// The native assets produced by the hooks, which should be bundled. List get encodedAssets; - /// Whether all hooks completed without errors. - /// - /// All error messages are streamed to [NativeAssetsBuildRunner.logger]. - bool get success; - /// The native assets produced by the hooks, which should be linked. Map> get encodedAssetsForLinking; } diff --git a/pkgs/native_assets_builder/lib/src/model/build_result.dart b/pkgs/native_assets_builder/lib/src/model/build_result.dart index 96b2aac2d..a857e7622 100644 --- a/pkgs/native_assets_builder/lib/src/model/build_result.dart +++ b/pkgs/native_assets_builder/lib/src/model/build_result.dart @@ -4,19 +4,12 @@ import 'package:native_assets_cli/native_assets_cli_internal.dart'; -import '../build_runner/build_runner.dart'; - /// The result of executing build hooks from all packages in the dependency tree /// of the entry point application. abstract class BuildResult { /// The files used by the hooks. List get dependencies; - /// Whether all hooks completed without errors. - /// - /// All error messages are streamed to [NativeAssetsBuildRunner.logger]. - bool get success; - /// The native assets produced by the hooks, which should be bundled. List get encodedAssets; diff --git a/pkgs/native_assets_builder/lib/src/model/hook_result.dart b/pkgs/native_assets_builder/lib/src/model/hook_result.dart index 52ec4d98f..033d635db 100644 --- a/pkgs/native_assets_builder/lib/src/model/hook_result.dart +++ b/pkgs/native_assets_builder/lib/src/model/hook_result.dart @@ -22,61 +22,48 @@ final class HookResult implements BuildResult, BuildDryRunResult, LinkResult { @override final List dependencies; - /// Whether all hooks completed without errors. - /// - /// All error messages are streamed to [NativeAssetsBuildRunner.logger]. - @override - final bool success; - HookResult._({ required this.encodedAssets, required this.encodedAssetsForLinking, required this.dependencies, - required this.success, }); factory HookResult({ List? encodedAssets, Map>? encodedAssetsForLinking, List? dependencies, - bool success = true, }) => HookResult._( encodedAssets: encodedAssets ?? [], encodedAssetsForLinking: encodedAssetsForLinking ?? {}, dependencies: dependencies ?? [], - success: success, ); - factory HookResult.failure() => HookResult(success: false); - - HookResult copyAdd(HookOutputImpl hookOutput, bool hookSuccess) { - final mergedMaps = - mergeMaps(encodedAssetsForLinking, hookOutput.encodedAssetsForLinking, - value: (encodedAssets1, encodedAssets2) => [ - ...encodedAssets1, - ...encodedAssets2, - ]); + HookResult copyAdd(HookOutput hookOutput) { + final mergedMaps = mergeMaps( + encodedAssetsForLinking, + hookOutput is BuildOutput + ? hookOutput.encodedAssetsForLinking + : >{}, + value: (encodedAssets1, encodedAssets2) => [ + ...encodedAssets1, + ...encodedAssets2, + ]); + final hookOutputAssets = (hookOutput is BuildOutput) + ? hookOutput.encodedAssets + : (hookOutput as LinkOutput).encodedAssets; return HookResult( encodedAssets: [ ...encodedAssets, - ...hookOutput.encodedAssets, + ...hookOutputAssets, ], encodedAssetsForLinking: mergedMaps, dependencies: [ ...dependencies, ...hookOutput.dependencies, ]..sort(_uriCompare), - success: success && hookSuccess, ); } - - HookResult withSuccess(bool success) => HookResult( - encodedAssets: encodedAssets, - encodedAssetsForLinking: encodedAssetsForLinking, - dependencies: dependencies, - success: success, - ); } int _uriCompare(Uri u1, Uri u2) => u1.toString().compareTo(u2.toString()); diff --git a/pkgs/native_assets_builder/lib/src/model/link_result.dart b/pkgs/native_assets_builder/lib/src/model/link_result.dart index 7b72ef951..b2bb578a4 100644 --- a/pkgs/native_assets_builder/lib/src/model/link_result.dart +++ b/pkgs/native_assets_builder/lib/src/model/link_result.dart @@ -4,8 +4,6 @@ import 'package:native_assets_cli/native_assets_cli_internal.dart'; -import '../build_runner/build_runner.dart'; - /// The result of executing the link hooks in dry run mode from all packages in /// the dependency tree of the entry point application. abstract interface class LinkResult { @@ -15,9 +13,4 @@ abstract interface class LinkResult { /// The files used by the hooks. List get dependencies; - - /// Whether all hooks completed without errors. - /// - /// All error messages are streamed to [NativeAssetsBuildRunner.logger]. - bool get success; } diff --git a/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart b/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart index e5616093b..98eec9cf5 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart @@ -26,7 +26,7 @@ void main() async { // Trigger a build, should invoke build for libraries with native assets. { final logMessages = []; - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, @@ -34,7 +34,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect( logMessages.join('\n'), stringContainsInOrder( diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart index 5f75a90ea..59e606757 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart @@ -32,7 +32,7 @@ void main() async { applicationAssetValidator: validateCodeAssetsInApplication, ); final fullLog = logMessages.join('\n'); - expect(result.success, false); + expect(result, isNull); expect( fullLog, contains('does not start with "package:wrong_namespace_asset/"'), @@ -66,7 +66,7 @@ void main() async { buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ); - expect(result.success, true); + expect(result, isNotNull); } }); }); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart index 9e3fa7c4f..096f00bc9 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart @@ -23,22 +23,22 @@ void main() async { logger: logger, ); - final dryRunResult = await buildDryRun( + final dryRunResult = (await buildDryRun( packageUri, logger, dartExecutable, linkingEnabled: false, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, - ); - final buildResult = await build( + ))!; + final buildResult = (await build( packageUri, logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect(dryRunResult.encodedAssets.length, 1); expect(buildResult.encodedAssets.length, 1); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart index 827b9d0ea..b81987c16 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart @@ -38,7 +38,7 @@ void main() async { applicationAssetValidator: validateCodeAssetsInApplication, ); final fullLog = logMessages.join('\n'); - expect(result.success, false); + expect(result, isNull); if (package == 'wrong_build_output_3') { // Should re-execute the process on second run. expect( diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart index c3ca4d278..9034149ee 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart @@ -28,7 +28,7 @@ void main() async { { final logMessages = []; - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, @@ -36,7 +36,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect( logMessages.join('\n'), contains( @@ -54,7 +54,7 @@ void main() async { { final logMessages = []; - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, @@ -62,7 +62,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect( logMessages.join('\n'), contains('Skipping build for native_add'), @@ -99,14 +99,14 @@ void main() async { await Future.delayed(const Duration(seconds: 1)); { - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; await expectSymbols( asset: CodeAsset.fromEncoded(result.encodedAssets.single), symbols: ['add']); @@ -118,14 +118,14 @@ void main() async { ); { - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; await expectSymbols( asset: CodeAsset.fromEncoded(result.encodedAssets.single), symbols: ['add', 'subtract'], @@ -152,14 +152,14 @@ void main() async { // cached. await Future.delayed(const Duration(seconds: 1)); - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; { final compiledHook = logMessages .where((m) => @@ -179,14 +179,14 @@ void main() async { targetUri: packageUri); { - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; { final compiledHook = logMessages .where((m) => diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_cycle_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_cycle_test.dart index 746cc2701..75321d0b5 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_cycle_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_cycle_test.dart @@ -31,7 +31,7 @@ void main() async { buildValidator: (config, output) async => [], ); final fullLog = logMessages.join('\n'); - expect(result.success, false); + expect(result, isNull); expect( fullLog, contains( @@ -52,7 +52,7 @@ void main() async { applicationAssetValidator: (_) async => [], ); final fullLog = logMessages.join('\n'); - expect(result.success, false); + expect(result, isNull); expect( fullLog, contains( diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart index f973b9c90..198ba4252 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart @@ -24,14 +24,14 @@ void main() async { ); { - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect(result.encodedAssets.length, 1); await expectSymbols( asset: CodeAsset.fromEncoded(result.encodedAssets.single), @@ -60,7 +60,7 @@ void main() async { applicationAssetValidator: validateCodeAssetsInApplication, ); final fullLog = logMessages.join('\n'); - expect(result.success, false); + expect(result, isNull); expect(fullLog, contains('To reproduce run:')); final reproCommand = fullLog .split('\n') @@ -78,14 +78,14 @@ void main() async { ); { - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect(result.encodedAssets.length, 1); await expectSymbols( asset: CodeAsset.fromEncoded(result.encodedAssets.single), diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart index c34013ae3..3799ed120 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart @@ -24,7 +24,7 @@ void main() async { { final logMessages = []; - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, @@ -33,14 +33,14 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect(result.encodedAssets, isEmpty); expect(result.dependencies, isEmpty); } { final logMessages = []; - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, @@ -49,7 +49,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect(result.encodedAssets, isNotEmpty); expect( result.dependencies, diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_reusability_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_reusability_test.dart index a19cffb95..c1e091691 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_reusability_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_reusability_test.dart @@ -27,9 +27,15 @@ void main() async { dartExecutable: dartExecutable, ); + BuildConfigBuilder configCreator() => BuildConfigBuilder() + ..setupCodeConfig( + targetArchitecture: Architecture.current, + linkModePreference: LinkModePreference.dynamic, + ); + await buildRunner.buildDryRun( + configCreator: configCreator, targetOS: Target.current.os, - linkModePreference: LinkModePreference.dynamic, workingDirectory: packageUri, includeParentEnvironment: true, linkingEnabled: false, @@ -37,8 +43,8 @@ void main() async { buildValidator: (config, output) async => [], ); await buildRunner.buildDryRun( + configCreator: configCreator, targetOS: Target.current.os, - linkModePreference: LinkModePreference.dynamic, workingDirectory: packageUri, includeParentEnvironment: true, linkingEnabled: false, @@ -46,9 +52,9 @@ void main() async { buildValidator: (config, output) async => [], ); await buildRunner.build( + configCreator: configCreator, + targetOS: OS.current, buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - target: Target.current, workingDirectory: packageUri, includeParentEnvironment: true, linkingEnabled: false, @@ -57,9 +63,9 @@ void main() async { applicationAssetValidator: (_) async => [], ); await buildRunner.build( + configCreator: configCreator, buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - target: Target.current, + targetOS: OS.current, workingDirectory: packageUri, includeParentEnvironment: true, linkingEnabled: false, diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart index e5b0ecf49..4443c2a31 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart @@ -46,7 +46,7 @@ void main() async { printOnFailure('cc: $cc'); - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, @@ -63,7 +63,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect(result.encodedAssets.length, 1); }); }); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart index 9c635ac51..aba3ba9ea 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart @@ -32,7 +32,7 @@ void main() async { // Trigger a build, should invoke build for libraries with native assets. { final logMessages = []; - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, @@ -40,7 +40,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect( logMessages.join('\n'), stringContainsInOrder([ @@ -57,7 +57,7 @@ void main() async { packageLayout = await PackageLayout.fromRootPackageRoot(packageUri); } final logMessages = []; - final result = await build( + final result = (await build( packageUri, logger, dartExecutable, @@ -66,7 +66,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect( false, logMessages.join('\n').contains( diff --git a/pkgs/native_assets_builder/test/build_runner/concurrency_shared_test_helper.dart b/pkgs/native_assets_builder/test/build_runner/concurrency_shared_test_helper.dart index bafbc2d5e..0f8f90ba1 100644 --- a/pkgs/native_assets_builder/test/build_runner/concurrency_shared_test_helper.dart +++ b/pkgs/native_assets_builder/test/build_runner/concurrency_shared_test_helper.dart @@ -20,19 +20,23 @@ void main(List args) async { logger: logger, dartExecutable: dartExecutable, ).build( + configCreator: () => BuildConfigBuilder() + ..setupCodeConfig( + targetArchitecture: target.architecture, + linkModePreference: LinkModePreference.dynamic, + targetAndroidNdkApi: target.os == OS.android ? 30 : null, + ), buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - target: target, + targetOS: target.os, workingDirectory: packageUri, includeParentEnvironment: true, linkingEnabled: false, supportedAssetTypes: [DataAsset.type], - targetAndroidNdkApi: target.os == OS.android ? 30 : null, buildValidator: (config, output) async => await validateDataAssetBuildOutput(config, output), applicationAssetValidator: (_) async => [], ); - if (!result.success) { + if (result == null) { throw Error(); } print('done'); diff --git a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart index 32ac611a6..47c80ddba 100644 --- a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart +++ b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart @@ -24,9 +24,13 @@ void main(List args) async { dartExecutable: dartExecutable, singleHookTimeout: timeout, ).build( + configCreator: () => BuildConfigBuilder() + ..setupCodeConfig( + targetArchitecture: Architecture.current, + linkModePreference: LinkModePreference.dynamic, + ), buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - target: Target.current, + targetOS: OS.current, workingDirectory: packageUri, includeParentEnvironment: true, linkingEnabled: false, @@ -37,7 +41,7 @@ void main(List args) async { ], applicationAssetValidator: validateCodeAssetsInApplication, ); - if (!result.success) { + if (result == null) { throw Error(); } print('done'); diff --git a/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart b/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart index 78d4ddca8..c0eecc0ec 100644 --- a/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart @@ -32,7 +32,7 @@ void main() async { applicationAssetValidator: validateCodeAssetsInApplication, ); final fullLog = logMessages.join('\n'); - expect(result.success, false); + expect(result, isNull); expect( fullLog, contains('Duplicate dynamic library file name'), @@ -52,7 +52,7 @@ void main() async { logger: logger, ); - final buildResult = await build( + final buildResult = (await build( packageUri, logger, linkingEnabled: true, @@ -60,8 +60,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); - expect(buildResult.success, isTrue); + ))!; final linkResult = await link( packageUri, @@ -73,7 +72,7 @@ void main() async { applicationAssetValidator: validateCodeAssetsInApplication, ); // Application validation error due to conflicting dylib name. - expect(linkResult.success, isFalse); + expect(linkResult, isNull); }); }); } diff --git a/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart b/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart index 021a3d2fd..b2c3b85b9 100644 --- a/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart @@ -86,11 +86,11 @@ void main() async { ); final fullLog = logMessages.join('\n'); if (hook == 'build') { - expect(buildResult.success, success); + expect(buildResult, success ? isNotNull : isNull); } else { assert(hook == 'link'); - expect(buildResult.success, true); - expect(linkResult.success, success); + expect(buildResult, isNotNull); + expect(linkResult, success ? isNotNull : isNull); } if (!success) { expect( diff --git a/pkgs/native_assets_builder/test/build_runner/helpers.dart b/pkgs/native_assets_builder/test/build_runner/helpers.dart index daaa8f8b1..b40825943 100644 --- a/pkgs/native_assets_builder/test/build_runner/helpers.dart +++ b/pkgs/native_assets_builder/test/build_runner/helpers.dart @@ -7,7 +7,6 @@ import 'dart:io'; import 'package:logging/logging.dart'; import 'package:native_assets_builder/native_assets_builder.dart'; -import 'package:native_assets_builder/src/model/hook_result.dart'; import 'package:test/test.dart'; import '../helpers.dart'; @@ -29,7 +28,7 @@ Future runPubGet({ expect(result.exitCode, 0); } -Future build( +Future build( Uri packageUri, Logger logger, Uri dartExecutable, { @@ -47,32 +46,36 @@ Future build( int? targetAndroidNdkApi, Target? target, bool linkingEnabled = false, - required Iterable supportedAssetTypes, + required List supportedAssetTypes, }) async => await runWithLog(capturedLogs, () async { final result = await NativeAssetsBuildRunner( logger: logger, dartExecutable: dartExecutable, ).build( + configCreator: () => BuildConfigBuilder() + ..setupCodeConfig( + targetArchitecture: target?.architecture ?? Architecture.current, + linkModePreference: linkModePreference, + cCompilerConfig: cCompilerConfig, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion, + targetAndroidNdkApi: targetAndroidNdkApi, + ), buildMode: BuildMode.release, - linkModePreference: linkModePreference, - target: target ?? Target.current, + targetOS: target?.os ?? OS.current, workingDirectory: packageUri, - cCompilerConfig: cCompilerConfig, includeParentEnvironment: includeParentEnvironment, packageLayout: packageLayout, runPackageName: runPackageName, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, linkingEnabled: linkingEnabled, supportedAssetTypes: supportedAssetTypes, buildValidator: buildValidator, applicationAssetValidator: applicationAssetValidator, ); - if (result.success) { + if (result != null) { expect(await result.encodedAssets.allExist(), true); for (final encodedAssetsForLinking in result.encodedAssetsForLinking.values) { @@ -83,7 +86,7 @@ Future build( return result; }); -Future link( +Future link( Uri packageUri, Logger logger, Uri dartExecutable, { @@ -101,39 +104,43 @@ Future link( int? targetMacOSVersion, int? targetAndroidNdkApi, Target? target, - required Iterable supportedAssetTypes, + required List supportedAssetTypes, }) async => await runWithLog(capturedLogs, () async { final result = await NativeAssetsBuildRunner( logger: logger, dartExecutable: dartExecutable, ).link( - linkModePreference: linkModePreference, + configCreator: () => LinkConfigBuilder() + ..setupCodeConfig( + targetArchitecture: target?.architecture ?? Architecture.current, + linkModePreference: linkModePreference, + cCompilerConfig: cCompilerConfig, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion, + targetAndroidNdkApi: targetAndroidNdkApi, + ), buildMode: BuildMode.release, - target: target ?? Target.current, + targetOS: target?.os ?? OS.current, workingDirectory: packageUri, - cCompilerConfig: cCompilerConfig, includeParentEnvironment: includeParentEnvironment, packageLayout: packageLayout, buildResult: buildResult, resourceIdentifiers: resourceIdentifiers, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, supportedAssetTypes: supportedAssetTypes, linkValidator: linkValidator, applicationAssetValidator: applicationAssetValidator, ); - if (result.success) { + if (result != null) { expect(await result.encodedAssets.allExist(), true); } return result; }); -Future<(BuildResult, LinkResult)> buildAndLink( +Future<(BuildResult?, LinkResult?)> buildAndLink( Uri packageUri, Logger logger, Uri dartExecutable, { @@ -152,7 +159,7 @@ Future<(BuildResult, LinkResult)> buildAndLink( int? targetAndroidNdkApi, Target? target, Uri? resourceIdentifiers, - required Iterable supportedAssetTypes, + required List supportedAssetTypes, }) async => await runWithLog(capturedLogs, () async { final buildRunner = NativeAssetsBuildRunner( @@ -160,26 +167,30 @@ Future<(BuildResult, LinkResult)> buildAndLink( dartExecutable: dartExecutable, ); final buildResult = await buildRunner.build( + configCreator: () => BuildConfigBuilder() + ..setupCodeConfig( + targetArchitecture: target?.architecture ?? Architecture.current, + linkModePreference: linkModePreference, + cCompilerConfig: cCompilerConfig, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion, + targetAndroidNdkApi: targetAndroidNdkApi, + ), buildMode: BuildMode.release, - linkModePreference: linkModePreference, - target: target ?? Target.current, + targetOS: target?.os ?? OS.current, workingDirectory: packageUri, - cCompilerConfig: cCompilerConfig, includeParentEnvironment: includeParentEnvironment, packageLayout: packageLayout, runPackageName: runPackageName, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, linkingEnabled: true, supportedAssetTypes: supportedAssetTypes, buildValidator: buildValidator, applicationAssetValidator: applicationAssetValidator, ); - if (!buildResult.success) { - return (buildResult, HookResult()); + if (buildResult == null) { + return (null, null); } expect(await buildResult.encodedAssets.allExist(), true); @@ -189,26 +200,30 @@ Future<(BuildResult, LinkResult)> buildAndLink( } final linkResult = await buildRunner.link( - linkModePreference: linkModePreference, + configCreator: () => LinkConfigBuilder() + ..setupCodeConfig( + targetArchitecture: target?.architecture ?? Architecture.current, + linkModePreference: linkModePreference, + cCompilerConfig: cCompilerConfig, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion, + targetAndroidNdkApi: targetAndroidNdkApi, + ), buildMode: BuildMode.release, - target: target ?? Target.current, + targetOS: target?.os ?? OS.current, workingDirectory: packageUri, - cCompilerConfig: cCompilerConfig, includeParentEnvironment: includeParentEnvironment, packageLayout: packageLayout, buildResult: buildResult, resourceIdentifiers: resourceIdentifiers, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, supportedAssetTypes: supportedAssetTypes, linkValidator: linkValidator, applicationAssetValidator: applicationAssetValidator, ); - if (linkResult.success) { - expect(await buildResult.encodedAssets.allExist(), true); + if (linkResult != null) { + expect(await linkResult.encodedAssets.allExist(), true); } return (buildResult, linkResult); @@ -233,7 +248,7 @@ Future runWithLog( return result; } -Future buildDryRun( +Future buildDryRun( Uri packageUri, Logger logger, Uri dartExecutable, { @@ -244,14 +259,18 @@ Future buildDryRun( List? capturedLogs, PackageLayout? packageLayout, required bool linkingEnabled, - required Iterable supportedAssetTypes, + required List supportedAssetTypes, }) async => runWithLog(capturedLogs, () async { final result = await NativeAssetsBuildRunner( logger: logger, dartExecutable: dartExecutable, ).buildDryRun( - linkModePreference: linkModePreference, + configCreator: () => BuildConfigBuilder() + ..setupCodeConfig( + targetArchitecture: null, + linkModePreference: linkModePreference, + ), targetOS: Target.current.os, workingDirectory: packageUri, includeParentEnvironment: includeParentEnvironment, diff --git a/pkgs/native_assets_builder/test/build_runner/link_caching_test.dart b/pkgs/native_assets_builder/test/build_runner/link_caching_test.dart index f43429f8e..21f20657c 100644 --- a/pkgs/native_assets_builder/test/build_runner/link_caching_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/link_caching_test.dart @@ -33,7 +33,7 @@ void main() async { late LinkResult linkResult; Future runBuild() async { logMessages.clear(); - buildResult = await build( + buildResult = (await build( packageUri, logger, dartExecutable, @@ -42,12 +42,12 @@ void main() async { capturedLogs: logMessages, buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], - ); + ))!; } Future runLink() async { logMessages.clear(); - linkResult = await link( + linkResult = (await link( packageUri, logger, dartExecutable, @@ -56,11 +56,11 @@ void main() async { capturedLogs: logMessages, linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], - ); + ))!; } await runBuild(); - expect(buildResult.success, isTrue); + expect(buildResult, isNotNull); expect( logMessages.join('\n'), stringContainsInOrder([ @@ -74,7 +74,7 @@ void main() async { ); await runLink(); - expect(linkResult.success, isTrue); + expect(linkResult, isNotNull); expect( logMessages.join('\n'), stringContainsInOrder([ @@ -88,14 +88,14 @@ void main() async { ); await runBuild(); - expect(buildResult.success, isTrue); + expect(buildResult, isNotNull); expect( logMessages.join('\n'), contains('Skipping build for $packageName'), ); await runLink(); - expect(linkResult.success, isTrue); + expect(linkResult, isNotNull); expect( logMessages.join('\n'), contains('Skipping link for $packageName'), @@ -110,28 +110,28 @@ void main() async { await Future.delayed(const Duration(seconds: 1)); await runBuild(); - expect(buildResult.success, isTrue); + expect(buildResult, isNotNull); expect( logMessages.join('\n'), stringContainsInOrder(['Running', 'hook.dill']), ); await runLink(); - expect(linkResult.success, isTrue); + expect(linkResult, isNotNull); expect( logMessages.join('\n'), stringContainsInOrder(['Running', 'hook.dill']), ); await runBuild(); - expect(buildResult.success, isTrue); + expect(buildResult, isNotNull); expect( logMessages.join('\n'), contains('Skipping build for $packageName'), ); await runLink(); - expect(linkResult.success, isTrue); + expect(linkResult, isNotNull); expect( logMessages.join('\n'), contains('Skipping link for $packageName'), diff --git a/pkgs/native_assets_builder/test/build_runner/link_test.dart b/pkgs/native_assets_builder/test/build_runner/link_test.dart index cd261d578..c5006bc31 100644 --- a/pkgs/native_assets_builder/test/build_runner/link_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/link_test.dart @@ -26,7 +26,7 @@ void main() async { logger: logger, ); - final buildResult = await build( + final buildResult = (await build( packageUri, logger, dartExecutable, @@ -34,10 +34,10 @@ void main() async { supportedAssetTypes: [DataAsset.type], buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], - ); + ))!; expect(buildResult.encodedAssets.length, 0); - final linkResult = await link( + final linkResult = (await link( packageUri, logger, dartExecutable, @@ -45,10 +45,10 @@ void main() async { supportedAssetTypes: [DataAsset.type], linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], - ); + ))!; expect(linkResult.encodedAssets.length, 2); - final buildNoLinkResult = await build( + final buildNoLinkResult = (await build( packageUri, logger, dartExecutable, @@ -56,7 +56,7 @@ void main() async { supportedAssetTypes: [DataAsset.type], buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], - ); + ))!; expect(buildNoLinkResult.encodedAssets.length, 4); }); }, @@ -102,8 +102,8 @@ void main() async { buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], ); - expect(buildResult.success, true); - expect(_getNames(buildResult.encodedAssets), + expect(buildResult, isNotNull); + expect(_getNames(buildResult!.encodedAssets), unorderedEquals(builtHelperAssets)); expect( _getNames(buildResult.encodedAssetsForLinking['complex_link']!), @@ -119,9 +119,9 @@ void main() async { linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], ); - expect(linkResult.success, true); + expect(linkResult, isNotNull); - expect(_getNames(linkResult.encodedAssets), + expect(_getNames(linkResult!.encodedAssets), unorderedEquals([...builtHelperAssets, ...linkedAssets])); }); }, @@ -138,7 +138,7 @@ void main() async { logger: logger, ); - final buildResult = await build( + final buildResult = (await build( packageUri, logger, dartExecutable, @@ -146,12 +146,12 @@ void main() async { supportedAssetTypes: [DataAsset.type], buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], - ); + ))!; expect(buildResult.encodedAssets.length, 0); expect(buildResult.encodedAssetsForLinking.length, 0); final logMessages = []; - final linkResult = await link( + final linkResult = (await link( packageUri, logger, dartExecutable, @@ -160,7 +160,7 @@ void main() async { supportedAssetTypes: [DataAsset.type], linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], - ); + ))!; expect(linkResult.encodedAssets.length, 0); expect( logMessages, @@ -191,7 +191,7 @@ void main() async { logger: logger, ); - final buildResult = await build( + final buildResult = (await build( packageUri, logger, dartExecutable, @@ -199,12 +199,12 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect(buildResult.encodedAssets.length, 0); expect(buildResult.encodedAssetsForLinking.length, 1); final logMessages = []; - final linkResult = await link( + final linkResult = (await link( packageUri, logger, dartExecutable, @@ -213,7 +213,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], linkValidator: validateCodeAssetLinkOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; expect(linkResult.encodedAssets.length, 1); expect(linkResult.encodedAssets.first.type, CodeAsset.type); }); diff --git a/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart b/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart index 55b20dba4..ae62b4295 100644 --- a/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart @@ -21,7 +21,7 @@ void main() async { logger: logger, ); - final resultDynamic = await build( + final resultDynamic = (await build( packageUri, logger, dartExecutable, @@ -29,9 +29,9 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; - final resultPreferDynamic = await build( + final resultPreferDynamic = (await build( packageUri, logger, dartExecutable, @@ -39,9 +39,9 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; - final resultStatic = await build( + final resultStatic = (await build( packageUri, logger, dartExecutable, @@ -49,9 +49,9 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; - final resultPreferStatic = await build( + final resultPreferStatic = (await build( packageUri, logger, dartExecutable, @@ -59,7 +59,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, - ); + ))!; // This package honors preferences. expect( diff --git a/pkgs/native_assets_builder/test/build_runner/resources_test.dart b/pkgs/native_assets_builder/test/build_runner/resources_test.dart index 14b80af78..3ae036471 100644 --- a/pkgs/native_assets_builder/test/build_runner/resources_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/resources_test.dart @@ -29,7 +29,7 @@ void main() async { logger: logger, ); - final buildResult = await build( + final buildResult = (await build( packageUri, logger, dartExecutable, @@ -37,7 +37,7 @@ void main() async { supportedAssetTypes: [DataAsset.type], buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], - ); + ))!; Iterable buildFiles() => Directory.fromUri( packageUri.resolve('.dart_tool/native_assets_builder/')) diff --git a/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart b/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart index 01e637f5a..0f776dd47 100644 --- a/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart @@ -30,9 +30,10 @@ void main() async { supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, + linkingEnabled: true, ); final fullLog = logMessages.join('\n'); - expect(result.success, false); + expect(result, isNull); expect( fullLog, contains('but that package does not have a link hook'), diff --git a/pkgs/native_assets_builder/test/test_data/native_dynamic_linking_test.dart b/pkgs/native_assets_builder/test/test_data/native_dynamic_linking_test.dart index fbf4947d2..5865d93fb 100644 --- a/pkgs/native_assets_builder/test/test_data/native_dynamic_linking_test.dart +++ b/pkgs/native_assets_builder/test/test_data/native_dynamic_linking_test.dart @@ -32,25 +32,26 @@ void main() async { final testPackageUri = testDataUri.resolve('$name/'); final dartUri = Uri.file(Platform.resolvedExecutable); - final config = BuildConfigImpl( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: name, - packageRoot: testPackageUri, - targetOS: OS.current, - version: HookConfigImpl.latestVersion, - linkModePreference: LinkModePreference.dynamic, - dryRun: dryRun, - linkingEnabled: false, - targetArchitecture: dryRun ? null : Architecture.current, - buildMode: dryRun ? null : BuildMode.debug, - cCompiler: dryRun ? null : cCompiler, - supportedAssetTypes: [CodeAsset.type], - ); + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: name, + packageRoot: testPackageUri, + targetOS: OS.current, + supportedAssetTypes: [CodeAsset.type], + buildMode: dryRun ? null : BuildMode.debug) + ..setupBuildConfig(dryRun: dryRun, linkingEnabled: false) + ..setupBuildRunConfig( + outputDirectory: outputDirectory, + outputDirectoryShared: outputDirectoryShared) + ..setupCodeConfig( + targetArchitecture: dryRun ? null : Architecture.current, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: dryRun ? null : cCompiler, + ); final buildConfigUri = testTempUri.resolve('build_config.json'); File.fromUri(buildConfigUri) - .writeAsStringSync(jsonEncode(config.toJson())); + .writeAsStringSync(jsonEncode(configBuilder.json)); final processResult = await Process.run( dartUri.toFilePath(), @@ -68,8 +69,9 @@ void main() async { expect(processResult.exitCode, 0); final buildOutputUri = outputDirectory.resolve('build_output.json'); - final buildOutput = HookOutputImpl.fromJsonString( - await File.fromUri(buildOutputUri).readAsString()); + final buildOutput = BuildOutput( + json.decode(await File.fromUri(buildOutputUri).readAsString()) + as Map); final assets = buildOutput.encodedAssets; final dependencies = buildOutput.dependencies; if (dryRun) { diff --git a/pkgs/native_assets_builder/test/test_data/transformer_test.dart b/pkgs/native_assets_builder/test/test_data/transformer_test.dart index 334fa8724..acd50699b 100644 --- a/pkgs/native_assets_builder/test/test_data/transformer_test.dart +++ b/pkgs/native_assets_builder/test/test_data/transformer_test.dart @@ -45,24 +45,25 @@ void main() async { late BuildOutput output; Future runBuild(Architecture architecture) async { - final config = BuildConfigImpl( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageUri, - targetOS: OS.current, - version: HookConfigImpl.latestVersion, - linkModePreference: LinkModePreference.dynamic, - dryRun: false, - linkingEnabled: false, - targetArchitecture: architecture, - buildMode: BuildMode.debug, - supportedAssetTypes: [DataAsset.type], - ); + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: packageUri, + targetOS: OS.current, + supportedAssetTypes: [DataAsset.type], + buildMode: BuildMode.debug) + ..setupBuildConfig(dryRun: false, linkingEnabled: false) + ..setupBuildRunConfig( + outputDirectory: outputDirectory, + outputDirectoryShared: outputDirectoryShared) + ..setupCodeConfig( + targetArchitecture: architecture, + linkModePreference: LinkModePreference.dynamic, + ); final buildConfigUri = testTempUri.resolve('build_config.json'); - await File.fromUri(buildConfigUri) - .writeAsString(jsonEncode(config.toJson())); + File.fromUri(buildConfigUri) + .writeAsStringSync(jsonEncode(configBuilder.json)); final processResult = await Process.run( dartUri.toFilePath(), @@ -81,8 +82,9 @@ void main() async { stdout = processResult.stdout as String; final buildOutputUri = outputDirectory.resolve('build_output.json'); - output = HookOutputImpl.fromJsonString( - await File.fromUri(buildOutputUri).readAsString()); + output = BuildOutput( + json.decode(await File.fromUri(buildOutputUri).readAsString()) + as Map); } await runBuild(Architecture.x64); @@ -94,7 +96,7 @@ void main() async { ]), ); expect( - output.dataAssets.all, + output.dataAssets, contains( DataAsset( file: outputDirectoryShared.resolve('data_transformed0.json'), diff --git a/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart b/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart index fb9921e47..3dfcb16c7 100644 --- a/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart @@ -6,13 +6,14 @@ import 'package:native_assets_cli/native_assets_cli.dart'; void main(List arguments) async { await link(arguments, (config, output) async { - print(''' -Received ${config.codeAssets.all.length} encodedAssets: ${config.codeAssets.all.map((e) => e.id)}. -'''); - output.codeAssets.addAll( - config.codeAssets.all.where((asset) => asset.id.endsWith('add'))); - print(''' -Keeping only ${output.codeAssets.all.map((e) => e.id)}. -'''); + for (final codeAsset in config.codeAssets.all) { + print('Got code asset: ${codeAsset.id}'); + if (codeAsset.id.endsWith('add')) { + output.codeAssets.add(codeAsset); + print('-> Keeping ${codeAsset.id}'); + } else { + print('-> Dropping ${codeAsset.id}'); + } + } }); } diff --git a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version/hook/build.dart b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version/hook/build.dart index 73ef7a438..1f9200207 100644 --- a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version/hook/build.dart @@ -15,14 +15,15 @@ const minMacOSVersionForThisPackage = 13; void main(List arguments) async { await build(arguments, (config, output) async { if (config.targetOS == OS.android) { - if (config.targetAndroidNdkApi! < minNdkApiVersionForThisPackage) { + if (config.codeConfig.targetAndroidNdkApi! < + minNdkApiVersionForThisPackage) { throw UnsupportedError( 'The native assets for this package require at ' 'least Android NDK API level $minNdkApiVersionForThisPackage.', ); } } else if (config.targetOS == OS.iOS) { - final iosVersion = config.targetIOSVersion; + final iosVersion = config.codeConfig.targetIOSVersion; // iosVersion is nullable to deal with version skew. if (iosVersion != null && iosVersion < minIosVersionForThisPackage) { throw UnsupportedError( @@ -31,7 +32,7 @@ void main(List arguments) async { ); } } else if (config.targetOS == OS.macOS) { - final macosVersion = config.targetMacOSVersion; + final macosVersion = config.codeConfig.targetMacOSVersion; // macosVersion is nullable to deal with version skew. if (macosVersion != null && macosVersion < minMacOSVersionForThisPackage) { diff --git a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_linker/hook/link.dart b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_linker/hook/link.dart index 3036e8749..ae888ae8e 100644 --- a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_linker/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_linker/hook/link.dart @@ -15,14 +15,15 @@ const minMacOSVersionForThisPackage = 13; void main(List arguments) async { await link(arguments, (config, output) async { if (config.targetOS == OS.android) { - if (config.targetAndroidNdkApi! < minNdkApiVersionForThisPackage) { + if (config.codeConfig.targetAndroidNdkApi! < + minNdkApiVersionForThisPackage) { throw UnsupportedError( 'The native assets for this package require at ' 'least Android NDK API level $minNdkApiVersionForThisPackage.', ); } } else if (config.targetOS == OS.iOS) { - final iosVersion = config.targetIOSVersion; + final iosVersion = config.codeConfig.targetIOSVersion; // iosVersion is nullable to deal with version skew. if (iosVersion != null && iosVersion < minIosVersionForThisPackage) { throw UnsupportedError( @@ -31,7 +32,7 @@ void main(List arguments) async { ); } } else if (config.targetOS == OS.macOS) { - final macosVersion = config.targetMacOSVersion; + final macosVersion = config.codeConfig.targetMacOSVersion; // macosVersion is nullable to deal with version skew. if (macosVersion != null && macosVersion < minMacOSVersionForThisPackage) { diff --git a/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart b/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart index aab673ecc..30fa8ef31 100644 --- a/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart @@ -18,16 +18,17 @@ void main(List arguments) async { ], ); // Temp output to prevent outputting the dylib for bundling. - final tempBuildOutput = BuildOutput(); + final outputBuilder = BuildOutputBuilder(); await cbuilder.run( config: config, - output: tempBuildOutput, + output: outputBuilder, logger: Logger('') ..level = Level.ALL ..onRecord.listen((record) { print('${record.level.name}: ${record.time}: ${record.message}'); }), ); + final tempBuildOutput = BuildOutput(outputBuilder.json); output.addEncodedAsset( tempBuildOutput.encodedAssets.single, // Send dylib to linking if linking is enabled. diff --git a/pkgs/native_assets_builder/test_data/package_reading_metadata/hook/build.dart b/pkgs/native_assets_builder/test_data/package_reading_metadata/hook/build.dart index 10d8fcc10..5ae35355f 100644 --- a/pkgs/native_assets_builder/test_data/package_reading_metadata/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/package_reading_metadata/hook/build.dart @@ -7,18 +7,20 @@ import 'package:native_assets_cli/native_assets_cli.dart'; void main(List args) async { - final buildConfig = BuildConfig(args); - if (!buildConfig.dryRun) { - final someValue = - buildConfig.metadatum('package_with_metadata', 'some_key'); - assert(someValue != null); - final someInt = buildConfig.metadatum('package_with_metadata', 'some_int'); - assert(someInt != null); - print({ - 'some_int': someInt, - 'some_key': someValue, - }); - } else { - print('meta data not available in dry run'); - } + await build(args, (buildConfig, _) async { + if (!buildConfig.dryRun) { + final someValue = + buildConfig.metadatum('package_with_metadata', 'some_key'); + assert(someValue != null); + final someInt = + buildConfig.metadatum('package_with_metadata', 'some_int'); + assert(someInt != null); + print({ + 'some_int': someInt, + 'some_key': someValue, + }); + } else { + print('meta data not available in dry run'); + } + }); } diff --git a/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart b/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart index 9e4d9f2ee..3478258ab 100644 --- a/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart @@ -10,7 +10,7 @@ void main(List args) async { }); } -void shake(LinkOutput output, Iterable assets) { +void shake(LinkOutputBuilder output, Iterable assets) { for (final asset in assets.skip(2)) { output.dataAssets.add(asset); diff --git a/pkgs/native_assets_builder/test_data/wrong_build_output/hook/build.dart b/pkgs/native_assets_builder/test_data/wrong_build_output/hook/build.dart index cd8dac2c2..d1d26aeb1 100644 --- a/pkgs/native_assets_builder/test_data/wrong_build_output/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/wrong_build_output/hook/build.dart @@ -2,13 +2,18 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/src/args_parser.dart'; void main(List args) async { - final buildConfig = BuildConfigImpl.fromArguments(args); - await File.fromUri(buildConfig.outputFile).writeAsString(_wrongContents); + final configPath = getConfigArgument(args); + final buildConfig = BuildConfig( + json.decode(File(configPath).readAsStringSync()) as Map); + await File.fromUri(buildConfig.outputDirectory.resolve('build_output.json')) + .writeAsString(_wrongContents); } const _wrongContents = ''' diff --git a/pkgs/native_assets_builder/test_data/wrong_build_output_2/hook/build.dart b/pkgs/native_assets_builder/test_data/wrong_build_output_2/hook/build.dart index dfb5b5e20..9f8ff4ed8 100644 --- a/pkgs/native_assets_builder/test_data/wrong_build_output_2/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/wrong_build_output_2/hook/build.dart @@ -2,13 +2,18 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/src/args_parser.dart'; void main(List args) async { - final buildConfig = BuildConfigImpl.fromArguments(args); - await File.fromUri(buildConfig.outputFile).writeAsString(_wrongContents); + final configPath = getConfigArgument(args); + final buildConfig = BuildConfig( + json.decode(File(configPath).readAsStringSync()) as Map); + await File.fromUri(buildConfig.outputDirectory.resolve('build_output.json')) + .writeAsString(_wrongContents); } const _wrongContents = ''' diff --git a/pkgs/native_assets_builder/test_data/wrong_build_output_3/hook/build.dart b/pkgs/native_assets_builder/test_data/wrong_build_output_3/hook/build.dart index cb50e5731..58666acf2 100644 --- a/pkgs/native_assets_builder/test_data/wrong_build_output_3/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/wrong_build_output_3/hook/build.dart @@ -2,20 +2,25 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/src/args_parser.dart'; void main(List args) async { - final buildConfig = BuildConfigImpl.fromArguments(args); - await File.fromUri(buildConfig.outputFile).writeAsString(_rightContents); + final configPath = getConfigArgument(args); + final buildConfig = BuildConfig( + json.decode(File(configPath).readAsStringSync()) as Map); + await File.fromUri(buildConfig.outputDirectory.resolve('build_output.json')) + .writeAsString(_rightContents); exit(1); } -const _rightContents = ''' -timestamp: 2023-07-28 14:22:45.000 -encodedAssets: [] -dependencies: [] -metadata: {} -version: 1.0.0 -'''; +const _rightContents = '''{ + "timestamp": "2023-07-28 14:22:45.000", + "encodedAssets": [], + "dependencies": [], + "metadata": {}, + "version": "1.5.0" +}'''; diff --git a/pkgs/native_assets_builder/test_data/wrong_linker/hook/build.dart b/pkgs/native_assets_builder/test_data/wrong_linker/hook/build.dart index 8f3c9993c..4e06197eb 100644 --- a/pkgs/native_assets_builder/test_data/wrong_linker/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/wrong_linker/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli.dart'; void main(List arguments) async { await build(arguments, (config, output) async { @@ -28,14 +28,3 @@ void main(List arguments) async { ); }); } - -// Copy from `build`, but without the validation. -Future build( - List arguments, - Future Function(BuildConfig config, BuildOutput output) builder, -) async { - final config = BuildConfigImpl.fromArguments(arguments); - final output = HookOutputImpl(); - await builder(config, output); - await output.writeToFile(config: config); -} diff --git a/pkgs/native_assets_builder/test_data/wrong_namespace_asset/hook/build.dart b/pkgs/native_assets_builder/test_data/wrong_namespace_asset/hook/build.dart index 66ad30529..b923086ce 100644 --- a/pkgs/native_assets_builder/test_data/wrong_namespace_asset/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/wrong_namespace_asset/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli.dart'; void main(List arguments) async { await build(arguments, (config, output) async { @@ -27,14 +27,3 @@ void main(List arguments) async { ); }); } - -// Copy from `build`, but without the validation. -Future build( - List arguments, - Future Function(BuildConfig config, BuildOutput output) builder, -) async { - final config = BuildConfigImpl.fromArguments(arguments); - final output = HookOutputImpl(); - await builder(config, output); - await output.writeToFile(config: config); -} diff --git a/pkgs/native_assets_cli/example/build/local_asset/hook/build.dart b/pkgs/native_assets_cli/example/build/local_asset/hook/build.dart index 280945122..54540905c 100644 --- a/pkgs/native_assets_cli/example/build/local_asset/hook/build.dart +++ b/pkgs/native_assets_cli/example/build/local_asset/hook/build.dart @@ -11,7 +11,7 @@ final packageAssetPath = Uri.file('assets/$assetName'); Future main(List args) async { await build(args, (config, output) async { - if (config.linkModePreference == LinkModePreference.static) { + if (config.codeConfig.linkModePreference == LinkModePreference.static) { // Simulate that this build hook only supports dynamic libraries. throw UnsupportedError( 'LinkModePreference.static is not supported.', @@ -38,7 +38,8 @@ Future main(List args) async { file: assetPath, linkMode: DynamicLoadingBundled(), os: config.targetOS, - architecture: config.targetArchitecture, + architecture: + config.dryRun ? null : config.codeConfig.targetArchitecture, ), ); }); diff --git a/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart b/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart index eda5bcd25..c21063d6c 100644 --- a/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart +++ b/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart @@ -2,7 +2,6 @@ // for details. 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'; import 'package:native_assets_cli/test.dart'; import 'package:test/test.dart'; @@ -12,10 +11,16 @@ void main() { testBuildHook( description: 'test my build hook', mainMethod: build.main, + extraConfigSetup: (config) { + config.setupCodeConfig( + linkModePreference: LinkModePreference.dynamic, + targetArchitecture: Architecture.current, + ); + }, check: (_, output) { - expect(output.codeAssets.all, isNotEmpty); + expect(output.codeAssets, isNotEmpty); expect( - output.codeAssets.all.first.id, + output.codeAssets.first.id, 'package:local_asset/asset.txt', ); }, diff --git a/pkgs/native_assets_cli/lib/native_assets_cli.dart b/pkgs/native_assets_cli/lib/native_assets_cli.dart index 8bac2546a..9cf2d1821 100644 --- a/pkgs/native_assets_cli/lib/native_assets_cli.dart +++ b/pkgs/native_assets_cli/lib/native_assets_cli.dart @@ -7,12 +7,8 @@ library native_assets_cli; export 'src/api/build.dart' show build; -export 'src/api/build_config.dart' show BuildConfig; -export 'src/api/build_output.dart' show BuildOutput, LinkOutput; export 'src/api/builder.dart' show Builder; -export 'src/api/hook_config.dart' show HookConfig; export 'src/api/link.dart' show link; -export 'src/api/link_config.dart' show LinkConfig; export 'src/api/linker.dart' show Linker; export 'src/architecture.dart' show Architecture; export 'src/build_mode.dart' show BuildMode; @@ -21,12 +17,18 @@ export 'src/code_assets/code_asset.dart' show BuildOutputCodeAssets, CodeAsset, + CodeAssetBuildConfig, CodeAssetsBuildOutput, CodeAssetsLinkConfig, CodeAssetsLinkOutput, + CodeConfig, LinkConfigCodeAssets, LinkOutputCodeAssets, OSLibraryNaming; +export 'src/config.dart' show BuildConfig, BuildOutputBuilder; +export 'src/config.dart' show BuildOutput, LinkOutput, LinkOutputBuilder; +export 'src/config.dart' show HookConfig; +export 'src/config.dart' show LinkConfig; export 'src/data_assets/data_asset.dart' show BuildOutputDataAssets, diff --git a/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart b/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart index 173e9086e..95d1f5ec7 100644 --- a/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart +++ b/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart @@ -17,15 +17,18 @@ library native_assets_cli_internal; export 'native_assets_cli.dart' hide build, link; -export 'src/api/build_config.dart' show BuildConfigImpl; -export 'src/api/build_output.dart' show HookOutputImpl; -export 'src/api/hook_config.dart' show HookConfigImpl; -export 'src/api/link_config.dart' show LinkConfigImpl; +export 'src/code_assets/code_asset_bundling.dart' + show CodeAssetBuildConfigBuilder, CodeAssetBuildOutput, CodeAssetLinkOutput; export 'src/code_assets/validation.dart' show validateCodeAssetBuildOutput, validateCodeAssetLinkOutput, validateCodeAssetsInApplication; +export 'src/config.dart' show BuildConfigBuilder, LinkConfigBuilder; +export 'src/config.dart' show BuildOutputBuilder, LinkOutputBuilder; +export 'src/config.dart' show HookConfigBuilder, HookOutput; +export 'src/data_assets/data_asset_bundling.dart' + show DataAssetBuildOutput, DataAssetLinkOutput; export 'src/data_assets/validation.dart' show validateDataAssetBuildOutput, validateDataAssetLinkOutput; export 'src/encoded_asset.dart' show EncodedAsset; diff --git a/pkgs/native_assets_cli/lib/src/api/build.dart b/pkgs/native_assets_cli/lib/src/api/build.dart index b1a0eae93..8becd87eb 100644 --- a/pkgs/native_assets_cli/lib/src/api/build.dart +++ b/pkgs/native_assets_cli/lib/src/api/build.dart @@ -2,9 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:convert'; +import 'dart:io'; + +import '../args_parser.dart'; +import '../config.dart'; import '../validation.dart'; -import 'build_config.dart'; -import 'build_output.dart'; /// Runs a native assets build. /// @@ -86,14 +89,22 @@ import 'build_output.dart'; /// ``` Future build( List arguments, - Future Function(BuildConfig config, BuildOutput output) builder, + Future Function(BuildConfig config, BuildOutputBuilder output) builder, ) async { - final config = BuildConfigImpl.fromArguments(arguments); - final output = HookOutputImpl(); + final configPath = getConfigArgument(arguments); + final bytes = File(configPath).readAsBytesSync(); + final jsonConfig = const Utf8Decoder() + .fuse(const JsonDecoder()) + .convert(bytes) as Map; + final config = BuildConfig(jsonConfig); + final output = BuildOutputBuilder(); await builder(config, output); - final errors = await validateBuildOutput(config, output); + final errors = await validateBuildOutput(config, BuildOutput(output.json)); if (errors.isEmpty) { - await output.writeToFile(config: config); + final jsonOutput = + const JsonEncoder().fuse(const Utf8Encoder()).convert(output.json); + await File.fromUri(config.outputDirectory.resolve('build_output.json')) + .writeAsBytes(jsonOutput); } else { final message = [ 'The output contained unsupported output:', diff --git a/pkgs/native_assets_cli/lib/src/api/build_config.dart b/pkgs/native_assets_cli/lib/src/api/build_config.dart deleted file mode 100644 index 08c03389e..000000000 --- a/pkgs/native_assets_cli/lib/src/api/build_config.dart +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:convert'; -import 'dart:io'; - -import 'package:collection/collection.dart'; -import 'package:pub_semver/pub_semver.dart'; - -import '../architecture.dart'; -import '../args_parser.dart'; -import '../build_mode.dart'; -import '../c_compiler_config.dart'; -import '../ios_sdk.dart'; -import '../json_utils.dart'; -import '../link_mode_preference.dart'; -import '../model/hook.dart'; -import '../model/metadata.dart'; -import '../os.dart'; -import '../utils/json.dart'; -import '../utils/map.dart'; -import 'build.dart'; -import 'build_output.dart'; -import 'deprecation_messages.dart'; -import 'hook_config.dart'; - -part '../model/build_config.dart'; - -/// The configuration for a build hook (`hook/build.dart`) invocation. -/// -/// A package can optionally provide build hook. If such a hook exists, it will -/// be automatically run, by the Flutter and Dart SDK tools. The hook will be -/// run with specific commandline arguments, which [BuildConfig] can parse and -/// provide more convenient access to. -abstract final class BuildConfig implements HookConfig { - /// Metadata from a direct dependency. - /// - /// The [packageName] of is the package name of the direct dependency. - /// - /// Returns `null` if metadata was not provided. - /// - /// Not available during a [dryRun]. Will throw a [StateError] if accessed - /// during a [dryRun]. - @Deprecated(metadataDeprecation) - Object? metadatum(String packageName, String key); - - /// Whether link hooks will be run after the build hooks. - /// - /// If [linkingEnabled] is true, [BuildOutput.addEncodedAsset] may be called - /// with the`linkInPackage` parameter so that assets can be linked in a link - /// hook. - /// Linking is enabled in Flutter release builds and Dart AOT configurations. - /// These configurations are optimized for app size. - /// - `flutter build` - /// - `flutter run --release` - /// - `dart build` - /// - /// If [linkingEnabled] is false, no assets should be added with the - /// `linkInPackage` parameter set. All assets must be ready for bundling. - /// Linking is disabled in Flutter debug builds and Dart JIT configurations. - /// These configurations are optimized for development speed. - /// - `dart run` - /// - `flutter run` (debug mode) - bool get linkingEnabled; - - /// The version of [BuildConfig]. - /// - /// The build config is used in the protocol between the Dart and Flutter SDKs - /// and packages through build hook invocations. - /// - /// We're trying to avoid breaking changes. However, in the case that we have - /// to, the major version mismatch between the Dart or Flutter SDK and build - /// hook (`hook/build.dart`) will lead to a nice error message. - static Version get latestVersion => HookConfigImpl.latestVersion; - - /// Constructs a config by parsing CLI arguments and loading the config file. - /// - /// Build hooks will most likely use [build] instead of this constructor. - /// - /// The [arguments] must be commandline arguments. - /// - /// If provided, [environment] must be a map containing environment variables. - /// If not provided, [environment] defaults to [Platform.environment]. - /// - /// If provided, [workingDirectory] is used to resolves paths inside - /// [environment]. If not provided, [workingDirectory] defaults to - /// [Directory.current]. - /// - /// This async constructor is intended to be used directly in CLI files. - factory BuildConfig( - List arguments, { - Map? environment, - Uri? workingDirectory, - }) => - BuildConfigImpl.fromArguments( - arguments, - environment: environment, - workingDirectory: workingDirectory, - ); - - /// Constructs a config for a non-dry run by providing values for each field. - /// - /// Build hooks will most likely use [build] instead of this constructor. - /// However, for unit testing code which consumes a [BuildConfig], this - /// constructor facilitates easy construction. - /// - /// For the documentation of the parameters, see the equally named fields. - /// - /// Parameter [dependencyMetadata] must be a nested map `{'packageName' : - /// {'key' : 'value'}}` where `packageName` and `key` correspond to the - // ignore: deprecated_member_use_from_same_package - /// parameters in [metadatum]. - factory BuildConfig.build({ - required Uri outputDirectory, - required Uri outputDirectoryShared, - required String packageName, - required Uri packageRoot, - required BuildMode buildMode, - required Architecture targetArchitecture, - required OS targetOS, - IOSSdk? targetIOSSdk, - int? targetIOSVersion, - int? targetMacOSVersion, - int? targetAndroidNdkApi, - CCompilerConfig? cCompiler, - required LinkModePreference linkModePreference, - @Deprecated(metadataDeprecation) - Map>? dependencyMetadata, - required Iterable supportedAssetTypes, - required bool linkingEnabled, - }) => - BuildConfigImpl( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRoot, - buildMode: buildMode, - targetArchitecture: targetArchitecture, - targetOS: targetOS, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, - cCompiler: cCompiler, - linkModePreference: linkModePreference, - dependencyMetadata: dependencyMetadata != null - ? { - for (final entry in dependencyMetadata.entries) - entry.key: Metadata(entry.value.cast()) - } - : null, - linkingEnabled: linkingEnabled, - supportedAssetTypes: supportedAssetTypes, - ); - - /// Constructs a config for a dry run by providing values for each field. - /// - /// Build hooks will most likely use [build] instead of this constructor. - /// However, for unit testing code which consumes a [BuildConfig], this - /// constructor facilitates easy construction. - /// - /// For the documentation of the parameters, see the equally named fields. - factory BuildConfig.dryRun({ - required Uri outputDirectory, - required Uri outputDirectoryShared, - required String packageName, - required Uri packageRoot, - required OS targetOS, - required LinkModePreference linkModePreference, - required bool linkingEnabled, - required Iterable supportedAssetTypes, - }) => - BuildConfigImpl.dryRun( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRoot, - targetOS: targetOS, - linkModePreference: linkModePreference, - supportedAssetTypes: supportedAssetTypes, - linkingEnabled: linkingEnabled, - ); -} diff --git a/pkgs/native_assets_cli/lib/src/api/build_output.dart b/pkgs/native_assets_cli/lib/src/api/build_output.dart deleted file mode 100644 index a435bf066..000000000 --- a/pkgs/native_assets_cli/lib/src/api/build_output.dart +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:convert'; -import 'dart:io'; - -import 'package:collection/collection.dart'; -import 'package:pub_semver/pub_semver.dart'; - -import '../architecture.dart'; -import '../encoded_asset.dart'; -import '../json_utils.dart'; -import '../model/dependencies.dart'; -import '../model/metadata.dart'; -import '../os.dart'; -import '../utils/datetime.dart'; -import '../utils/file.dart'; -import '../utils/json.dart'; -import '../utils/map.dart'; -import 'build.dart'; -import 'build_config.dart'; -import 'builder.dart'; -import 'deprecation_messages.dart'; -import 'hook_config.dart'; -import 'link.dart'; -import 'linker.dart'; - -part '../model/hook_output.dart'; -part 'link_output.dart'; - -/// The output of a build hook (`hook/build.dart`) invocation. -/// -/// A package can optionally provide build hook (`hook/build.dart`). If such a -/// hook exists, it will be automatically run, by the Flutter and Dart SDK -/// tools. The hook is expect to produce a specific output which [BuildOutput] -/// can produce. -/// -/// For more information see [build]. -/// -/// Designed to be a sink. The [BuildOutput] is not intended to be read from. -/// [Builder]s stream outputs to the build output. For more info see [Builder]. -abstract final class BuildOutput { - /// Start time for the build of this output. - /// - /// The [timestamp] is rounded down to whole seconds, because - /// [File.lastModified] is rounded to whole seconds and caching logic compares - /// these timestamps. - DateTime get timestamp; - - /// The assets produced by this build. - /// - /// In dry runs, the assets for all [Architecture]s for the [OS] specified in - /// the dry run must be provided. - Iterable get encodedAssets; - - /// The assets produced by this build which should be linked. - /// - /// Every key in the map is a package name. These assets in the values are not - /// bundled with the application, but are sent to the link hook of the package - /// specified in the key, which can decide if they are bundled or not. - /// - /// In dry runs, the assets for all [Architecture]s for the [OS] specified in - /// the dry run must be provided. - Map> get encodedAssetsForLinking; - - /// The files used by this build. - /// - /// If any of the files in [dependencies] are modified after [timestamp], the - /// build will be re-run. - /// - /// The (transitive) Dart sources do not have to be added to these - /// dependencies, only non-Dart files. (Note that old Dart and Flutter SDKs - /// do not automatically add the Dart sources. So builds get wrongly cached, - /// try updating to the latest release.) - Iterable get dependencies; - - /// Create a build output. - /// - /// The [timestamp] must be before any [dependencies] are read by the build - /// this output belongs to. If the [BuildOutput] object is created at the - /// beginning of the build hook, [timestamp] can be omitted and will default - /// to [DateTime.now]. The [timestamp] is rounded down to whole seconds, - /// because [File.lastModified] is rounded to whole seconds and caching logic - /// compares these timestamps. - /// - /// The [EncodedAsset]s produced by this build or dry-run can be provided to - /// the constructor as [encodedAssets], or can be added later using - /// [addEncodedAsset] and [addEncodedAssets]. - /// - /// The files used by this build must be provided to the constructor as - /// [dependencies], or can be added later with [addDependency] and - /// [addDependencies]. If any of these files are modified after [timestamp], - /// the build will be re-run. Typically these dependencies contain the build - /// hook itself, and the source files used in the build. - /// - /// Metadata can be passed to build hook invocations of dependent packages. It - /// must be provided to the constructor as [metadata], or added later with - // ignore: deprecated_member_use_from_same_package - /// [addMetadatum] and [addMetadata]. - factory BuildOutput({ - DateTime? timestamp, - Iterable? encodedAssets, - Iterable? dependencies, - @Deprecated(metadataDeprecation) Map? metadata, - }) => - HookOutputImpl( - timestamp: timestamp, - encodedAssets: encodedAssets?.toList(), - dependencies: Dependencies([...?dependencies]), - metadata: Metadata({...?metadata}), - ); - - /// Adds [EncodedAsset]s produced by this build or dry run. - /// - /// If the [linkInPackage] argument is specified, the asset will not be - /// bundled during the build step, but sent as input to the link hook of the - /// specified package, where it can be further processed and possibly bundled. - /// - /// Note to hook writers. Prefer using the `.add` method on the extension for - /// the specific asset type being added: - /// - /// ```dart - /// main(List arguments) async { - /// await build((config, output) { - /// output.codeAssets.add(CodeAsset(...)); - /// output.dataAssets.add(DataAsset(...)); - /// }); - /// } - /// ``` - void addEncodedAsset(EncodedAsset asset, {String? linkInPackage}); - - /// Adds [EncodedAsset]s produced by this build or dry run. - /// - /// If the [linkInPackage] argument is specified, the assets will not be - /// bundled during the build step, but sent as input to the link hook of the - /// specified package, where they can be further processed and possibly - /// bundled. - /// - /// Note to hook writers. Prefer using the `.addAll` method on the extension - /// for the specific asset type being added: - /// - /// ```dart - /// main(List arguments) async { - /// await build((config, output) { - /// output.codeAssets.addAll([CodeAsset(...), ...]); - /// output.dataAssets.addAll([DataAsset(...), ...]); - /// }); - /// } - /// ``` - void addEncodedAssets(Iterable assets, {String? linkInPackage}); - - /// Adds file used by this build. - /// - /// If any of the files are modified after [timestamp], the build will be - /// re-run. - void addDependency(Uri dependency); - - /// Adds files used by this build. - /// - /// If any of the files are modified after [timestamp], the build will be - /// re-run. - void addDependencies(Iterable dependencies); - - /// Adds metadata to be passed to build hook invocations of dependent - /// packages. - @Deprecated(metadataDeprecation) - void addMetadatum(String key, Object value); - - /// Adds metadata to be passed to build hook invocations of dependent - /// packages. - @Deprecated(metadataDeprecation) - void addMetadata(Map metadata); - - /// The version of [BuildOutput]. - /// - /// The build output is used in the protocol between the Dart and Flutter SDKs - /// and packages through build hook invocations. - static Version get latestVersion => HookOutputImpl.latestVersion; -} diff --git a/pkgs/native_assets_cli/lib/src/api/builder.dart b/pkgs/native_assets_cli/lib/src/api/builder.dart index 99d21c716..40c543c4d 100644 --- a/pkgs/native_assets_cli/lib/src/api/builder.dart +++ b/pkgs/native_assets_cli/lib/src/api/builder.dart @@ -4,8 +4,7 @@ import 'package:logging/logging.dart'; -import 'build_config.dart'; -import 'build_output.dart'; +import '../config.dart'; import 'linker.dart'; /// A builder to be run during a build hook. @@ -48,22 +47,6 @@ import 'linker.dart'; /// }); /// } /// ``` -/// -/// The builder is designed to immediately operate on [BuildConfig]. If a -/// builder should deviate behavior from the build config, this should be -/// configurable through a constructor parameter. For example, if a native -/// compiler should output a static library to be sent to a linker, but the -/// [BuildConfig.linkModePreference] is set to dynamic linking, the builder -/// should have its own `linkModePreference` parameter in the constructor. -/// -/// The builder is designed to immediately operate on [BuildOutput]. If a -/// builder should output something else than standard, it should be -/// configurable through a constructor parameter. For example to send an asset -/// for linking to the output ([BuildOutput.addEncodedAsset] with -/// `linkInPackage` set), the builder should have a constructor parameter. -/// (Instead of capturing the BuildOutput as a return value and manually -/// manipulating it in the build hook.) This ensures that builder is in control -/// of what combination of build outputs are valid. abstract interface class Builder { /// Runs this build. /// @@ -71,7 +54,7 @@ abstract interface class Builder { /// logs to [logger]. Future run({ required BuildConfig config, - required BuildOutput output, + required BuildOutputBuilder output, required Logger? logger, }); } diff --git a/pkgs/native_assets_cli/lib/src/api/hook_config.dart b/pkgs/native_assets_cli/lib/src/api/hook_config.dart deleted file mode 100644 index f43e62e3a..000000000 --- a/pkgs/native_assets_cli/lib/src/api/hook_config.dart +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:convert'; -import 'dart:io'; - -import 'package:collection/collection.dart'; -import 'package:crypto/crypto.dart'; -import 'package:pub_semver/pub_semver.dart'; - -import '../architecture.dart'; -import '../build_mode.dart'; -import '../c_compiler_config.dart'; -import '../code_assets/code_asset.dart'; -import '../data_assets/data_asset.dart'; -import '../ios_sdk.dart'; -import '../json_utils.dart'; -import '../link_mode.dart'; -import '../link_mode_preference.dart'; -import '../model/hook.dart'; -import '../model/metadata.dart'; -import '../model/target.dart'; -import '../os.dart'; -import '../utils/map.dart'; -import 'build_config.dart'; -import 'link_config.dart'; - -part '../model/hook_config.dart'; - -/// The shared properties of a [LinkConfig] and a [BuildConfig]. -/// -/// This abstraction makes it easier to design APIs intended for both kinds of -/// build hooks, building and linking. -abstract class HookConfig { - /// The directory in which output and intermediate artifacts that are unique - /// to this configuration can be placed. - /// - /// This directory is unique per hook and per configuration. - /// - /// The contents of this directory will not be modified by anything else than - /// the hook itself. - /// - /// The invoker of the the hook will ensure concurrent invocations wait on - /// each other. - Uri get outputDirectory; - - /// The directory in which shared output and intermediate artifacts can be - /// placed. - /// - /// This directory is unique per hook. - /// - /// The contents of this directory will not be modified by anything else than - /// the hook itself. - /// - /// The invoker of the the hook will ensure concurrent invocations wait on - /// each other. - Uri get outputDirectoryShared; - - /// The name of the package the assets are built for. - String get packageName; - - /// The root of the package the assets are built for. - /// - /// Often a package's assets are built because a package is a dependency of - /// another. For this it is convenient to know the packageRoot. - Uri get packageRoot; - - /// The architecture being compiled for. - /// - /// Not specified (`null`) during a [dryRun]. - Architecture? get targetArchitecture; - - /// The operating system being compiled for. - OS get targetOS; - - /// When compiling for iOS, whether to target device or simulator. - /// - /// Only available if [targetOS] is [OS.iOS]. Will throw a [StateError] if - /// accessed otherwise. - /// - /// Not available during a [dryRun]. Will throw a [StateError] if accessed - /// during a [dryRun]. - IOSSdk? get targetIOSSdk; - - /// When compiling for iOS, the lowest iOS version that the compiled code - /// will be compatible with. - /// - /// Only available if [targetOS] is [OS.iOS]. Will throw a [StateError] if - /// accessed otherwise. - /// - /// Not available during a [dryRun]. Will throw a [StateError] if accessed - /// during a [dryRun]. - /// - /// Corresponds to `-mios-version-min=` for the Apple clang compiler. - int? get targetIOSVersion; - - /// When compiling for MacOS, the lowest MacOS version that the compiled code - /// will be compatible with. - /// - /// Only available if [targetOS] is [OS.macOS]. Will throw a [StateError] if - /// accessed otherwise. - /// - /// Not available during a [dryRun]. Will throw a [StateError] if accessed - /// during a [dryRun]. - /// - /// Corresponds to `-mmacosx-version-min=` for the Apple clang - /// compiler. - int? get targetMacOSVersion; - - /// When compiling for Android, the minimum Android SDK API version to that - /// the compiled code will be compatible with. - /// - /// Required when [targetOS] equals [OS.android]. - /// - /// Not available during a [dryRun]. Will throw a [StateError] if accessed - /// during a [dryRun]. - /// - /// For more information about the Android API version, refer to - /// [`minSdkVersion`](https://developer.android.com/ndk/guides/sdk-versions#minsdkversion) - /// in the Android documentation. - int? get targetAndroidNdkApi; - - /// The configuration for invoking the C compiler. - /// - /// Not available during a [dryRun]. Will throw a [StateError] if accessed - /// during a [dryRun]. - CCompilerConfig get cCompiler; - - /// Whether this run is a dry-run, which doesn't build anything. - /// - /// A dry-run only reports information about which assets a build would - /// create, but doesn't actually create files. - bool get dryRun; - - /// The [BuildMode] that the code should be compiled in. - /// - /// Currently [BuildMode.debug] and [BuildMode.release] are the only modes. - /// - /// Not available during a [dryRun]. Will throw a [StateError] if accessed - /// during a [dryRun]. - BuildMode get buildMode; - - /// The asset types that the invoker of this hook supports. - /// - /// Currently known values: - /// * [CodeAsset.type] - /// * [DataAsset.type] - Iterable get supportedAssetTypes; - - /// The preferred [LinkMode] method for [CodeAsset]s. - LinkModePreference get linkModePreference; -} diff --git a/pkgs/native_assets_cli/lib/src/api/link.dart b/pkgs/native_assets_cli/lib/src/api/link.dart index 98edb9e65..975ec280b 100644 --- a/pkgs/native_assets_cli/lib/src/api/link.dart +++ b/pkgs/native_assets_cli/lib/src/api/link.dart @@ -2,9 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:convert'; +import 'dart:io'; + +import '../args_parser.dart'; +import '../config.dart'; import '../validation.dart'; -import 'build_output.dart'; -import 'link_config.dart'; /// Runs a native assets link. /// @@ -29,15 +32,22 @@ import 'link_config.dart'; /// ``` Future link( List arguments, - Future Function(LinkConfig config, LinkOutput output) linker, + Future Function(LinkConfig config, LinkOutputBuilder output) linker, ) async { - final config = LinkConfig.fromArguments(arguments) as LinkConfigImpl; - - final output = HookOutputImpl(); + final configPath = getConfigArgument(arguments); + final bytes = File(configPath).readAsBytesSync(); + final jsonConfig = const Utf8Decoder() + .fuse(const JsonDecoder()) + .convert(bytes) as Map; + final config = LinkConfig(jsonConfig); + final output = LinkOutputBuilder(); await linker(config, output); - final errors = await validateLinkOutput(config, output); + final errors = await validateLinkOutput(config, LinkOutput(output.json)); if (errors.isEmpty) { - await output.writeToFile(config: config); + final jsonOutput = + const JsonEncoder().fuse(const Utf8Encoder()).convert(output.json); + await File.fromUri(config.outputDirectory.resolve('link_output.json')) + .writeAsBytes(jsonOutput); } else { final message = [ 'The output contained unsupported output:', diff --git a/pkgs/native_assets_cli/lib/src/api/link_config.dart b/pkgs/native_assets_cli/lib/src/api/link_config.dart deleted file mode 100644 index a029a460d..000000000 --- a/pkgs/native_assets_cli/lib/src/api/link_config.dart +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -import 'dart:convert'; -import 'dart:io'; - -import 'package:collection/collection.dart'; -import 'package:meta/meta.dart'; -import 'package:pub_semver/pub_semver.dart'; - -import '../architecture.dart'; -import '../args_parser.dart'; -import '../build_mode.dart'; -import '../c_compiler_config.dart'; -import '../encoded_asset.dart'; -import '../ios_sdk.dart'; -import '../json_utils.dart'; -import '../link_mode_preference.dart'; -import '../model/hook.dart'; -import '../os.dart'; -import '../utils/map.dart'; -import 'build_config.dart'; -import 'hook_config.dart'; - -part '../model/link_config.dart'; - -/// The configuration for a link hook (`hook/link.dart`) invocation. -/// -/// It consists of a subset of the fields from the [BuildConfig] already passed -/// to the build hook and the [encodedAssets] from the build step. -abstract class LinkConfig implements HookConfig { - /// The list of assets to be linked. These are the assets generated by a - /// `build.dart` script destined for this packages `link.dart`. - Iterable get encodedAssets; - - /// The path to the file containing recorded uses after kernel tree-shaking. - /// - /// The file contents can be parsed using `package:record_use`. - @experimental - Uri? get recordedUsagesFile; - - /// Generate the [LinkConfig] from the input arguments to the linking script. - factory LinkConfig.fromArguments(List arguments) => - LinkConfigImpl.fromArguments(arguments); - - factory LinkConfig.build({ - required Uri outputDirectory, - required Uri outputDirectoryShared, - required String packageName, - required Uri packageRoot, - Architecture? targetArchitecture, - required OS targetOS, - IOSSdk? targetIOSSdk, - int? targetIOSVersion, - int? targetMacOSVersion, - CCompilerConfig? cCompiler, - BuildMode? buildMode, - required Iterable supportedAssetTypes, - int? targetAndroidNdkApi, - required Iterable assets, - required LinkModePreference linkModePreference, - bool? dryRun, - Version? version, - }) => - LinkConfigImpl( - encodedAssets: assets, - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRoot, - buildMode: buildMode, - cCompiler: cCompiler, - targetAndroidNdkApi: targetAndroidNdkApi, - targetArchitecture: targetArchitecture, - targetIOSSdk: targetIOSSdk, - targetOS: targetOS, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - dryRun: dryRun, - linkModePreference: linkModePreference, - supportedAssetTypes: supportedAssetTypes, - version: version, - ); - - factory LinkConfig.dryRun({ - required Uri outputDirectory, - required Uri outputDirectoryShared, - required String packageName, - required Uri packageRoot, - required OS targetOS, - required Iterable supportedAssetTypes, - required Iterable assets, - required LinkModePreference linkModePreference, - Version? version, - }) => - LinkConfigImpl.dryRun( - encodedAssets: assets, - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRoot, - targetOS: targetOS, - supportedAssetTypes: supportedAssetTypes, - linkModePreference: linkModePreference, - version: version, - ); - - /// The version of [BuildConfig]. - /// - /// The build config is used in the protocol between the Dart and Flutter SDKs - /// and packages through build hook invocations. - /// - /// We're trying to avoid breaking changes. However, in the case that we have - /// to, the major version mismatch between the Dart or Flutter SDK and build - /// hook (`hook/build.dart`) will lead to a nice error message. - static Version get latestVersion => HookConfigImpl.latestVersion; -} diff --git a/pkgs/native_assets_cli/lib/src/api/link_output.dart b/pkgs/native_assets_cli/lib/src/api/link_output.dart deleted file mode 100644 index e90ace891..000000000 --- a/pkgs/native_assets_cli/lib/src/api/link_output.dart +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of 'build_output.dart'; - -/// The output of a link hook (`hook/link.dart`) invocation. -/// -/// A package can optionally provide link hook (`hook/link.dart`). If such a -/// hook exists, and any build hook outputs packages for linking with it, it -/// will be automatically run, by the Flutter and Dart SDK tools. The hook is -/// expect to produce a specific output which [LinkOutput] can produce. -/// -/// For more information see [link]. -/// -/// Designed to be a sink. The [LinkOutput] is not designed to be read from. -/// [Linker]s stream outputs to the link output. For more info see [Linker]. -abstract final class LinkOutput { - /// Start time for the link of this output. - /// - /// The [timestamp] is rounded down to whole seconds, because - /// [File.lastModified] is rounded to whole seconds and caching logic compares - /// these timestamps. - DateTime get timestamp; - - /// The assets produced by this link. - /// - /// In dry runs, the assets for all [Architecture]s for the [OS] specified in - /// the dry run must be provided. - Iterable get encodedAssets; - - /// The files used by this link. - /// - /// If any of the files in [dependencies] are modified after [timestamp], the - /// link will be re-run. - Iterable get dependencies; - - /// Adds file used by this link. - /// - /// If any of the files are modified after [timestamp], the link will be - /// re-run. - void addDependency(Uri dependency); - - /// Adds files used by this link. - /// - /// If any of the files are modified after [timestamp], the link will be - /// re-run. - void addDependencies(Iterable dependencies); - - /// Adds [EncodedAsset]s produced by this link or dry run. - void addEncodedAsset(EncodedAsset asset); - - /// Adds [EncodedAsset]s produced by this link or dry run. - void addEncodedAssets(Iterable assets); - - factory LinkOutput({ - Iterable? encodedAssets, - Dependencies? dependencies, - DateTime? timestamp, - }) => - HookOutputImpl( - encodedAssets: encodedAssets, - dependencies: dependencies, - timestamp: timestamp, - ); - - /// The version of [LinkOutput]. - /// - /// The link output is used in the protocol between the Dart and Flutter SDKs - /// and packages through build hook invocations. - static Version get latestVersion => HookOutputImpl.latestVersion; -} diff --git a/pkgs/native_assets_cli/lib/src/api/linker.dart b/pkgs/native_assets_cli/lib/src/api/linker.dart index 1bb080c45..a6e034cd0 100644 --- a/pkgs/native_assets_cli/lib/src/api/linker.dart +++ b/pkgs/native_assets_cli/lib/src/api/linker.dart @@ -4,9 +4,8 @@ import 'package:logging/logging.dart'; -import 'build_output.dart'; +import '../config.dart'; import 'builder.dart'; -import 'link_config.dart'; /// A linker to be run during a link hook. /// @@ -37,7 +36,7 @@ abstract interface class Linker { /// logs to [logger]. Future run({ required LinkConfig config, - required LinkOutput output, + required LinkOutputBuilder output, required Logger? logger, }); } diff --git a/pkgs/native_assets_cli/lib/src/api/test.dart b/pkgs/native_assets_cli/lib/src/api/test.dart deleted file mode 100644 index df1782c15..000000000 --- a/pkgs/native_assets_cli/lib/src/api/test.dart +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:meta/meta.dart' show isTest; -import 'package:test/test.dart'; -import 'package:yaml/yaml.dart'; - -import '../architecture.dart'; -import '../build_mode.dart'; -import '../c_compiler_config.dart'; -import '../code_assets/code_asset.dart'; -import '../data_assets/data_asset.dart'; -import '../ios_sdk.dart'; -import '../link_mode_preference.dart'; -import '../os.dart'; -import 'build_config.dart'; -import 'build_output.dart'; - -@isTest -Future testBuildHook({ - required String description, - // ignore: inference_failure_on_function_return_type - required Function(List arguments) mainMethod, - required void Function(BuildConfig config, BuildOutput output) check, - BuildMode? buildMode, - Architecture? targetArchitecture, - OS? targetOS, - IOSSdk? targetIOSSdk, - int? targetIOSVersion, - int? targetMacOSVersion, - int? targetAndroidNdkApi, - CCompilerConfig? cCompiler, - LinkModePreference? linkModePreference, - required Iterable supportedAssetTypes, - bool? linkingEnabled, -}) async { - test( - description, - () async { - final tempDir = await _tempDirForTest(); - - final outputDirectory = tempDir.resolve('output/'); - await Directory.fromUri(outputDirectory).create(); - final outputDirectoryShared = tempDir.resolve('output_shared/'); - await Directory.fromUri(outputDirectory).create(); - - final buildConfig = BuildConfig.build( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: await _packageName(), - packageRoot: Directory.current.uri, - buildMode: buildMode ?? BuildMode.release, - targetArchitecture: targetArchitecture ?? Architecture.current, - targetOS: targetOS ?? OS.current, - linkModePreference: linkModePreference ?? LinkModePreference.dynamic, - linkingEnabled: linkingEnabled ?? true, - cCompiler: cCompiler, - supportedAssetTypes: supportedAssetTypes, - targetAndroidNdkApi: targetAndroidNdkApi, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - ) as BuildConfigImpl; - final buildConfigUri = tempDir.resolve('build_config.json'); - - await _writeBuildConfig(buildConfigUri, buildConfig); - - await mainMethod(['--config=${buildConfigUri.toFilePath()}']); - - final hookOutput = await _readOutput(buildConfig) as BuildOutput; - - check(buildConfig, hookOutput); - - final allEncodedAssets = [ - ...hookOutput.encodedAssets, - ...hookOutput.encodedAssetsForLinking.values.expand((e) => e) - ]; - for (final asset in allEncodedAssets) { - expect(buildConfig.supportedAssetTypes, contains(asset.type)); - } - - for (final asset in hookOutput.dataAssets.all) { - final file = File.fromUri(asset.file); - expect(await file.exists(), true); - } - for (final asset in hookOutput.codeAssets.all) { - if (asset.file != null) { - final file = File.fromUri(asset.file!); - expect(await file.exists(), true); - } - } - }, - ); -} - -Future _writeBuildConfig( - Uri buildConfigUri, - BuildConfigImpl buildConfig, -) async { - final file = File.fromUri(buildConfigUri); - await file.create(); - file.writeAsStringSync(buildConfig.toJsonString()); -} - -Future _readOutput(BuildConfigImpl buildConfig) async { - final hookOutput = HookOutputImpl.fromJsonString( - await File.fromUri(buildConfig.outputFile).readAsString()); - return hookOutput; -} - -Future _packageName() async { - final uri = Directory.current.uri.resolve('pubspec.yaml'); - final readAsString = await File.fromUri(uri).readAsString(); - final yaml = loadYaml(readAsString) as YamlMap; - return yaml['name'] as String; -} - -const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES'; - -Future _tempDirForTest({String? prefix, bool keepTemp = false}) async { - final tempDir = await Directory.systemTemp.createTemp(prefix); - // Deal with Windows temp folder aliases. - final tempUri = - Directory(await tempDir.resolveSymbolicLinks()).uri.normalizePath(); - if ((!Platform.environment.containsKey(keepTempKey) || - Platform.environment[keepTempKey]!.isEmpty) && - !keepTemp) { - addTearDown(() => tempDir.delete(recursive: true)); - } - return tempUri; -} diff --git a/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart b/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart index 2a13e71ca..c07b91fb7 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart @@ -2,13 +2,14 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import '../api/build_config.dart'; -import '../api/build_output.dart'; -import '../api/link_config.dart'; import '../architecture.dart'; +import '../c_compiler_config.dart'; +import '../config.dart'; import '../encoded_asset.dart'; +import '../ios_sdk.dart'; import '../json_utils.dart'; import '../link_mode.dart'; +import '../link_mode_preference.dart'; import '../os.dart'; import '../utils/json.dart'; import '../utils/map.dart'; @@ -190,12 +191,17 @@ final class CodeAsset { static const String type = 'native_code'; } +/// Build config extension for code assets. +extension CodeAssetBuildConfig on BuildConfig { + CodeConfig get codeConfig => CodeConfig(this); +} + /// Build output extension for code assets. -extension CodeAssetsBuildOutput on BuildOutput { +extension CodeAssetsBuildOutput on BuildOutputBuilder { BuildOutputCodeAssets get codeAssets => BuildOutputCodeAssets(this); } -extension type BuildOutputCodeAssets(BuildOutput _output) { +extension type BuildOutputCodeAssets(BuildOutputBuilder _output) { void add(CodeAsset asset, {String? linkInPackage}) => _output.addEncodedAsset(asset.encode(), linkInPackage: linkInPackage); @@ -204,14 +210,11 @@ extension type BuildOutputCodeAssets(BuildOutput _output) { add(asset, linkInPackage: linkInPackage); } } - - Iterable get all => _output.encodedAssets - .where((e) => e.type == CodeAsset.type) - .map(CodeAsset.fromEncoded); } /// Link output extension for code assets. extension CodeAssetsLinkConfig on LinkConfig { + CodeConfig get codeConfig => CodeConfig(this); LinkConfigCodeAssets get codeAssets => LinkConfigCodeAssets(this); } @@ -229,18 +232,14 @@ extension type LinkConfigCodeAssets(LinkConfig _config) { } /// Link output extension for code assets. -extension CodeAssetsLinkOutput on LinkOutput { +extension CodeAssetsLinkOutput on LinkOutputBuilder { LinkOutputCodeAssets get codeAssets => LinkOutputCodeAssets(this); } -extension type LinkOutputCodeAssets(LinkOutput _output) { +extension type LinkOutputCodeAssets(LinkOutputBuilder _output) { void add(CodeAsset asset) => _output.addEncodedAsset(asset.encode()); void addAll(Iterable assets) => assets.forEach(add); - - Iterable get all => _output.encodedAssets - .where((e) => e.type == CodeAsset.type) - .map(CodeAsset.fromEncoded); } extension OSLibraryNaming on OS { @@ -275,6 +274,55 @@ extension OSLibraryNaming on OS { } } +class CodeConfig { + final Architecture? _targetArchitecture; + + final LinkModePreference linkModePreference; + final CCompilerConfig cCompiler; + final int? targetIOSVersion; + final int? targetMacOSVersion; + final int? targetAndroidNdkApi; + final IOSSdk? targetIOSSdk; + + CodeConfig(HookConfig config) + : linkModePreference = LinkModePreference.fromString( + config.json.string('link_mode_preference')), + _targetArchitecture = (config is BuildConfig && config.dryRun) + ? null + : Architecture.fromString( + config.json.string('target_architecture')), + cCompiler = (() { + final cCompiler = CCompilerConfig( + archiver: config.json.optionalPath('c_compiler.ar'), + compiler: config.json.optionalPath('c_compiler.cc'), + linker: config.json.optionalPath('c_compiler.ld'), + envScript: config.json.optionalPath('c_compiler.env_script'), + envScriptArgs: switch ( + config.json.optionalList('env_script_arguments')) { + final List l => [ + for (int i = 0; i < l.length; ++i) l.get(i) + ], + null => null, + }, + ); + return cCompiler; + })(), + targetIOSVersion = config.json.optionalInt('target_ios_version'), + targetMacOSVersion = config.json.optionalInt('target_macos_version'), + targetAndroidNdkApi = config.json.optionalInt('target_android_ndk_api'), + targetIOSSdk = switch (config.json.optionalString('target_ios_sdk')) { + final String value => IOSSdk.fromString(value), + null => null, + }; + + Architecture get targetArchitecture { + if (_targetArchitecture == null) { + throw StateError('Cannot access target architecture in dry runs'); + } + return _targetArchitecture; + } +} + /// The default name prefix for dynamic libraries per [OS]. const _dylibPrefix = { OS.android: 'lib', diff --git a/pkgs/native_assets_cli/lib/src/code_assets/code_asset_bundling.dart b/pkgs/native_assets_cli/lib/src/code_assets/code_asset_bundling.dart new file mode 100644 index 000000000..ce8bc7e87 --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/code_assets/code_asset_bundling.dart @@ -0,0 +1,77 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../architecture.dart'; +import '../c_compiler_config.dart'; +import '../config.dart'; +import '../ios_sdk.dart'; +import '../link_mode_preference.dart'; +import 'code_asset.dart'; + +// XXX TODO: Migrate to json decoding api. +extension CodeAssetBuildConfigBuilder on HookConfigBuilder { + void setupCodeConfig({ + required Architecture? targetArchitecture, + required LinkModePreference linkModePreference, + CCompilerConfig? cCompilerConfig, + int? targetIOSVersion, + int? targetMacOSVersion, + int? targetAndroidNdkApi, + IOSSdk? targetIOSSdk, + }) { + if (targetArchitecture != null) { + json['target_architecture'] = targetArchitecture.toString(); + } + json['link_mode_preference'] = linkModePreference.toString(); + if (cCompilerConfig != null) { + final ar = cCompilerConfig.archiver?.toFilePath(); + if (ar != null) { + json['c_compiler.ar'] = ar; + } + final cc = cCompilerConfig.compiler?.toFilePath(); + if (ar != null) { + json['c_compiler.cc'] = cc; + } + final ld = cCompilerConfig.linker?.toFilePath(); + if (ar != null) { + json['c_compiler.ld'] = ld; + } + final envScript = cCompilerConfig.envScript?.toFilePath(); + if (envScript != null) { + json['c_compiler.env_script'] = envScript; + } + final envScriptArgs = cCompilerConfig.envScriptArgs; + if (envScriptArgs != null && envScriptArgs.isNotEmpty) { + json['env_script_arguments'] = envScriptArgs; + } + } + + if (targetIOSVersion != null) { + json['target_ios_version'] = targetIOSVersion; + } + if (targetMacOSVersion != null) { + json['target_macos_version'] = targetMacOSVersion; + } + if (targetAndroidNdkApi != null) { + json['target_android_ndk_api'] = targetAndroidNdkApi; + } + if (targetIOSSdk != null) { + json['target_ios_sdk'] = targetIOSSdk.toString(); + } + } +} + +extension CodeAssetBuildOutput on BuildOutput { + List get codeAssets => encodedAssets + .where((asset) => asset.type == CodeAsset.type) + .map(CodeAsset.fromEncoded) + .toList(); +} + +extension CodeAssetLinkOutput on LinkOutput { + List get codeAssets => encodedAssets + .where((asset) => asset.type == CodeAsset.type) + .map(CodeAsset.fromEncoded) + .toList(); +} diff --git a/pkgs/native_assets_cli/lib/src/code_assets/validation.dart b/pkgs/native_assets_cli/lib/src/code_assets/validation.dart index 4910f2ed6..8c333d361 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/validation.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/validation.dart @@ -8,17 +8,18 @@ import '../../native_assets_cli_internal.dart'; import '../link_mode.dart'; Future validateCodeAssetBuildOutput( - HookConfig config, + BuildConfig config, BuildOutput output, ) => - _validateCodeAssetBuildOrLinkOutput(config, output as HookOutputImpl, true); + _validateCodeAssetBuildOrLinkOutput(config, config.codeConfig, + output.encodedAssets, config.dryRun, output, true); Future validateCodeAssetLinkOutput( - HookConfig config, + LinkConfig config, LinkOutput output, ) => _validateCodeAssetBuildOrLinkOutput( - config, output as HookOutputImpl, false); + config, config.codeConfig, output.encodedAssets, false, output, false); /// Validates that the given code assets can be used together in an application. /// @@ -40,18 +41,22 @@ Future validateCodeAssetsInApplication( Future _validateCodeAssetBuildOrLinkOutput( HookConfig config, - HookOutputImpl output, + CodeConfig codeConfig, + List encodedAssets, + bool dryRun, + HookOutput output, bool isBuild, ) async { final errors = []; final ids = {}; final fileNameToEncodedAssetId = >{}; - for (final asset in output.encodedAssets) { + for (final asset in encodedAssets) { if (asset.type != CodeAsset.type) continue; _validateCodeAssets( config, - config.dryRun, + codeConfig, + dryRun, CodeAsset.fromEncoded(asset), errors, ids, @@ -66,6 +71,7 @@ Future _validateCodeAssetBuildOrLinkOutput( void _validateCodeAssets( HookConfig config, + CodeConfig codeConfig, bool dryRun, CodeAsset codeAsset, List errors, @@ -81,7 +87,7 @@ void _validateCodeAssets( errors.add('More than one code asset with same "$id" id.'); } - final preference = config.linkModePreference; + final preference = codeConfig.linkModePreference; final linkMode = codeAsset.linkMode; if ((linkMode is DynamicLoading && preference == LinkModePreference.static) || (linkMode is StaticLinking && preference == LinkModePreference.dynamic)) { @@ -101,9 +107,9 @@ void _validateCodeAssets( if (!dryRun) { if (architecture == null) { errors.add('CodeAsset "$id" has no architecture.'); - } else if (architecture != config.targetArchitecture) { + } else if (architecture != codeConfig.targetArchitecture) { errors.add('CodeAsset "$id" has an architecture "$architecture", which ' - 'is not the target architecture "${config.targetArchitecture}".'); + 'is not the target architecture "${codeConfig.targetArchitecture}".'); } } diff --git a/pkgs/native_assets_cli/lib/src/config.dart b/pkgs/native_assets_cli/lib/src/config.dart new file mode 100644 index 000000000..904b36eac --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/config.dart @@ -0,0 +1,538 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert' hide json; +import 'dart:io'; + +import 'package:crypto/crypto.dart' show sha256; +import 'package:pub_semver/pub_semver.dart'; + +import 'api/deprecation_messages.dart'; +import 'architecture.dart'; +import 'build_mode.dart'; +import 'encoded_asset.dart'; +import 'json_utils.dart'; +import 'model/metadata.dart'; +import 'os.dart'; +import 'utils/datetime.dart'; +import 'utils/json.dart'; + +/// The shared properties of a [LinkConfig] and a [BuildConfig]. +/// +/// This abstraction makes it easier to design APIs intended for both kinds of +/// build hooks, building and linking. +sealed class HookConfig { + /// The underlying json configuration of this [HookConfig]. + final Map json; + + /// The version of the [HookConfig]. + final Version version; + + /// The directory in which output and intermediate artifacts that are unique + /// to this configuration can be placed. + /// + /// This directory is unique per hook and per configuration. + /// + /// The contents of this directory will not be modified by anything else than + /// the hook itself. + /// + /// The invoker of the the hook will ensure concurrent invocations wait on + /// each other. + final Uri outputDirectory; + + /// The directory in which shared output and intermediate artifacts can be + /// placed. + /// + /// This directory is unique per hook. + /// + /// The contents of this directory will not be modified by anything else than + /// the hook itself. + /// + /// The invoker of the the hook will ensure concurrent invocations wait on + /// each other. + final Uri outputDirectoryShared; + + /// The name of the package the assets are built for. + final String packageName; + + /// The root of the package the assets are built for. + /// + /// Often a package's assets are built because a package is a dependency of + /// another. For this it is convenient to know the packageRoot. + final Uri packageRoot; + + /// The operating system being compiled for. + final OS targetOS; + + /// The [BuildMode] that the code should be compiled in. + /// + /// Currently [BuildMode.debug] and [BuildMode.release] are the only modes. + /// + /// Not available during a dry run. + final BuildMode? _buildMode; + + /// The asset types that the invoker of this hook supports. + final List supportedAssetTypes; + + HookConfig(this.json) + : version = switch (Version.parse(json.string(_versionKey))) { + final Version version => (version.major != currentVersion.major || + version < currentVersion) + ? throw FormatException( + 'Only compatible versions with $currentVersion are supported ' + '(was: $version).') + : version, + }, + outputDirectory = json.path(_outDirConfigKey), + outputDirectoryShared = json.path(_outDirSharedConfigKey), + packageRoot = json.path(_packageRootConfigKey), + packageName = json.string(_packageNameConfigKey), + targetOS = OS.fromString(json.string(_targetOSConfigKey)), + supportedAssetTypes = + json.optionalStringList(_supportedAssetTypesKey) ?? const [], + _buildMode = switch (json.optionalString(_buildModeConfigKey)) { + String value => BuildMode.fromString(value), + null => null, + }; + + BuildMode get buildMode { + if (_buildMode == null) { + throw StateError('Build mode should not be accessed in dry-run mode.'); + } + return _buildMode; + } + + @override + String toString() => const JsonEncoder.withIndent(' ').convert(json); + + // The latest supported config version. + static Version currentVersion = Version(3, 5, 0); +} + +sealed class HookConfigBuilder { + final Map json = { + 'version': HookConfig.currentVersion.toString(), + }; + + void setupHookConfig({ + required Uri packageRoot, + required String packageName, + required OS targetOS, + required List supportedAssetTypes, + required BuildMode? buildMode, + }) { + json[_packageNameConfigKey] = packageName; + json[_packageRootConfigKey] = packageRoot.toFilePath(); + json[_targetOSConfigKey] = targetOS.toString(); + json[_supportedAssetTypesKey] = supportedAssetTypes; + if (buildMode != null) { + json[_buildModeConfigKey] = buildMode.toString(); + } + } + + /// Constructs a checksum for a [BuildConfig]. + /// + /// This can be used to construct an output directory name specific to the + /// [BuildConfig] being built with this [BuildConfigBuilder]. It is therefore + /// assumed the output directory has not been set yet. + String computeChecksum() { + if (json.containsKey(_outDirConfigKey) || + json.containsKey(_outDirSharedConfigKey)) { + // The bundling tools would first calculate the checksum, create an output + // directory and then call [BuildConfigBuilder.setupBuildRunConfig] & + // [LinkConfigBuilder.setupLinkRunConfig]. + throw StateError('The checksum should be generated before setting ' + 'up the run configuration'); + } + final hash = sha256 + .convert(const JsonEncoder().fuse(const Utf8Encoder()).convert(json)) + .toString() + // 256 bit hashes lead to 64 hex character strings. + // To avoid overflowing file paths limits, only use 32. + // Using 16 hex characters would also be unlikely to have collisions. + .substring(0, 32); + return hash; + } + //String computeChecksum() { + //final savedOutDir = json.remove(_outDirConfigKey); + //final savedSharedOutDir = json.remove(_outDirSharedConfigKey); + //final hash = sha256 + //.convert(const JsonEncoder().fuse(const Utf8Encoder()).convert(json)) + //.toString() + //// 256 bit hashes lead to 64 hex character strings. + //// To avoid overflowing file paths limits, only use 32. + //// Using 16 hex characters would also be unlikely to have collisions. + //.substring(0, 32); + //if (savedOutDir != null) json[_outDirConfigKey] = savedOutDir; + //if (savedSharedOutDir != null) { + //json[_outDirSharedConfigKey] = savedSharedOutDir; + //} + //return hash; + //} +} + +const _targetOSConfigKey = 'target_os'; +const _buildModeConfigKey = 'build_mode'; +const _metadataConfigKey = 'metadata'; +const _outDirConfigKey = 'out_dir'; +const _outDirSharedConfigKey = 'out_dir_shared'; +const _packageNameConfigKey = 'package_name'; +const _packageRootConfigKey = 'package_root'; +const _supportedAssetTypesKey = 'supported_asset_types'; + +final class BuildConfig extends HookConfig { + /// Whether this run is a dry-run, which doesn't build anything. + /// + /// A dry-run only reports information about which assets a build would + /// create, but doesn't actually create files. + final bool dryRun; + + final bool linkingEnabled; + + final Map metadata; + + BuildConfig(super.json) + : dryRun = json.getOptional(_dryRunConfigKey) ?? false, + linkingEnabled = json.get(_linkingEnabledKey), + metadata = { + for (final entry + in (json.optionalMap(_dependencyMetadataKey) ?? {}).entries) + entry.key: Metadata.fromJson(as>(entry.value)), + }; + + Object? metadatum(String packageName, String key) => + metadata[packageName]?.metadata[key]; +} + +final class BuildConfigBuilder extends HookConfigBuilder { + void setupBuildConfig({ + required bool dryRun, + required bool linkingEnabled, + Map? metadata, + }) { + json[_dryRunConfigKey] = dryRun; + json[_linkingEnabledKey] = linkingEnabled; + if (metadata != null) { + json[_dependencyMetadataKey] = { + for (final key in metadata.keys) key: metadata[key]!.toJson(), + }; + } + } + + void setupBuildRunConfig({ + required Uri outputDirectory, + required Uri outputDirectoryShared, + }) { + json[_outDirConfigKey] = outputDirectory.toFilePath(); + json[_outDirSharedConfigKey] = outputDirectoryShared.toFilePath(); + } +} + +const _dryRunConfigKey = 'dry_run'; +const _linkingEnabledKey = 'linking_enabled'; + +final class LinkConfig extends HookConfig { + final List encodedAssets; + + final Uri? recordedUsagesFile; + + LinkConfig(super.json) + : encodedAssets = + _parseAssets(json.getOptional>(_assetsKey)), + recordedUsagesFile = json.optionalPath(_recordedUsagesFileConfigKey); +} + +final class LinkConfigBuilder extends HookConfigBuilder { + void setupLinkConfig({ + required List assets, + }) { + json[_assetsKey] = [for (final asset in assets) asset.toJson()]; + } + + void setupLinkRunConfig({ + required Uri outputDirectory, + required Uri outputDirectoryShared, + required Uri? recordedUsesFile, + }) { + json[_outDirConfigKey] = outputDirectory.toFilePath(); + json[_outDirSharedConfigKey] = outputDirectoryShared.toFilePath(); + if (recordedUsesFile != null) { + json[_recordedUsagesFileConfigKey] = recordedUsesFile.toFilePath(); + } + } +} + +List _parseAssets(List? object) => object == null + ? [] + : [ + for (int i = 0; i < object.length; ++i) + EncodedAsset.fromJson(object.mapAt(i)), + ]; + +const _recordedUsagesFileConfigKey = 'resource_identifiers'; +const _assetsKey = 'assets'; +const _versionKey = 'version'; + +sealed class HookOutput { + /// The underlying json configuration of this [HookOutput]. + final Map json; + + /// The version of the [HookConfig]. + final Version version; + + /// Start time for the build of this output. + /// + /// The [timestamp] is rounded down to whole seconds, because + /// [File.lastModified] is rounded to whole seconds and caching logic compares + /// these timestamps. + final DateTime timestamp; + + /// The files used by this build. + /// + /// If any of the files in [dependencies] are modified after [timestamp], the + /// build will be re-run. + /// + /// The (transitive) Dart sources do not have to be added to these + /// dependencies, only non-Dart files. (Note that old Dart and Flutter SDKs + /// do not automatically add the Dart sources. So builds get wrongly cached, + /// try updating to the latest release.) + final List dependencies; + + HookOutput(this.json) + : version = switch (Version.parse(json.string(_versionKey))) { + final Version version => (version.major != latestVersion.major || + version < latestVersion) + ? throw FormatException( + 'Only compatible versions with $latestVersion are supported ' + '(was: $version).') + : version, + }, + timestamp = DateTime.parse(json.string(_timestampKey)), + dependencies = _parseDependencies(json.optionalList(_dependenciesKey)); + + @override + String toString() => const JsonEncoder.withIndent(' ').convert(json); + + /// The version of [HookOutput]. + static final Version latestVersion = Version(1, 5, 0); +} + +List _parseDependencies(List? list) { + if (list == null) return const []; + return [ + for (int i = 0; i < list.length; ++i) list.pathAt(i), + ]; +} + +const String _timestampKey = 'timestamp'; +const String _dependenciesKey = 'dependencies'; + +sealed class HookOutputBuilder { + final Map json = {}; + + HookOutputBuilder() { + json[_versionKey] = HookOutput.latestVersion.toString(); + json[_timestampKey] = DateTime.now().roundDownToSeconds().toString(); + } + + /// Adds file used by this build. + /// + /// If any of the files are modified after [BuildOutput.timestamp], the + // build will be re-run. + void addDependency(Uri uri) { + var dependencies = json[_dependenciesKey] as List?; + dependencies ??= json[_dependenciesKey] = []; + dependencies.add(uri.toFilePath()); + } + + /// Adds files used by this build. + /// + /// If any of the files are modified after [BuildOutput.timestamp], the + // build will be re-run. + void addDependencies(Iterable uris) { + var dependencies = json[_dependenciesKey] as List?; + dependencies ??= json[_dependenciesKey] = []; + dependencies.addAll(uris.map((uri) => uri.toFilePath())); + } +} + +class BuildOutput extends HookOutput { + /// The assets produced by this build. + /// + /// In dry runs, the assets for all [Architecture]s for the [OS] specified in + /// the dry run must be provided. + final List encodedAssets; + + /// The assets produced by this build which should be linked. + /// + /// Every key in the map is a package name. These assets in the values are not + /// bundled with the application, but are sent to the link hook of the package + /// specified in the key, which can decide if they are bundled or not. + /// + /// In dry runs, the assets for all [Architecture]s for the [OS] specified in + /// the dry run must be provided. + final Map> encodedAssetsForLinking; + + /// Metadata passed to dependent build hook invocations. + final Metadata metadata; + + /// Creates a [BuildOutput] from the given [json]. + BuildOutput(super.json) + : encodedAssets = _parseEncodedAssets(json.optionalList(_assetsKey)), + encodedAssetsForLinking = { + for (final MapEntry(:key, :value) + in (json.optionalMap(_assetsForLinkingKey) ?? {}).entries) + key: _parseEncodedAssets(value as List), + }, + metadata = + Metadata.fromJson(json.optionalMap(_metadataConfigKey) ?? {}); +} + +List _parseEncodedAssets(List? json) => json == null + ? const [] + : [ + for (int i = 0; i < json.length; ++i) + EncodedAsset.fromJson(json.mapAt(i)), + ]; + +const _assetsForLinkingKey = 'assetsForLinking'; +const _dependencyMetadataKey = 'dependency_metadata'; + +// XXX TODO +class BuildOutputBuilder extends HookOutputBuilder { + /// Adds metadata to be passed to build hook invocations of dependent + /// packages. + @Deprecated(metadataDeprecation) + void addMetadatum(String key, Object value) { + var map = json[_metadataConfigKey] as Map?; + map ??= json[_metadataConfigKey] = {}; + map[key] = value; + } + + /// Adds metadata to be passed to build hook invocations of dependent + /// packages. + @Deprecated(metadataDeprecation) + void addMetadata(Map metadata) { + var map = json[_metadataConfigKey] as Map?; + map ??= json[_metadataConfigKey] = {}; + map.addAll(metadata); + } + + /// Adds [EncodedAsset]s produced by this build or dry run. + /// + /// If the [linkInPackage] argument is specified, the asset will not be + /// bundled during the build step, but sent as input to the link hook of the + /// specified package, where it can be further processed and possibly bundled. + /// + /// Note to hook writers. Prefer using the `.add` method on the extension for + /// the specific asset type being added: + /// + /// ```dart + /// main(List arguments) async { + /// await build((config, output) { + /// output.codeAssets.add(CodeAsset(...)); + /// output.dataAssets.add(DataAsset(...)); + /// }); + /// } + /// ``` + void addEncodedAsset(EncodedAsset asset, {String? linkInPackage}) { + final list = _getEncodedAssetsList(json, linkInPackage); + list.add(asset.toJson()); + } + + /// Adds [EncodedAsset]s produced by this build or dry run. + /// + /// If the [linkInPackage] argument is specified, the assets will not be + /// bundled during the build step, but sent as input to the link hook of the + /// specified package, where they can be further processed and possibly + /// bundled. + /// + /// Note to hook writers. Prefer using the `.addAll` method on the extension + /// for the specific asset type being added: + /// + /// ```dart + /// main(List arguments) async { + /// await build((config, output) { + /// output.codeAssets.addAll([CodeAsset(...), ...]); + /// output.dataAssets.addAll([DataAsset(...), ...]); + /// }); + /// } + /// ``` + void addEncodedAssets(Iterable assets, + {String? linkInPackage}) { + final list = _getEncodedAssetsList(json, linkInPackage); + for (final asset in assets) { + list.add(asset.toJson()); + } + } +} + +List _getEncodedAssetsList( + Map json, String? linkInPackage) { + if (linkInPackage == null) { + var list = json[_assetsKey] as List?; + list ??= json[_assetsKey] = >[]; + return list; + } + var map = json[_assetsForLinkingKey] as Map?; + map ??= json[_assetsForLinkingKey] = {}; + + var list = map[linkInPackage] as List?; + list ??= map[linkInPackage] = >[]; + return list; +} + +class LinkOutput extends HookOutput { + /// The assets produced by this build. + /// + /// In dry runs, the assets for all [Architecture]s for the [OS] specified in + /// the dry run must be provided. + final List encodedAssets; + + /// Creates a [BuildOutput] from the given [json]. + LinkOutput(super.json) + : encodedAssets = _parseEncodedAssets(json.optionalList(_assetsKey)); +} + +class LinkOutputBuilder extends HookOutputBuilder { + /// Adds [EncodedAsset]s produced by this build. + /// + /// Note to hook writers. Prefer using the `.add` method on the extension for + /// the specific asset type being added: + /// + /// ```dart + /// main(List arguments) async { + /// await build((config, output) { + /// output.codeAssets.add(CodeAsset(...)); + /// output.dataAssets.add(DataAsset(...)); + /// }); + /// } + /// ``` + void addEncodedAsset(EncodedAsset asset) { + var list = json[_assetsKey] as List?; + list ??= json[_assetsKey] = >[]; + list.add(asset.toJson()); + } + + /// Adds [EncodedAsset]s produced by this build. + /// + /// Note to hook writers. Prefer using the `.addAll` method on the extension + /// for the specific asset type being added: + /// + /// ```dart + /// main(List arguments) async { + /// await build((config, output) { + /// output.codeAssets.addAll([CodeAsset(...), ...]); + /// output.dataAssets.addAll([DataAsset(...), ...]); + /// }); + /// } + /// ``` + void addEncodedAssets(Iterable assets) { + var list = json[_assetsKey] as List?; + list ??= json[_assetsKey] = >[]; + for (final asset in assets) { + list.add(asset.toJson()); + } + } +} diff --git a/pkgs/native_assets_cli/lib/src/data_assets/data_asset.dart b/pkgs/native_assets_cli/lib/src/data_assets/data_asset.dart index 9c79b0629..248e6715c 100644 --- a/pkgs/native_assets_cli/lib/src/data_assets/data_asset.dart +++ b/pkgs/native_assets_cli/lib/src/data_assets/data_asset.dart @@ -2,9 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import '../api/build_config.dart'; -import '../api/build_output.dart'; -import '../api/link_config.dart'; +import '../config.dart'; import '../encoded_asset.dart'; import '../json_utils.dart'; import '../utils/map.dart'; @@ -93,11 +91,11 @@ final class DataAsset { } /// Build output extension for data assets. -extension DataAssetsBuildOutput on BuildOutput { +extension DataAssetsBuildOutput on BuildOutputBuilder { BuildOutputDataAssets get dataAssets => BuildOutputDataAssets(this); } -extension type BuildOutputDataAssets(BuildOutput _output) { +extension type BuildOutputDataAssets(BuildOutputBuilder _output) { void add(DataAsset asset, {String? linkInPackage}) => _output.addEncodedAsset(asset.encode(), linkInPackage: linkInPackage); @@ -106,10 +104,6 @@ extension type BuildOutputDataAssets(BuildOutput _output) { add(asset, linkInPackage: linkInPackage); } } - - Iterable get all => _output.encodedAssets - .where((e) => e.type == DataAsset.type) - .map(DataAsset.fromEncoded); } /// Link output extension for data assets. @@ -131,18 +125,14 @@ extension type LinkConfigDataAssets(LinkConfig _config) { } /// Link output extension for data assets. -extension DataAssetsLinkOutput on LinkOutput { +extension DataAssetsLinkOutput on LinkOutputBuilder { LinkOutputDataAssets get dataAssets => LinkOutputDataAssets(this); } -extension type LinkOutputDataAssets(LinkOutput _output) { +extension type LinkOutputDataAssets(LinkOutputBuilder _output) { void add(DataAsset asset) => _output.addEncodedAsset(asset.encode()); void addAll(Iterable assets) => assets.forEach(add); - - Iterable get all => _output.encodedAssets - .where((e) => e.type == DataAsset.type) - .map(DataAsset.fromEncoded); } const _nameKey = 'name'; diff --git a/pkgs/native_assets_cli/lib/src/data_assets/data_asset_bundling.dart b/pkgs/native_assets_cli/lib/src/data_assets/data_asset_bundling.dart new file mode 100644 index 000000000..45a17b0fd --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/data_assets/data_asset_bundling.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../config.dart'; +import 'data_asset.dart'; + +extension DataAssetBuildOutput on BuildOutput { + List get dataAssets => encodedAssets + .where((asset) => asset.type == DataAsset.type) + .map(DataAsset.fromEncoded) + .toList(); +} + +extension DataAssetLinkOutput on LinkOutput { + List get dataAssets => encodedAssets + .where((asset) => asset.type == DataAsset.type) + .map(DataAsset.fromEncoded) + .toList(); +} diff --git a/pkgs/native_assets_cli/lib/src/data_assets/validation.dart b/pkgs/native_assets_cli/lib/src/data_assets/validation.dart index d6dd9de36..8504b11c9 100644 --- a/pkgs/native_assets_cli/lib/src/data_assets/validation.dart +++ b/pkgs/native_assets_cli/lib/src/data_assets/validation.dart @@ -7,30 +7,32 @@ import 'dart:io'; import '../../native_assets_cli_internal.dart'; Future validateDataAssetBuildOutput( - HookConfig config, + BuildConfig config, BuildOutput output, ) => - _validateDataAssetBuildOrLinkOutput(config, output as HookOutputImpl, true); + _validateDataAssetBuildOrLinkOutput( + config, output.encodedAssets, config.dryRun, true); Future validateDataAssetLinkOutput( - HookConfig config, + LinkConfig config, LinkOutput output, ) => _validateDataAssetBuildOrLinkOutput( - config, output as HookOutputImpl, false); + config, output.encodedAssets, false, false); Future _validateDataAssetBuildOrLinkOutput( HookConfig config, - HookOutputImpl output, + List encodedAssets, + bool dryRun, bool isBuild, ) async { final errors = []; final ids = {}; - for (final asset in output.encodedAssets) { + for (final asset in encodedAssets) { if (asset.type != DataAsset.type) continue; - _validateDataAssets(config, config.dryRun, DataAsset.fromEncoded(asset), - errors, ids, isBuild); + _validateDataAssets( + config, dryRun, DataAsset.fromEncoded(asset), errors, ids, isBuild); } return errors; } diff --git a/pkgs/native_assets_cli/lib/src/json_utils.dart b/pkgs/native_assets_cli/lib/src/json_utils.dart index 1680a1247..08864113a 100644 --- a/pkgs/native_assets_cli/lib/src/json_utils.dart +++ b/pkgs/native_assets_cli/lib/src/json_utils.dart @@ -82,6 +82,7 @@ extension ListJsonUtils on List { } Map mapAt(int index) => get>(index); + Uri pathAt(int index) => _fileSystemPathToUri(get(index)); } void _throwIfNotExists(String key, Uri value) { diff --git a/pkgs/native_assets_cli/lib/src/link_mode.dart b/pkgs/native_assets_cli/lib/src/link_mode.dart index bd02c1a7d..3b66c07dd 100644 --- a/pkgs/native_assets_cli/lib/src/link_mode.dart +++ b/pkgs/native_assets_cli/lib/src/link_mode.dart @@ -2,8 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'api/build_config.dart'; import 'code_assets/code_asset.dart'; +import 'config.dart'; /// The link mode for a [CodeAsset]. /// diff --git a/pkgs/native_assets_cli/lib/src/model/build_config.dart b/pkgs/native_assets_cli/lib/src/model/build_config.dart deleted file mode 100644 index 01b3ca7ce..000000000 --- a/pkgs/native_assets_cli/lib/src/model/build_config.dart +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of '../api/build_config.dart'; - -final class BuildConfigImpl extends HookConfigImpl implements BuildConfig { - @override - Hook get hook => Hook.build; - - @override - //TODO: Should be removed once migration to `hook/` is complete. - Uri get script { - final hookScript = packageRoot.resolve('hook/').resolve(hook.scriptName); - if (File.fromUri(hookScript).existsSync()) { - return hookScript; - } else { - return packageRoot.resolve(hook.scriptName); - } - } - - @override - String get outputName => 'build_output.json'; - - @override - Object? metadatum(String packageName, String key) { - HookConfigImpl.ensureNotDryRun(dryRun); - return _dependencyMetadata?[packageName]?.metadata[key]; - } - - final Map? _dependencyMetadata; - - @override - bool get linkingEnabled { - if (version == Version(1, 3, 0)) { - return true; - } - return _linkingEnabled as bool; - } - - final bool? _linkingEnabled; - - BuildConfigImpl({ - required super.outputDirectory, - required super.outputDirectoryShared, - required super.packageName, - required super.packageRoot, - Version? version, - super.buildMode, - super.cCompiler, - required super.supportedAssetTypes, - super.targetAndroidNdkApi, - required super.targetArchitecture, - super.targetIOSSdk, - super.targetIOSVersion, - super.targetMacOSVersion, - required super.targetOS, - required super.linkModePreference, - Map? dependencyMetadata, - required bool? linkingEnabled, - super.dryRun, - }) : _dependencyMetadata = dependencyMetadata, - _linkingEnabled = linkingEnabled, - super( - hook: Hook.build, - version: version ?? HookConfigImpl.latestVersion, - ) { - if (this.version < Version(1, 4, 0)) { - assert(linkingEnabled == null); - } else { - assert(linkingEnabled != null); - } - } - - BuildConfigImpl.dryRun({ - required super.outputDirectory, - required super.outputDirectoryShared, - required super.packageName, - required super.packageRoot, - required super.targetOS, - required super.linkModePreference, - required bool? linkingEnabled, - required super.supportedAssetTypes, - }) : _dependencyMetadata = null, - _linkingEnabled = linkingEnabled, - super.dryRun( - hook: Hook.build, - version: HookConfigImpl.latestVersion, - ); - - static BuildConfigImpl fromArguments( - List arguments, { - Map? environment, - Uri? workingDirectory, - }) { - final configPath = getConfigArgument(arguments); - final bytes = File(configPath).readAsBytesSync(); - final linkConfigJson = const Utf8Decoder() - .fuse(const JsonDecoder()) - .convert(bytes) as Map; - return fromJson(linkConfigJson); - } - - static const dependencyMetadataConfigKey = 'dependency_metadata'; - - static const linkingEnabledKey = 'linking_enabled'; - - static BuildConfigImpl fromJson(Map config) { - final dryRun = HookConfigImpl.parseDryRun(config) ?? false; - final targetOS = HookConfigImpl.parseTargetOS(config); - return BuildConfigImpl( - outputDirectory: HookConfigImpl.parseOutDir(config), - outputDirectoryShared: HookConfigImpl.parseOutDirShared(config), - packageName: HookConfigImpl.parsePackageName(config), - packageRoot: HookConfigImpl.parsePackageRoot(config), - buildMode: HookConfigImpl.parseBuildMode(config, dryRun), - targetOS: targetOS, - targetArchitecture: - HookConfigImpl.parseTargetArchitecture(config, dryRun, targetOS), - linkModePreference: HookConfigImpl.parseLinkModePreference(config), - dependencyMetadata: parseDependencyMetadata(config), - linkingEnabled: parseHasLinkPhase(config), - version: HookConfigImpl.parseVersion(config), - cCompiler: HookConfigImpl.parseCCompiler(config, dryRun), - supportedAssetTypes: - HookConfigImpl.parseSupportedEncodedAssetTypes(config), - targetAndroidNdkApi: - HookConfigImpl.parseTargetAndroidNdkApi(config, dryRun, targetOS), - targetIOSSdk: HookConfigImpl.parseTargetIOSSdk(config, dryRun, targetOS), - targetIOSVersion: - HookConfigImpl.parseTargetIosVersion(config, dryRun, targetOS), - targetMacOSVersion: - HookConfigImpl.parseTargetMacOSVersion(config, dryRun, targetOS), - dryRun: dryRun, - ); - } - - static Map? parseDependencyMetadata( - Map config) { - final fileValue = config.optionalMap(dependencyMetadataConfigKey); - if (fileValue == null) { - return null; - } - return fileValue - .map((key, defines) => MapEntry(as(key), defines)) - .map( - (packageName, defines) { - if (defines is! Map) { - throw FormatException("Unexpected value '$defines' for key " - "'$dependencyMetadataConfigKey.$packageName' in config file. " - 'Expected a Map.'); - } - return MapEntry( - packageName, - Metadata(defines - .map((key, value) => MapEntry(as(key), as(value))) - .sortOnKey()), - ); - }, - ).sortOnKey(); - } - - static bool? parseHasLinkPhase(Map config) => - config.optionalBool(linkingEnabledKey); - - @override - Map toJson() => { - ...hookToJson(), - if (!dryRun) ...{ - if (_dependencyMetadata != null && _dependencyMetadata.isNotEmpty) - dependencyMetadataConfigKey: _dependencyMetadata.map( - (packageName, metadata) => - MapEntry(packageName, metadata.toJson()), - ), - }, - if (version >= Version(1, 4, 0)) linkingEnabledKey: linkingEnabled, - }.sortOnKey(); - - @override - bool operator ==(Object other) { - if (super != other) { - return false; - } - if (other is! BuildConfigImpl) { - return false; - } - if (!dryRun && - !const DeepCollectionEquality() - .equals(other._dependencyMetadata, _dependencyMetadata)) { - return false; - } - if (_linkingEnabled != other._linkingEnabled) { - return false; - } - return true; - } - - @override - int get hashCode => Object.hashAll([ - super.hashCode, - linkModePreference, - linkingEnabled, - if (!dryRun) ...[ - const DeepCollectionEquality().hash(_dependencyMetadata), - ], - ]); - - @override - String toString() => 'BuildConfig(${toJson()})'; -} diff --git a/pkgs/native_assets_cli/lib/src/model/hook.dart b/pkgs/native_assets_cli/lib/src/model/hook.dart index a7f3d56f3..a53045c38 100644 --- a/pkgs/native_assets_cli/lib/src/model/hook.dart +++ b/pkgs/native_assets_cli/lib/src/model/hook.dart @@ -12,7 +12,12 @@ enum Hook { final String _scriptName; + const Hook(this._scriptName); + String get scriptName => '$_scriptName.dart'; - const Hook(this._scriptName); + String get outputName => switch (this) { + Hook.build => 'build_output.json', + Hook.link => 'link_output.json' + }; } diff --git a/pkgs/native_assets_cli/lib/src/model/hook_config.dart b/pkgs/native_assets_cli/lib/src/model/hook_config.dart deleted file mode 100644 index e209ab38c..000000000 --- a/pkgs/native_assets_cli/lib/src/model/hook_config.dart +++ /dev/null @@ -1,548 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of '../api/hook_config.dart'; - -abstract class HookConfigImpl implements HookConfig { - final Hook hook; - - @override - final Uri outputDirectory; - - @override - final Uri outputDirectoryShared; - - @override - final String packageName; - - @override - final Uri packageRoot; - - final Version version; - - final BuildMode? _buildMode; - - @override - BuildMode get buildMode { - ensureNotDryRun(dryRun); - return _buildMode!; - } - - final CCompilerConfig _cCompiler; - - @override - CCompilerConfig get cCompiler { - ensureNotDryRun(dryRun); - return _cCompiler; - } - - @override - final bool dryRun; - - @override - final Iterable supportedAssetTypes; - - final int? _targetAndroidNdkApi; - - @override - final LinkModePreference linkModePreference; - - @override - int? get targetAndroidNdkApi { - ensureNotDryRun(dryRun); - return _targetAndroidNdkApi; - } - - @override - final Architecture? targetArchitecture; - - final IOSSdk? _targetIOSSdk; - - @override - IOSSdk? get targetIOSSdk { - ensureNotDryRun(dryRun); - if (targetOS != OS.iOS) { - throw StateError( - 'This field is not available in if targetOS is not OS.iOS.', - ); - } - return _targetIOSSdk; - } - - final int? _targetIOSVersion; - - @override - int? get targetIOSVersion { - ensureNotDryRun(dryRun); - if (targetOS != OS.iOS) { - throw StateError( - 'This field is not available in if targetOS is not OS.iOS.', - ); - } - return _targetIOSVersion; - } - - final int? _targetMacOSVersion; - - @override - int? get targetMacOSVersion { - ensureNotDryRun(dryRun); - if (targetOS != OS.macOS) { - throw StateError( - 'This field is not available in if targetOS is not OS.macOS.', - ); - } - return _targetMacOSVersion; - } - - @override - final OS targetOS; - - /// Output file name based on the protocol version. - /// - /// Makes newer build hooks work with older Dart SDKs. - String get outputName; - - HookConfigImpl({ - required this.hook, - required this.outputDirectory, - required this.outputDirectoryShared, - required this.packageName, - required this.packageRoot, - required this.version, - required BuildMode? buildMode, - required CCompilerConfig? cCompiler, - required this.supportedAssetTypes, - required int? targetAndroidNdkApi, - required this.targetArchitecture, - required IOSSdk? targetIOSSdk, - required int? targetIOSVersion, - required int? targetMacOSVersion, - required this.linkModePreference, - required this.targetOS, - bool? dryRun, - }) : _targetAndroidNdkApi = targetAndroidNdkApi, - _targetIOSSdk = targetIOSSdk, - _targetIOSVersion = targetIOSVersion, - _targetMacOSVersion = targetMacOSVersion, - _buildMode = buildMode, - _cCompiler = cCompiler ?? CCompilerConfig(), - dryRun = dryRun ?? false; - - HookConfigImpl.dryRun({ - required this.hook, - required this.outputDirectory, - required this.outputDirectoryShared, - required this.packageName, - required this.packageRoot, - required this.version, - required this.supportedAssetTypes, - required this.linkModePreference, - required this.targetOS, - }) : _cCompiler = CCompilerConfig(), - dryRun = true, - targetArchitecture = null, - _buildMode = null, - _targetAndroidNdkApi = null, - _targetIOSSdk = null, - _targetIOSVersion = null, - _targetMacOSVersion = null; - - Uri get outputFile => outputDirectory.resolve(outputName); - - // This is currently overriden by [BuildConfig], do account for older versions - // still using a top-level build.dart. - Uri get script => packageRoot.resolve('hook/').resolve(hook.scriptName); - - String toJsonString() => const JsonEncoder.withIndent(' ').convert(toJson()); - - static const outDirConfigKey = 'out_dir'; - static const outDirSharedConfigKey = 'out_dir_shared'; - static const packageNameConfigKey = 'package_name'; - static const packageRootConfigKey = 'package_root'; - static const _versionKey = 'version'; - static const targetAndroidNdkApiConfigKey = 'target_android_ndk_api'; - static const targetIOSVersionConfigKey = 'target_ios_version'; - static const targetMacOSVersionConfigKey = 'target_macos_version'; - static const dryRunConfigKey = 'dry_run'; - static const supportedAssetTypesKey = 'supported_asset_types'; - - Map toJson(); - - Map hookToJson() { - late Map cCompilerJson; - if (!dryRun) { - cCompilerJson = cCompiler.toJson(); - } - - return { - outDirConfigKey: outputDirectory.toFilePath(), - outDirSharedConfigKey: outputDirectoryShared.toFilePath(), - packageNameConfigKey: packageName, - packageRootConfigKey: packageRoot.toFilePath(), - _targetOSConfigKey: targetOS.toString(), - supportedAssetTypesKey: supportedAssetTypes, - _versionKey: version.toString(), - if (dryRun) dryRunConfigKey: dryRun, - if (!dryRun) ...{ - _buildModeConfigKey: buildMode.toString(), - _targetArchitectureKey: targetArchitecture.toString(), - if (targetOS == OS.iOS && targetIOSSdk != null) - _targetIOSSdkConfigKey: targetIOSSdk.toString(), - if (targetOS == OS.iOS && targetIOSVersion != null) - targetIOSVersionConfigKey: targetIOSVersion!, - if (targetOS == OS.macOS && targetMacOSVersion != null) - targetMacOSVersionConfigKey: targetMacOSVersion!, - if (targetAndroidNdkApi != null) - targetAndroidNdkApiConfigKey: targetAndroidNdkApi!, - if (cCompilerJson.isNotEmpty) _compilerConfigKey: cCompilerJson, - }, - _linkModePreferenceConfigKey: linkModePreference.toString(), - }.sortOnKey(); - } - - static Version parseVersion(Map config) { - final version = Version.parse(config.string('version')); - if (version.major > latestVersion.major) { - throw FormatException( - 'The config version $version is newer than this ' - 'package:native_assets_cli config version $latestVersion, ' - 'please update native_assets_cli.', - ); - } - if (version.major < latestVersion.major) { - throw FormatException( - 'The config version $version is newer than this ' - 'package:native_assets_cli config version $latestVersion, ' - 'please update the Dart or Flutter SDK.', - ); - } - return version; - } - - static bool? parseDryRun(Map config) => - config.optionalBool(dryRunConfigKey); - - static Uri parseOutDir(Map config) => - config.path(outDirConfigKey, mustExist: true); - - static Uri parseOutDirShared(Map config) { - final configResult = - config.optionalPath(outDirSharedConfigKey, mustExist: true); - if (configResult != null) { - return configResult; - } - // Backwards compatibility, create a directory next to the output dir. - // This is will not be shared so caching doesn't work, but it will make - // the newer hooks not crash. - final outDir = config.path(outDirConfigKey); - final outDirShared = outDir.resolve('../out_shared/'); - Directory.fromUri(outDirShared).createSync(); - return outDirShared; - } - - static String parsePackageName(Map config) => - config.string(packageNameConfigKey); - - static Uri parsePackageRoot(Map config) => - config.path(packageRootConfigKey, mustExist: true); - - static BuildMode? parseBuildMode(Map config, bool dryRun) { - if (dryRun) { - _throwIfNotNullInDryRun(config, _buildModeConfigKey); - return null; - } else { - return BuildMode.fromString( - config.string( - _buildModeConfigKey, - validValues: BuildMode.values.map((e) => '$e'), - ), - ); - } - } - - static LinkModePreference parseLinkModePreference( - Map config) => - LinkModePreference.fromString( - config.string( - _linkModePreferenceConfigKey, - validValues: LinkModePreference.values.map((e) => '$e'), - ), - ); - - static OS parseTargetOS(Map config) => OS.fromString( - config.string( - _targetOSConfigKey, - validValues: OS.values.map((e) => '$e'), - ), - ); - - static Architecture? parseTargetArchitecture( - Map config, - bool dryRun, - OS? targetOS, - ) { - if (dryRun) { - _throwIfNotNullInDryRun(config, _targetArchitectureKey); - return null; - } else { - final validArchitectures = [ - if (targetOS == null) - ...Architecture.values - else - for (final target in Target.values) - if (target.os == targetOS) target.architecture - ]; - return Architecture.fromString( - config.string( - _targetArchitectureKey, - validValues: validArchitectures.map((e) => '$e'), - ), - ); - } - } - - static IOSSdk? parseTargetIOSSdk( - Map config, bool dryRun, OS? targetOS) { - if (dryRun) { - _throwIfNotNullInDryRun(config, _targetIOSSdkConfigKey); - return null; - } else { - return targetOS == OS.iOS - ? IOSSdk.fromString( - config.string( - _targetIOSSdkConfigKey, - validValues: IOSSdk.values.map((e) => '$e'), - ), - ) - : null; - } - } - - static int? parseTargetAndroidNdkApi( - Map config, - bool dryRun, - OS? targetOS, - ) { - if (dryRun) { - _throwIfNotNullInDryRun(config, targetAndroidNdkApiConfigKey); - return null; - } else { - return (targetOS == OS.android) - ? config.int(targetAndroidNdkApiConfigKey) - : null; - } - } - - static int? parseTargetIosVersion( - Map config, - bool dryRun, - OS? targetOS, - ) { - if (dryRun) { - _throwIfNotNullInDryRun(config, targetIOSVersionConfigKey); - return null; - } else { - return (targetOS == OS.iOS) - ? config.optionalInt(targetIOSVersionConfigKey) - : null; - } - } - - static int? parseTargetMacOSVersion( - Map config, - bool dryRun, - OS? targetOS, - ) { - if (dryRun) { - _throwIfNotNullInDryRun(config, targetMacOSVersionConfigKey); - return null; - } else { - return (targetOS == OS.macOS) - ? config.optionalInt(targetMacOSVersionConfigKey) - : null; - } - } - - static List parseSupportedEncodedAssetTypes( - Map config) => - config.optionalStringList(supportedAssetTypesKey) ?? []; - - static CCompilerConfig parseCCompiler( - Map config, bool dryRun) { - if (dryRun) { - _throwIfNotNullInDryRun(config, _compilerConfigKey); - } - - final cCompilerJson = - config.getOptional>(_compilerConfigKey); - if (cCompilerJson == null) return CCompilerConfig(); - - return CCompilerConfig.fromJson(cCompilerJson); - } - - static void _throwIfNotNullInDryRun( - Map config, String key) { - final object = config.getOptional(key); - if (object != null) { - throw const FormatException('''This field is not available in dry runs. -In Flutter projects, native builds are generated per OS which target multiple -architectures, build modes, etc. Therefore, the list of native assets produced -can _only_ depend on OS.'''); - } - } - - static void ensureNotDryRun(bool dryRun) { - if (dryRun) { - throw StateError('''This field is not available in dry runs. -In Flutter projects, native builds are generated per OS which target multiple -architectures, build modes, etc. Therefore, the list of native assets produced -can _only_ depend on OS.'''); - } - } - - @override - bool operator ==(Object other) { - if (other is! HookConfigImpl) { - return false; - } - if (other.outputDirectory != outputDirectory) return false; - if (other.outputDirectoryShared != outputDirectoryShared) return false; - if (other.packageName != packageName) return false; - if (other.packageRoot != packageRoot) return false; - if (other.dryRun != dryRun) return false; - if (other.targetOS != targetOS) return false; - if (other.linkModePreference != linkModePreference) return false; - if (!const DeepCollectionEquality() - .equals(other.supportedAssetTypes, supportedAssetTypes)) { - return false; - } - if (!dryRun) { - if (other.buildMode != buildMode) return false; - if (other.targetArchitecture != targetArchitecture) return false; - if (targetOS == OS.iOS && other.targetIOSSdk != targetIOSSdk) { - return false; - } - if (other.targetAndroidNdkApi != targetAndroidNdkApi) return false; - if (other.cCompiler != cCompiler) return false; - } - return true; - } - - @override - int get hashCode => Object.hashAll([ - outputDirectory, - outputDirectoryShared, - packageName, - packageRoot, - targetOS, - dryRun, - if (!dryRun) ...[ - buildMode, - targetArchitecture, - if (targetOS == OS.iOS) targetIOSSdk, - targetAndroidNdkApi, - cCompiler, - ], - ]); - - /// Constructs a checksum for a [BuildConfigImpl] based on the fields of a - /// buildconfig that influence the build. - /// - /// This can be used for an [outputDirectory], but should not be used for - /// dry-runs. - /// - /// In particular, it only takes the package name from [packageRoot], so that - /// the hash is equal across checkouts and ignores [outputDirectory] itself. - static String checksum({ - required String packageName, - required Uri packageRoot, - required Architecture targetArchitecture, - required OS targetOS, - required BuildMode buildMode, - IOSSdk? targetIOSSdk, - int? targetAndroidNdkApi, - CCompilerConfig? cCompiler, - required LinkModePreference linkModePreference, - Map? dependencyMetadata, - required Iterable supportedAssetTypes, - Version? version, - required Hook hook, - required bool? linkingEnabled, - }) { - final input = [ - version ?? latestVersion, - packageName, - targetArchitecture.toString(), - targetOS.toString(), - targetIOSSdk.toString(), - targetAndroidNdkApi.toString(), - buildMode.toString(), - linkModePreference.toString(), - cCompiler?.archiver.toString(), - cCompiler?.compiler.toString(), - cCompiler?.envScript.toString(), - cCompiler?.envScriptArgs.toString(), - cCompiler?.linker.toString(), - if (dependencyMetadata != null) - for (final entry in dependencyMetadata.entries) ...[ - entry.key, - json.encode(entry.value.toJson()), - ], - ...supportedAssetTypes, - hook.name, - linkingEnabled, - ].join('###'); - final sha256String = sha256.convert(utf8.encode(input)).toString(); - // 256 bit hashes lead to 64 hex character strings. - // To avoid overflowing file paths limits, only use 32. - // Using 16 hex characters would also be unlikely to have collisions. - const nameLength = 32; - return sha256String.substring(0, nameLength); - } - - static String checksumDryRun({ - required String packageName, - required Uri packageRoot, - required OS targetOS, - required LinkModePreference linkModePreference, - Version? version, - Iterable? supportedAssetTypes, - required Hook hook, - required bool? linkingEnabled, - }) { - final input = [ - version ?? latestVersion, - packageName, - targetOS.toString(), - linkModePreference.toString(), - ...supportedAssetTypes ?? [CodeAsset.type], - hook.name, - linkingEnabled, - ].join('###'); - final sha256String = sha256.convert(utf8.encode(input)).toString(); - // 256 bit hashes lead to 64 hex character strings. - // To avoid overflowing file paths limits, only use 32. - // Using 16 hex characters would also be unlikely to have collisions. - const nameLength = 32; - return sha256String.substring(0, nameLength); - } - - /// The version of [HookConfigImpl]. - /// - /// This class is used in the protocol between the Dart and Flutter SDKs - /// and packages through build hook invocations. - /// - /// If we ever were to make breaking changes, it would be useful to give - /// proper error messages rather than just fail to parse the JSON - /// representation in the protocol. - static Version latestVersion = Version(1, 5, 0); -} - -const String _compilerConfigKey = 'c_compiler'; -const String _buildModeConfigKey = 'build_mode'; -const String _targetOSConfigKey = 'target_os'; -const String _targetArchitectureKey = 'target_architecture'; -const String _targetIOSSdkConfigKey = 'target_ios_sdk'; -const String _linkModePreferenceConfigKey = 'link_mode_preference'; diff --git a/pkgs/native_assets_cli/lib/src/model/hook_output.dart b/pkgs/native_assets_cli/lib/src/model/hook_output.dart deleted file mode 100644 index 0d48d9fb7..000000000 --- a/pkgs/native_assets_cli/lib/src/model/hook_output.dart +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of '../api/build_output.dart'; - -final class HookOutputImpl implements BuildOutput, LinkOutput { - @override - final DateTime timestamp; - - final List _assets; - - @override - Iterable get encodedAssets => _assets; - - final Map> _assetsForLinking; - - @override - Map> get encodedAssetsForLinking => - _assetsForLinking; - - final Dependencies _dependencies; - - Dependencies get dependenciesModel => _dependencies; - - @override - Iterable get dependencies => _dependencies.dependencies; - - final Metadata metadata; - - HookOutputImpl({ - DateTime? timestamp, - Iterable? encodedAssets, - Map>? encodedAssetsForLinking, - Dependencies? dependencies, - Metadata? metadata, - }) : timestamp = (timestamp ?? DateTime.now()).roundDownToSeconds(), - _assets = [ - ...?encodedAssets, - ], - _assetsForLinking = encodedAssetsForLinking ?? {}, - // ignore: prefer_const_constructors - _dependencies = dependencies ?? Dependencies([]), - // ignore: prefer_const_constructors - metadata = metadata ?? Metadata({}); - - @override - void addDependency(Uri dependency) => - _dependencies.dependencies.add(dependency); - - @override - void addDependencies(Iterable dependencies) => - _dependencies.dependencies.addAll(dependencies); - - static const _assetsKey = 'assets'; - static const _assetsForLinkingKey = 'assetsForLinking'; - static const _dependenciesKey = 'dependencies'; - static const _metadataKey = 'metadata'; - static const _timestampKey = 'timestamp'; - static const _versionKey = 'version'; - - factory HookOutputImpl.fromJsonString(String jsonString) { - final Object? json = jsonDecode(jsonString); - return HookOutputImpl.fromJson(as>(json)); - } - - factory HookOutputImpl.fromJson(Map jsonMap) { - final outputVersion = Version.parse(get(jsonMap, 'version')); - if (outputVersion.major > latestVersion.major) { - throw FormatException( - 'The output version $outputVersion is newer than the ' - 'package:native_assets_cli config version $latestVersion in Dart or ' - 'Flutter, please update the Dart or Flutter SDK.', - ); - } - if (outputVersion.major < latestVersion.major) { - throw FormatException( - 'The output version $outputVersion is newer than this ' - 'package:native_assets_cli config version $latestVersion in Dart or ' - 'Flutter, please update native_assets_cli.', - ); - } - return HookOutputImpl( - timestamp: DateTime.parse(get(jsonMap, _timestampKey)), - encodedAssets: [ - for (final json in jsonMap.optionalList(_assetsKey) ?? []) - EncodedAsset.fromJson(json as Map), - ], - encodedAssetsForLinking: { - for (final MapEntry(:key, :value) - in (get?>(jsonMap, _assetsForLinkingKey) ?? {}) - .entries) - key: [ - for (final json in value as List) - EncodedAsset.fromJson(json as Map), - ], - }, - dependencies: - Dependencies.fromJson(get?>(jsonMap, _dependenciesKey)), - metadata: - Metadata.fromJson(get?>(jsonMap, _metadataKey)), - ); - } - - Map toJson(Version version) => { - _timestampKey: timestamp.toString(), - if (_assets.isNotEmpty) - _assetsKey: [ - for (final asset in encodedAssets) asset.toJson(), - ], - if (_assetsForLinking.isNotEmpty) - _assetsForLinkingKey: { - for (final MapEntry(:key, :value) - in encodedAssetsForLinking.entries) - key: [for (final asset in value) asset.toJson()], - }, - if (_dependencies.dependencies.isNotEmpty) - _dependenciesKey: _dependencies.toJson(), - if (metadata.metadata.isNotEmpty) _metadataKey: metadata.toJson(), - _versionKey: version.toString(), - }..sortOnKey(); - - String toJsonString(Version version) => - const JsonEncoder.withIndent(' ').convert(toJson(version)); - - /// The version of [HookOutputImpl]. - /// - /// This class is used in the protocol between the Dart and Flutter SDKs and - /// packages through build hook invocations. - /// - /// If we ever were to make breaking changes, it would be useful to give - /// proper error messages rather than just fail to parse the JSON - /// representation in the protocol. - /// - /// [BuildOutput.latestVersion] is tied to [BuildConfig.latestVersion]. This - /// enables making the JSON serialization in build hooks dependent on the - /// version of the Dart or Flutter SDK. When there is a need to split the - /// versions of BuildConfig and BuildOutput, the BuildConfig should start - /// passing the highest supported version of BuildOutput. - static Version latestVersion = HookConfigImpl.latestVersion; - - /// Reads the JSON file from [file]. - static HookOutputImpl? readFromFile({required Uri file}) { - final buildOutputFile = File.fromUri(file); - if (buildOutputFile.existsSync()) { - return HookOutputImpl.fromJsonString(buildOutputFile.readAsStringSync()); - } - - return null; - } - - /// Writes the [toJsonString] to the output file specified in the [config]. - Future writeToFile({required HookConfigImpl config}) async { - final configVersion = config.version; - final jsonString = toJsonString(configVersion); - await File.fromUri(config.outputFile) - .writeAsStringCreateDirectory(jsonString); - } - - @override - String toString() => toJsonString(HookConfigImpl.latestVersion); - - @override - bool operator ==(Object other) { - if (other is! HookOutputImpl) { - return false; - } - return other.timestamp == timestamp && - const ListEquality().equals(other._assets, _assets) && - other._dependencies == _dependencies && - other.metadata == metadata; - } - - @override - int get hashCode => Object.hash( - timestamp.hashCode, - const ListEquality().hash(_assets), - _dependencies, - metadata, - ); - - @override - void addMetadatum(String key, Object value) { - metadata.metadata[key] = value; - } - - @override - void addMetadata(Map metadata) { - this.metadata.metadata.addAll(metadata); - } - - Metadata get metadataModel => metadata; - - @override - void addEncodedAsset(EncodedAsset asset, {String? linkInPackage}) { - _getEncodedAssetList(linkInPackage).add(asset); - } - - @override - void addEncodedAssets(Iterable assets, - {String? linkInPackage}) { - _getEncodedAssetList(linkInPackage).addAll(assets.cast()); - } - - List _getEncodedAssetList(String? linkInPackage) => - linkInPackage == null - ? _assets - : (_assetsForLinking[linkInPackage] ??= []); - - HookOutputImpl copyWith({Iterable? encodedAssets}) => - HookOutputImpl( - timestamp: timestamp, - encodedAssets: encodedAssets?.toList() ?? _assets, - encodedAssetsForLinking: encodedAssetsForLinking, - dependencies: _dependencies, - metadata: metadata, - ); -} diff --git a/pkgs/native_assets_cli/lib/src/model/link_config.dart b/pkgs/native_assets_cli/lib/src/model/link_config.dart deleted file mode 100644 index 0f46876a7..000000000 --- a/pkgs/native_assets_cli/lib/src/model/link_config.dart +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of '../api/link_config.dart'; - -/// The input to the linking script. -/// -/// It consists of the fields inherited from the [HookConfig] and the -/// [encodedAssets] from the build step. -class LinkConfigImpl extends HookConfigImpl implements LinkConfig { - static const resourceIdentifierKey = 'resource_identifiers'; - - static const assetsKey = 'assets'; - - @override - final Iterable encodedAssets; - - // TODO: Placeholder for the resources.json file URL. We don't want to change - // native_assets_builder when implementing the parsing. - @override - final Uri? recordedUsagesFile; - - LinkConfigImpl({ - required this.encodedAssets, - this.recordedUsagesFile, - required super.outputDirectory, - required super.outputDirectoryShared, - required super.packageName, - required super.packageRoot, - Version? version, - required super.buildMode, - super.cCompiler, - required super.supportedAssetTypes, - super.targetAndroidNdkApi, - super.targetArchitecture, - super.targetIOSSdk, - super.targetIOSVersion, - super.targetMacOSVersion, - required super.targetOS, - required super.linkModePreference, - super.dryRun, - }) : super( - hook: Hook.link, - version: version ?? HookConfigImpl.latestVersion, - ); - - LinkConfigImpl.dryRun({ - required this.encodedAssets, - this.recordedUsagesFile, - required super.outputDirectory, - required super.outputDirectoryShared, - required super.packageName, - required super.packageRoot, - Version? version, - required super.supportedAssetTypes, - required super.linkModePreference, - required super.targetOS, - }) : super.dryRun( - hook: Hook.link, - version: version ?? HookConfigImpl.latestVersion, - ); - - @override - Hook get hook => Hook.link; - - @override - String get outputName => 'link_output.json'; - - @override - Map toJson() => { - ...hookToJson(), - if (recordedUsagesFile != null) - resourceIdentifierKey: recordedUsagesFile!.toFilePath(), - if (encodedAssets.isNotEmpty) - assetsKey: [ - for (final asset in encodedAssets) asset.toJson(), - ], - }.sortOnKey(); - - static LinkConfig fromArguments(List arguments) { - final configPath = getConfigArgument(arguments); - final bytes = File(configPath).readAsBytesSync(); - final linkConfigJson = const Utf8Decoder() - .fuse(const JsonDecoder()) - .convert(bytes) as Map; - return fromJson(linkConfigJson); - } - - static LinkConfigImpl fromJson(Map config) { - final dryRun = HookConfigImpl.parseDryRun(config) ?? false; - final targetOS = HookConfigImpl.parseTargetOS(config); - return LinkConfigImpl( - outputDirectory: HookConfigImpl.parseOutDir(config), - outputDirectoryShared: HookConfigImpl.parseOutDirShared(config), - packageName: HookConfigImpl.parsePackageName(config), - packageRoot: HookConfigImpl.parsePackageRoot(config), - buildMode: HookConfigImpl.parseBuildMode(config, dryRun), - targetOS: targetOS, - targetArchitecture: - HookConfigImpl.parseTargetArchitecture(config, dryRun, targetOS), - linkModePreference: HookConfigImpl.parseLinkModePreference(config), - version: HookConfigImpl.parseVersion(config), - cCompiler: HookConfigImpl.parseCCompiler(config, dryRun), - supportedAssetTypes: - HookConfigImpl.parseSupportedEncodedAssetTypes(config), - targetAndroidNdkApi: - HookConfigImpl.parseTargetAndroidNdkApi(config, dryRun, targetOS), - targetIOSSdk: HookConfigImpl.parseTargetIOSSdk(config, dryRun, targetOS), - targetIOSVersion: - HookConfigImpl.parseTargetIosVersion(config, dryRun, targetOS), - targetMacOSVersion: - HookConfigImpl.parseTargetMacOSVersion(config, dryRun, targetOS), - encodedAssets: [ - for (final json in config.optionalList(assetsKey) ?? []) - EncodedAsset.fromJson(json as Map), - ], - recordedUsagesFile: parseRecordedUsagesUri(config), - dryRun: dryRun, - ); - } - - static Uri? parseRecordedUsagesUri(Map config) => - config.optionalPath(resourceIdentifierKey); - - @override - bool operator ==(Object other) { - if (super != other) { - return false; - } - if (other is! LinkConfigImpl) { - return false; - } - if (other.recordedUsagesFile != recordedUsagesFile) { - return false; - } - if (!const DeepCollectionEquality() - .equals(other.encodedAssets, encodedAssets)) { - return false; - } - return true; - } - - @override - int get hashCode => Object.hashAll([ - super.hashCode, - recordedUsagesFile, - const DeepCollectionEquality().hash(encodedAssets), - ]); - - @override - String toString() => 'LinkConfig(${toJson()})'; -} diff --git a/pkgs/native_assets_cli/lib/test.dart b/pkgs/native_assets_cli/lib/test.dart index af750284a..ca2b329d2 100644 --- a/pkgs/native_assets_cli/lib/test.dart +++ b/pkgs/native_assets_cli/lib/test.dart @@ -1,5 +1,107 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -export 'src/api/test.dart' show testBuildHook; +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:meta/meta.dart' show isTest; +import 'package:test/test.dart'; +import 'package:yaml/yaml.dart'; + +import 'native_assets_cli_internal.dart'; + +export 'native_assets_cli_internal.dart'; +export 'src/code_assets/code_asset_bundling.dart'; + +@isTest +Future testBuildHook({ + required String description, + required void Function(BuildConfigBuilder) extraConfigSetup, + required FutureOr Function(List arguments) mainMethod, + required FutureOr Function(BuildConfig config, BuildOutput output) + check, + BuildMode? buildMode, + OS? targetOS, + List? supportedAssetTypes, + bool? linkingEnabled, +}) async { + test( + description, + () async { + final tempDir = await _tempDirForTest(); + final outputDirectory = tempDir.resolve('output/'); + final outputDirectoryShared = tempDir.resolve('output_shared/'); + + await Directory.fromUri(outputDirectory).create(); + await Directory.fromUri(outputDirectoryShared).create(); + + final configBuilder = BuildConfigBuilder(); + configBuilder + ..setupHookConfig( + packageRoot: Directory.current.uri, + packageName: _readPackageNameFromPubspec(), + targetOS: targetOS ?? OS.current, + supportedAssetTypes: supportedAssetTypes ?? [], + buildMode: buildMode ?? BuildMode.release, + ) + ..setupBuildConfig( + dryRun: false, + linkingEnabled: true, + ) + ..setupBuildRunConfig( + outputDirectory: outputDirectory, + outputDirectoryShared: outputDirectoryShared, + ); + extraConfigSetup(configBuilder); + + final config = BuildConfig(configBuilder.json); + + final configUri = tempDir.resolve(Hook.build.outputName); + _writeJsonTo(configUri, config.json); + await mainMethod(['--config=${configUri.toFilePath()}']); + final output = BuildOutput( + _readJsonFrom(config.outputDirectory.resolve(Hook.build.outputName))); + + // Test conformance of protocol invariants. + expect(await validateBuildOutput(config, output), isEmpty); + + // Run user-defined tests. + check(config, output); + }, + ); +} + +void _writeJsonTo(Uri uri, Map json) { + final encoder = const JsonEncoder().fuse(const Utf8Encoder()); + File.fromUri(uri).writeAsBytesSync(encoder.convert(json)); +} + +Map _readJsonFrom(Uri uri) { + final decoder = const Utf8Decoder().fuse(const JsonDecoder()); + final bytes = File.fromUri(uri).readAsBytesSync(); + return decoder.convert(bytes) as Map; +} + +String _readPackageNameFromPubspec() { + final uri = Directory.current.uri.resolve('pubspec.yaml'); + final readAsString = File.fromUri(uri).readAsStringSync(); + final yaml = loadYaml(readAsString) as YamlMap; + return yaml['name'] as String; +} + +const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES'; + +Future _tempDirForTest({String? prefix, bool keepTemp = false}) async { + final tempDir = await Directory.systemTemp.createTemp(prefix); + // Deal with Windows temp folder aliases. + final tempUri = + Directory(await tempDir.resolveSymbolicLinks()).uri.normalizePath(); + if ((!Platform.environment.containsKey(keepTempKey) || + Platform.environment[keepTempKey]!.isEmpty) && + !keepTemp) { + addTearDown(() => tempDir.delete(recursive: true)); + } + return tempUri; +} diff --git a/pkgs/native_assets_cli/test/api/build_config_test.dart b/pkgs/native_assets_cli/test/api/build_config_test.dart deleted file mode 100644 index 613c60dce..000000000 --- a/pkgs/native_assets_cli/test/api/build_config_test.dart +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. 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: deprecated_member_use_from_same_package - -import 'dart:io'; - -import 'package:native_assets_cli/native_assets_cli.dart'; -import 'package:native_assets_cli/src/api/build_config.dart'; -import 'package:test/test.dart'; - -void main() async { - late Uri tempUri; - late Uri outDirUri; - late Uri outDir2Uri; - late Uri outputDirectoryShared; - late Uri outputDirectoryShared2; - late String packageName; - late Uri packageRootUri; - late Uri fakeClang; - late Uri fakeLd; - late Uri fakeAr; - late Uri fakeCl; - late Uri fakeVcVars; - - setUp(() async { - tempUri = (await Directory.systemTemp.createTemp()).uri; - outDirUri = tempUri.resolve('out1/'); - await Directory.fromUri(outDirUri).create(); - outDir2Uri = tempUri.resolve('out2/'); - await Directory.fromUri(outDir2Uri).create(); - outputDirectoryShared = tempUri.resolve('out_shared1/'); - await Directory.fromUri(outputDirectoryShared).create(); - outputDirectoryShared2 = tempUri.resolve('out_shared2/'); - await Directory.fromUri(outputDirectoryShared2).create(); - packageName = 'my_package'; - packageRootUri = tempUri.resolve('$packageName/'); - await Directory.fromUri(packageRootUri).create(); - fakeClang = tempUri.resolve('fake_clang'); - await File.fromUri(fakeClang).create(); - fakeLd = tempUri.resolve('fake_ld'); - await File.fromUri(fakeLd).create(); - fakeAr = tempUri.resolve('fake_ar'); - await File.fromUri(fakeAr).create(); - fakeCl = tempUri.resolve('cl.exe'); - await File.fromUri(fakeCl).create(); - fakeVcVars = tempUri.resolve('vcvarsall.bat'); - await File.fromUri(fakeVcVars).create(); - }); - - tearDown(() async { - await Directory.fromUri(tempUri).delete(recursive: true); - }); - - test('BuildConfig ==', () { - final config1 = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - archiver: fakeAr, - ), - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - - final config2 = BuildConfig.build( - outputDirectory: outDir2Uri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - - expect(config1, equals(config1)); - expect(config1 == config2, false); - expect(config1.outputDirectory != config2.outputDirectory, true); - expect(config1.packageRoot, config2.packageRoot); - expect(config1.targetArchitecture == config2.targetArchitecture, true); - expect(config1.targetOS != config2.targetOS, true); - expect(config1.targetIOSSdk, IOSSdk.iPhoneOS); - expect(() => config2.targetIOSSdk, throwsStateError); - expect(config1.cCompiler.compiler != config2.cCompiler.compiler, true); - expect(config1.cCompiler.linker != config2.cCompiler.linker, true); - expect(config1.cCompiler.archiver != config2.cCompiler.archiver, true); - expect(config1.cCompiler.envScript == config2.cCompiler.envScript, true); - expect(config1.cCompiler.envScriptArgs == config2.cCompiler.envScriptArgs, - true); - expect(config1.cCompiler != config2.cCompiler, true); - expect(config1.linkModePreference, config2.linkModePreference); - expect(config1.supportedAssetTypes, config2.supportedAssetTypes); - expect(config1.linkingEnabled, config2.linkingEnabled); - }); - - test('BuildConfig fromConfig', () { - final buildConfig2 = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final config = { - 'build_mode': 'release', - 'supported_asset_types': [CodeAsset.type], - 'dry_run': false, - 'linking_enabled': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'arm64', - 'target_os': 'android', - 'version': BuildOutput.latestVersion.toString(), - }; - - final fromConfig = BuildConfigImpl.fromJson(config); - expect(fromConfig, equals(buildConfig2)); - }); - - test('BuildConfig.dryRun', () { - final buildConfig2 = BuildConfig.dryRun( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetOS: OS.android, - linkModePreference: LinkModePreference.preferStatic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: true, - ); - - final config = { - 'dry_run': true, - 'supported_asset_types': [CodeAsset.type], - 'linking_enabled': true, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_os': 'android', - 'version': BuildOutput.latestVersion.toString(), - }; - - final fromConfig = BuildConfigImpl.fromJson(config); - expect(fromConfig, equals(buildConfig2)); - }); - - test('BuildConfig == dependency metadata', () { - final buildConfig1 = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - dependencyMetadata: { - 'bar': { - 'key': 'value', - 'foo': ['asdf', 'fdsa'], - }, - 'foo': { - 'key': 321, - }, - }, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final buildConfig2 = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - dependencyMetadata: { - 'bar': { - 'key': 'value', - }, - 'foo': { - 'key': 123, - }, - }, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - expect(buildConfig1, equals(buildConfig1)); - expect(buildConfig1 == buildConfig2, false); - expect(buildConfig1.hashCode == buildConfig2.hashCode, false); - - expect(buildConfig1.metadatum('bar', 'key'), 'value'); - }); - - test('BuildConfig == hasLinkConfig', () { - final buildConfig1 = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.x64, - targetOS: OS.windows, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: true, - supportedAssetTypes: [CodeAsset.type], - ); - - final buildConfig2 = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.x64, - targetOS: OS.windows, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - expect(buildConfig1, equals(buildConfig1)); - expect(buildConfig1.hashCode, isNot(buildConfig2.hashCode)); - expect(buildConfig1, isNot(buildConfig2)); - }); - - test('BuildConfig fromArgs', () async { - final buildConfig = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - final configFileContents = (buildConfig as BuildConfigImpl).toJsonString(); - final configUri = tempUri.resolve('config.json'); - final configFile = File.fromUri(configUri); - await configFile.writeAsString(configFileContents); - final buildConfigFromArgs = BuildConfig( - ['--config', configUri.toFilePath()], - environment: {}, // Don't inherit the test environment. - ); - expect(buildConfigFromArgs, buildConfig); - }); - - test('BuildConfig.version', () { - BuildConfig.latestVersion.toString(); - }); -} diff --git a/pkgs/native_assets_cli/test/api/build_output_test.dart b/pkgs/native_assets_cli/test/api/build_output_test.dart deleted file mode 100644 index 9bd10f474..000000000 --- a/pkgs/native_assets_cli/test/api/build_output_test.dart +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:native_assets_cli/native_assets_cli.dart'; -import 'package:test/test.dart'; - -void main() { - late Uri tempUri; - - setUp(() async { - tempUri = (await Directory.systemTemp.createTemp()).uri; - }); - - tearDown(() async { - await Directory.fromUri(tempUri).delete(recursive: true); - }); - - test('BuildOutput constructor', () { - BuildOutput( - timestamp: DateTime.parse('2022-11-10 13:25:01.000'), - encodedAssets: [ - CodeAsset( - package: 'my_package', - name: 'foo', - file: Uri(path: 'path/to/libfoo.so'), - linkMode: DynamicLoadingBundled(), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - CodeAsset( - package: 'my_package', - name: 'foo2', - linkMode: DynamicLoadingSystem(Uri(path: 'path/to/libfoo2.so')), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - ], - dependencies: [ - Uri.file('path/to/file.ext'), - ], - // ignore: deprecated_member_use_from_same_package - metadata: { - 'key': 'value', - }, - ); - }); -} diff --git a/pkgs/native_assets_cli/test/api/build_test.dart b/pkgs/native_assets_cli/test/api/build_test.dart index baae8eba6..1e9e73fb0 100644 --- a/pkgs/native_assets_cli/test/api/build_test.dart +++ b/pkgs/native_assets_cli/test/api/build_test.dart @@ -2,11 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:convert'; import 'dart:io'; import 'package:file_testing/file_testing.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; -import 'package:native_assets_cli/src/api/build_config.dart'; +import 'package:native_assets_cli/native_assets_cli.dart' show build; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:test/test.dart'; void main() async { @@ -15,53 +16,38 @@ void main() async { late Uri outputDirectoryShared; late String packageName; late Uri packageRootUri; - late Uri fakeClang; - late Uri fakeLd; - late Uri fakeAr; - late Uri fakeCl; - late Uri fakeVcVars; late Uri buildConfigUri; - late BuildConfig config1; + late BuildConfig config; setUp(() async { tempUri = (await Directory.systemTemp.createTemp()).uri; outDirUri = tempUri.resolve('out1/'); await Directory.fromUri(outDirUri).create(); outputDirectoryShared = tempUri.resolve('out_shared1/'); - await Directory.fromUri(outputDirectoryShared).create(); packageName = 'my_package'; packageRootUri = tempUri.resolve('$packageName/'); await Directory.fromUri(packageRootUri).create(); - fakeClang = tempUri.resolve('fake_clang'); - await File.fromUri(fakeClang).create(); - fakeLd = tempUri.resolve('fake_ld'); - await File.fromUri(fakeLd).create(); - fakeAr = tempUri.resolve('fake_ar'); - await File.fromUri(fakeAr).create(); - fakeCl = tempUri.resolve('cl.exe'); - await File.fromUri(fakeCl).create(); - fakeVcVars = tempUri.resolve('vcvarsall.bat'); - await File.fromUri(fakeVcVars).create(); - config1 = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - archiver: fakeAr, - ), - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferDynamic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - final configJson = (config1 as BuildConfigImpl).toJsonString(); + final configBuilder = BuildConfigBuilder(); + configBuilder + ..setupHookConfig( + packageRoot: tempUri, + packageName: packageName, + targetOS: OS.iOS, + supportedAssetTypes: [CodeAsset.type], + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + dryRun: false, + linkingEnabled: false, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + ); + config = BuildConfig(configBuilder.json); + + final configJson = json.encode(config.json); buildConfigUri = tempUri.resolve('build_config.json'); await File.fromUri(buildConfigUri).writeAsString(configJson); }); @@ -72,7 +58,7 @@ void main() async { output.addDependency(packageRootUri.resolve('foo')); }); final buildOutputUri = - outDirUri.resolve((config1 as BuildConfigImpl).outputName); + config.outputDirectory.resolve(Hook.build.outputName); expect(File.fromUri(buildOutputUri), exists); }); } diff --git a/pkgs/native_assets_cli/test/api/link_config_test.dart b/pkgs/native_assets_cli/test/api/link_config_test.dart deleted file mode 100644 index bd739b65b..000000000 --- a/pkgs/native_assets_cli/test/api/link_config_test.dart +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:native_assets_cli/native_assets_cli.dart'; -import 'package:native_assets_cli/src/api/link_config.dart'; -import 'package:test/test.dart'; - -void main() async { - late Uri tempUri; - late Uri outDirUri; - late Uri outDir2Uri; - late Uri outputDirectoryShared; - late String packageName; - late Uri packageRootUri; - late Uri fakeClang; - late Uri fakeLd; - late Uri fakeAr; - late Uri fakeCl; - late Uri fakeVcVars; - - setUp(() async { - tempUri = (await Directory.systemTemp.createTemp()).uri; - outDirUri = tempUri.resolve('out1/'); - await Directory.fromUri(outDirUri).create(); - outDir2Uri = tempUri.resolve('out2/'); - await Directory.fromUri(outDir2Uri).create(); - outputDirectoryShared = tempUri.resolve('out_shared1/'); - await Directory.fromUri(outputDirectoryShared).create(); - packageName = 'my_package'; - packageRootUri = tempUri.resolve('$packageName/'); - await Directory.fromUri(packageRootUri).create(); - fakeClang = tempUri.resolve('fake_clang'); - await File.fromUri(fakeClang).create(); - fakeLd = tempUri.resolve('fake_ld'); - await File.fromUri(fakeLd).create(); - fakeAr = tempUri.resolve('fake_ar'); - await File.fromUri(fakeAr).create(); - fakeCl = tempUri.resolve('cl.exe'); - await File.fromUri(fakeCl).create(); - fakeVcVars = tempUri.resolve('vcvarsall.bat'); - await File.fromUri(fakeVcVars).create(); - }); - - tearDown(() async { - await Directory.fromUri(tempUri).delete(recursive: true); - }); - - test('LinkConfig ==', () { - final config1 = LinkConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - archiver: fakeAr, - ), - buildMode: BuildMode.release, - supportedAssetTypes: [CodeAsset.type], - assets: [], - linkModePreference: LinkModePreference.preferStatic, - ); - - final config2 = LinkConfig.build( - outputDirectory: outDir2Uri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - supportedAssetTypes: [CodeAsset.type], - assets: [], - linkModePreference: LinkModePreference.preferStatic, - ); - - expect(config1, equals(config1)); - expect(config1 == config2, false); - expect(config1.outputDirectory != config2.outputDirectory, true); - expect(config1.packageRoot, config2.packageRoot); - expect(config1.targetArchitecture == config2.targetArchitecture, true); - expect(config1.targetOS != config2.targetOS, true); - expect(config1.targetIOSSdk, IOSSdk.iPhoneOS); - expect(() => config2.targetIOSSdk, throwsStateError); - expect(config1.cCompiler.compiler != config2.cCompiler.compiler, true); - expect(config1.cCompiler.linker != config2.cCompiler.linker, true); - expect(config1.cCompiler.archiver != config2.cCompiler.archiver, true); - expect(config1.cCompiler.envScript == config2.cCompiler.envScript, true); - expect(config1.cCompiler.envScriptArgs == config2.cCompiler.envScriptArgs, - true); - expect(config1.cCompiler != config2.cCompiler, true); - expect(config1.supportedAssetTypes, config2.supportedAssetTypes); - }); - - test('LinkConfig fromConfig', () { - final linkConfig2 = LinkConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - assets: [], - linkModePreference: LinkModePreference.preferStatic, - supportedAssetTypes: [CodeAsset.type], - ); - - final config = { - 'build_mode': 'release', - 'dry_run': false, - 'supported_asset_types': [CodeAsset.type], - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'arm64', - 'target_os': 'android', - 'version': BuildOutput.latestVersion.toString(), - 'assets': [], - }; - - final fromConfig = LinkConfigImpl.fromJson(config); - expect(fromConfig, equals(linkConfig2)); - }); - - test('LinkConfig.dryRun', () { - final linkConfig2 = LinkConfig.dryRun( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetOS: OS.android, - supportedAssetTypes: [CodeAsset.type], - assets: [], - linkModePreference: LinkModePreference.preferStatic, - ); - - final config = { - 'dry_run': true, - 'supported_asset_types': [CodeAsset.type], - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_os': 'android', - 'version': BuildOutput.latestVersion.toString(), - 'assets': [], - }; - - final fromConfig = LinkConfigImpl.fromJson(config); - expect(fromConfig, equals(linkConfig2)); - }); - - test('LinkConfig fromArgs', () async { - final linkConfig = LinkConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - assets: [], - linkModePreference: LinkModePreference.preferStatic, - supportedAssetTypes: [CodeAsset.type], - ); - final configFileContents = (linkConfig as LinkConfigImpl).toJsonString(); - final configUri = tempUri.resolve('config.json'); - final configFile = File.fromUri(configUri); - await configFile.writeAsString(configFileContents); - final linkConfigFromArgs = - LinkConfig.fromArguments(['--config', configUri.toFilePath()]); - expect(linkConfigFromArgs, linkConfig); - }); - - test('LinkConfig.version', () { - LinkConfig.latestVersion.toString(); - }); -} diff --git a/pkgs/native_assets_cli/test/build_config_test.dart b/pkgs/native_assets_cli/test/build_config_test.dart new file mode 100644 index 000000000..85ebf0e6b --- /dev/null +++ b/pkgs/native_assets_cli/test/build_config_test.dart @@ -0,0 +1,321 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. 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: deprecated_member_use_from_same_package + +import 'dart:convert'; +import 'dart:io'; + +import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:test/test.dart'; + +//XXX TODO +//test('envScript', () { +//final buildConfig1 = BuildConfigImpl( +//outputDirectory: outDirUri, +//outputDirectoryShared: outputDirectoryShared, +//packageName: packageName, +//packageRoot: packageRootUri, +//targetArchitecture: Architecture.x64, +//targetOS: OS.windows, +//cCompiler: CCompilerConfig( +//compiler: fakeCl, +//envScript: fakeVcVars, +//envScriptArgs: ['x64'], +//), +//buildMode: BuildMode.release, +//linkModePreference: LinkModePreference.dynamic, +//linkingEnabled: false, +//supportedAssetTypes: [CodeAsset.type], +//); + +//final configFile = buildConfig1.toJson(); +//final fromConfig = BuildConfigImpl.fromJson(configFile); +//expect(fromConfig, equals(buildConfig1)); +//}); + +void main() async { + late Uri outDirUri; + late Uri outputDirectoryShared; + late String packageName; + late Uri packageRootUri; + late Uri fakeClang; + late Uri fakeLd; + late Uri fakeAr; + late Map metadata; + + setUp(() async { + final tempUri = Directory.systemTemp.uri; + outDirUri = tempUri.resolve('out1/'); + outputDirectoryShared = tempUri.resolve('out_shared1/'); + packageName = 'my_package'; + packageRootUri = tempUri.resolve('$packageName/'); + fakeClang = tempUri.resolve('fake_clang'); + fakeLd = tempUri.resolve('fake_ld'); + fakeAr = tempUri.resolve('fake_ar'); + metadata = { + 'bar': const Metadata({ + 'key': 'value', + 'foo': ['asdf', 'fdsa'], + }), + 'foo': const Metadata({ + 'key': 321, + }), + }; + }); + + test('BuildConfigBuilder->JSON->BuildConfig', () { + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: packageRootUri, + targetOS: OS.android, + buildMode: BuildMode.release, + supportedAssetTypes: [CodeAsset.type], + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + metadata: metadata, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + targetAndroidNdkApi: 30, + linkModePreference: LinkModePreference.preferStatic, + cCompilerConfig: CCompilerConfig( + compiler: fakeClang, + linker: fakeLd, + archiver: fakeAr, + ), + ); + final config = BuildConfig(configBuilder.json); + + final expectedConfigJson = { + 'build_mode': 'release', + 'supported_asset_types': [CodeAsset.type], + 'dry_run': false, + 'linking_enabled': false, + 'link_mode_preference': 'prefer-static', + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_android_ndk_api': 30, + 'target_architecture': 'arm64', + 'target_os': 'android', + 'version': HookConfig.currentVersion.toString(), + 'c_compiler.ar': fakeAr.toFilePath(), + 'c_compiler.ld': fakeLd.toFilePath(), + 'c_compiler.cc': fakeClang.toFilePath(), + 'dependency_metadata': { + 'bar': { + 'key': 'value', + 'foo': ['asdf', 'fdsa'], + }, + 'foo': { + 'key': 321, + }, + }, + }; + + expect(config.json, expectedConfigJson); + expect(json.decode(config.toString()), expectedConfigJson); + + expect(config.outputDirectory, outDirUri); + expect(config.outputDirectoryShared, outputDirectoryShared); + + expect(config.packageName, packageName); + expect(config.packageRoot, packageRootUri); + expect(config.targetOS, OS.android); + expect(config.buildMode, BuildMode.release); + expect(config.supportedAssetTypes, [CodeAsset.type]); + + expect(config.linkingEnabled, false); + expect(config.dryRun, false); + expect(config.metadata, metadata); + + final codeConfig = config.codeConfig; + expect(codeConfig.targetArchitecture, Architecture.arm64); + expect(codeConfig.targetAndroidNdkApi, 30); + expect(codeConfig.linkModePreference, LinkModePreference.preferStatic); + expect(codeConfig.cCompiler.compiler, fakeClang); + expect(codeConfig.cCompiler.linker, fakeLd); + expect(codeConfig.cCompiler.archiver, fakeAr); + }); + + test('BuildConfig.dryRun', () { + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: packageRootUri, + targetOS: OS.android, + buildMode: null, // not available in dry run + supportedAssetTypes: [CodeAsset.type], + ) + ..setupBuildConfig( + linkingEnabled: true, + dryRun: true, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + ) + ..setupCodeConfig( + targetArchitecture: null, // not available in dry run + cCompilerConfig: null, // not available in dry run + linkModePreference: LinkModePreference.preferStatic, + ); + final config = BuildConfig(configBuilder.json); + + final expectedConfigJson = { + 'dry_run': true, + 'supported_asset_types': [CodeAsset.type], + 'linking_enabled': true, + 'link_mode_preference': 'prefer-static', + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_os': 'android', + 'version': HookConfig.currentVersion.toString(), + }; + + expect(config.json, expectedConfigJson); + expect(json.decode(config.toString()), expectedConfigJson); + + expect(config.outputDirectory, outDirUri); + expect(config.outputDirectoryShared, outputDirectoryShared); + + expect(config.packageName, packageName); + expect(config.packageRoot, packageRootUri); + expect(config.targetOS, OS.android); + expect(config.supportedAssetTypes, [CodeAsset.type]); + expect(() => config.buildMode, throwsStateError); + + expect(config.linkingEnabled, true); + expect(config.dryRun, true); + expect(config.metadata, {}); + + final codeConfig = config.codeConfig; + expect(() => codeConfig.targetArchitecture, throwsStateError); + expect(codeConfig.targetAndroidNdkApi, null); + expect(codeConfig.linkModePreference, LinkModePreference.preferStatic); + expect(codeConfig.cCompiler.compiler, null); + expect(codeConfig.cCompiler.linker, null); + expect(codeConfig.cCompiler.archiver, null); + }); + + group('BuildConfig format issues', () { + for (final version in ['9001.0.0', '0.0.1']) { + test('BuildConfig version $version', () { + final outDir = outDirUri; + final config = { + 'link_mode_preference': 'prefer-static', + 'out_dir': outDir.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_root': packageRootUri.toFilePath(), + 'target_os': 'linux', + 'version': version, + 'package_name': packageName, + 'supported_asset_types': [CodeAsset.type], + 'dry_run': true, + 'linking_enabled': false, + }; + expect( + () => BuildConfig(config), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains(version) && + e.message.contains(HookConfig.currentVersion.toString()), + )), + ); + }); + } + + test('BuildConfig FormatExceptions', () { + expect( + () => BuildConfig({}), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains( + 'No value was provided for required key: ', + ), + )), + ); + expect( + () => BuildConfig({ + 'version': HookConfig.currentVersion.toString(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_architecture': 'arm64', + 'target_os': 'android', + 'target_android_ndk_api': 30, + 'link_mode_preference': 'prefer-static', + 'linking_enabled': true, + 'supported_asset_types': [CodeAsset.type], + }), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains( + 'No value was provided for required key: out_dir', + ), + )), + ); + expect( + () => BuildConfig({ + 'version': HookConfig.currentVersion.toString(), + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_architecture': 'arm64', + 'target_os': 'android', + 'target_android_ndk_api': 30, + 'link_mode_preference': 'prefer-static', + 'linking_enabled': true, + 'build_mode': BuildMode.release.name, + 'supported_asset_types': [CodeAsset.type], + 'dependency_metadata': { + 'bar': {'key': 'value'}, + 'foo': [], + }, + }), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains("Unexpected value '[]' ") && + e.message.contains('Expected a Map'), + )), + ); + }); + + test('invalid architecture', () { + final config = { + 'build_mode': 'release', + 'dry_run': false, + 'link_mode_preference': 'prefer-static', + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_android_ndk_api': 30, + 'target_architecture': 'invalid_architecture', + 'target_os': 'android', + 'supported_asset_types': [CodeAsset.type], + 'version': HookConfig.currentVersion.toString(), + }; + expect( + () => BuildConfig(config), + throwsFormatException, + ); + }); + }); +} diff --git a/pkgs/native_assets_cli/test/build_output_test.dart b/pkgs/native_assets_cli/test/build_output_test.dart new file mode 100644 index 000000000..e1af613f4 --- /dev/null +++ b/pkgs/native_assets_cli/test/build_output_test.dart @@ -0,0 +1,92 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. 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: deprecated_member_use_from_same_package + +import 'dart:convert'; + +import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/src/utils/datetime.dart'; +import 'package:test/test.dart'; + +void main() { + test('BuildOutputBuilder->JSON->BuildOutput', () { + final assets = [ + for (int i = 0; i < 6; i++) + DataAsset(file: Uri(path: 'asset$i'), name: 'assetId$i', package: 'pkg') + .encode(), + ]; + final uris = [ + for (int i = 0; i < 3; ++i) Uri.file('path$i'), + ]; + final metadata0 = { + 'meta-a': 'meta-b', + }; + final metadata1 = { + for (int i = 0; i < 2; ++i) 'meta$i': 'meta$i-value', + }; + final before = DateTime.now().roundDownToSeconds(); + final builder = BuildOutputBuilder(); + final after = DateTime.now().roundDownToSeconds(); + + builder.addDependency(uris.take(1).single); + builder.addDependencies(uris.skip(1).toList()); + builder.addMetadatum(metadata0.keys.single, metadata0.values.single); + builder.addMetadata(metadata1); + + builder.addEncodedAsset(assets.take(1).single); + builder.addEncodedAsset(assets.skip(1).first, + linkInPackage: 'package:linker1'); + builder.addEncodedAssets(assets.skip(2).take(2).toList()); + builder.addEncodedAssets(assets.skip(4).toList(), + linkInPackage: 'package:linker2'); + + final config = BuildOutput(builder.json); + expect(config.timestamp, greaterThanOrEqualTo(before)); + expect(config.timestamp, lessThanOrEqualTo(after)); + expect(config.timestamp, + lessThanOrEqualTo(config.timestamp.roundDownToSeconds())); + + print(const JsonEncoder.withIndent(' ').convert(config.json)); + + final expectedJson = { + 'version': '1.5.0', + 'timestamp': config.timestamp.toString(), + 'dependencies': [ + ...uris.map((uri) => uri.toFilePath()), + ], + 'metadata': { + ...metadata0, + ...metadata1, + }, + 'assets': [ + assets.take(1).single.toJson(), + ...assets.skip(2).take(2).map((e) => e.toJson()), + ], + 'assetsForLinking': { + 'package:linker1': [ + assets.skip(1).first.toJson(), + ], + 'package:linker2': [ + ...assets.skip(4).map((e) => e.toJson()), + ] + } + }; + expect(config.json, equals(expectedJson)); + }); + + for (final version in ['9001.0.0', '0.0.1']) { + test('BuildOutput version $version', () { + expect( + () => BuildOutput({'version': version}), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains(version) && + e.message.contains(HookOutput.latestVersion.toString()), + )), + ); + }); + } +} diff --git a/pkgs/native_assets_cli/test/checksum_test.dart b/pkgs/native_assets_cli/test/checksum_test.dart new file mode 100644 index 000000000..246066ade --- /dev/null +++ b/pkgs/native_assets_cli/test/checksum_test.dart @@ -0,0 +1,107 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. 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_internal.dart'; +import 'package:test/test.dart'; + +void main() { + test('checksum', () async { + // metadata, cc, link vs build, metadata, haslink + final checksums = []; + for (final os in [OS.linux, OS.macOS]) { + for (final buildMode in [BuildMode.release, BuildMode.debug]) { + for (final packageName in ['foo', 'bar']) { + for (final assetType in [CodeAsset.type, DataAsset.type]) { + for (final dryRun in [true, false]) { + for (final linking in [true, false]) { + final builder = BuildConfigBuilder() + ..setupHookConfig( + packageRoot: Uri.file('foo'), + packageName: packageName, + targetOS: os, + supportedAssetTypes: [assetType], + buildMode: buildMode, + ) + ..setupBuildConfig(dryRun: dryRun, linkingEnabled: linking); + checksums.add(builder.computeChecksum()); + } + } + } + } + } + } + // As all variants have something different, we expect the checksums to be + // unique. + expect(checksums.toSet().length, checksums.length); + + // If format or algorithm for checksumming changes we'd like to know (by + // needing to update this list). + expect(checksums, [ + '49daf3450cda2d6f703fd1c5615723e1', + '5b071ecc8b32a1dd7ae71cec893da765', + '42e0e9ef9b52243b2a033708c5614692', + '779e7bd31c6671c69c15bffe20b9b882', + 'e1684c0558449dc47dd6e95eed9c8f20', + '42264730ed1bac426fd9b0de85ca355a', + 'fae528a60605783f326c1e61af02a943', + '375be74dab1457c8ba637444654a4a3a', + '390e8e89b417572229bf7f2c02883a3c', + 'd2931555f8c5f3610b45012f63fafae4', + '423dc47a44ce262b6d1d30fd159752fe', + '1616bd24aa7745c19272cb7776c740d8', + '1dfafc3008d703fb5670cae22955e7f0', + '27c8a7891663bdea5791f0a4a0b00f0a', + '33628656d5ba5acff5ba6d672e6266e9', + '6a99fa1285cdbdf07e7f2f16dd9c124f', + '6d6fca403370aa7ea4ae309eb3e19272', + '09aadc73a263858f3b0724c3ca1c886a', + '920c1e3d286c746065652bfd2d740698', + 'cbf2c911f9d3e5b0d644b402d8feebd3', + 'ac36f6d4b530ddbd77d7c9fd93514bfc', + 'a77d9a81e1f66c43ba16743263516fc1', + '7619ec268bb1c4da8116db2605bd2ab8', + '3eaa505790a10afc93b4402799c735d2', + 'c9378ada5a069e0ea1f4906e6e981092', + '2915954b795f02d688269214b3db0cf7', + 'c6c895b2c738ff19eba67044f0dbbbd0', + '953a29fc8f4015a57fb44749dd576837', + '4c6c58417ab2e732e9b2952fedacce68', + '9cfb486089a705226ee8a138d14f7fd7', + '8a9fc2ebf5cc1fa39cd03179a5959fad', + 'b956d47a5613b89e09f00763fc7b30b6', + 'fe690851eb75c9566fbf2060f8b37df9', + 'f29ec64febd078bd188041ccb7d545f7', + '3f54f0ceca274275c71c4fa2ca3ef919', + '9896e8326e43a114ca1fa833a00f0e80', + '8f5c3abb4578159f37a3f585a4e52b62', + 'fd2e5b9cd4ccbe35a7b515f49b44a6f4', + '90d3dfc0dab4617da8b3b261c6d42ed6', + '4491024a82b1ae5545b3bb90f37c47bd', + '491e8c4549b80de2de7366f75deb6fb7', + 'bf8ce548a070836411efc4ffab36f00d', + '5562ecf90c8ea05f8cff98099a16c6bd', + '451b5c9be02a42cb5cf6359355241f6a', + '3b39694a45d1c427dbf24229ad88f969', + 'd4527aec8dc183f1f61819a414fe3a52', + '95ea9db54a39dfc3d7eecbf120b93ee0', + '2ac0ee9854562c6274749fdcc1fb3609', + 'd1ef410112e3f3ed8a98e1dc7e64f653', + '5e05ca0cd3496beebe8f3a3c5dec2e3c', + '3e2febea1b3c111eed26c9a5a6b90ef3', + '969f85ffb945e52278b0b55b895f12a1', + 'd00132dd4a88b01e4071e8b1e1d6cf28', + '5d940c16b18065eb2579a48d12a9cdd0', + '144cbd4cd41f6bf3a3bee7b0776cff40', + '793cd15349782e52b009a5337301c2b9', + '676def9232cfb0ad832311cf6c29defb', + '7010c8c6d8124e35b1c9ad643f219ffd', + 'd0b705242470e18b6caf62dc1765e70f', + 'e0874bd58e0a72f341406fef23979bd0', + '4174d81f0fa117071a58abc5886cce45', + '6221a8463b3978352a1cc6f0b0945f0a', + '154c04f511463b7f73033559561ca88d', + '66fc47c7320a7af96716f17c80b0eb3f', + ]); + }); +} diff --git a/pkgs/native_assets_cli/test/example/local_asset_test.dart b/pkgs/native_assets_cli/test/example/local_asset_test.dart index 31f15c0a8..629aa3c4c 100644 --- a/pkgs/native_assets_cli/test/example/local_asset_test.dart +++ b/pkgs/native_assets_cli/test/example/local_asset_test.dart @@ -40,25 +40,25 @@ void main() async { final testPackageUri = packageUri.resolve('example/build/$name/'); final dartUri = Uri.file(Platform.resolvedExecutable); - final config = BuildConfigImpl( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: name, - packageRoot: testPackageUri, - targetOS: OS.current, - version: HookConfigImpl.latestVersion, - linkModePreference: LinkModePreference.dynamic, - dryRun: dryRun, - linkingEnabled: false, - targetArchitecture: dryRun ? null : Architecture.current, - buildMode: dryRun ? null : BuildMode.debug, - cCompiler: dryRun ? null : cCompiler, - supportedAssetTypes: [CodeAsset.type], - ); + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageRoot: testPackageUri, + packageName: name, + targetOS: OS.current, + supportedAssetTypes: [CodeAsset.type], + buildMode: dryRun ? null : BuildMode.debug) + ..setupBuildRunConfig( + outputDirectory: outputDirectory, + outputDirectoryShared: outputDirectoryShared) + ..setupBuildConfig(linkingEnabled: false, dryRun: dryRun) + ..setupCodeConfig( + targetArchitecture: dryRun ? null : Architecture.current, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: dryRun ? null : cCompiler); final buildConfigUri = testTempUri.resolve('build_config.json'); await File.fromUri(buildConfigUri) - .writeAsString(jsonEncode(config.toJson())); + .writeAsString(jsonEncode(configBuilder.json)); final processResult = await Process.run( dartUri.toFilePath(), @@ -76,12 +76,13 @@ void main() async { expect(processResult.exitCode, 0); final buildOutputUri = outputDirectory.resolve('build_output.json'); - final buildOutput = HookOutputImpl.fromJsonString( - await File.fromUri(buildOutputUri).readAsString()) as BuildOutput; + final buildOutput = BuildOutput( + json.decode(await File.fromUri(buildOutputUri).readAsString()) + as Map); final assets = buildOutput.encodedAssets; final dependencies = buildOutput.dependencies; if (dryRun) { - final codeAsset = buildOutput.codeAssets.all.first; + final codeAsset = buildOutput.codeAssets.first; expect(assets.length, greaterThanOrEqualTo(1)); expect(await File.fromUri(codeAsset.file!).exists(), false); expect(dependencies, []); diff --git a/pkgs/native_assets_cli/test/example/native_add_library_test.dart b/pkgs/native_assets_cli/test/example/native_add_library_test.dart index 5c82eca99..3d0d2f9c7 100644 --- a/pkgs/native_assets_cli/test/example/native_add_library_test.dart +++ b/pkgs/native_assets_cli/test/example/native_add_library_test.dart @@ -40,25 +40,25 @@ void main() async { final testPackageUri = packageUri.resolve('example/build/$name/'); final dartUri = Uri.file(Platform.resolvedExecutable); - final config = BuildConfigImpl( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: name, - packageRoot: testPackageUri, - targetOS: OS.current, - version: HookConfigImpl.latestVersion, - linkModePreference: LinkModePreference.dynamic, - dryRun: dryRun, - linkingEnabled: false, - targetArchitecture: dryRun ? null : Architecture.current, - buildMode: dryRun ? null : BuildMode.debug, - cCompiler: dryRun ? null : cCompiler, - supportedAssetTypes: [CodeAsset.type], - ); + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageRoot: testPackageUri, + packageName: name, + targetOS: OS.current, + supportedAssetTypes: [CodeAsset.type], + buildMode: dryRun ? null : BuildMode.debug) + ..setupBuildRunConfig( + outputDirectory: outputDirectory, + outputDirectoryShared: outputDirectoryShared) + ..setupBuildConfig(linkingEnabled: false, dryRun: dryRun) + ..setupCodeConfig( + targetArchitecture: dryRun ? null : Architecture.current, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: dryRun ? null : cCompiler); final buildConfigUri = testTempUri.resolve('build_config.json'); await File.fromUri(buildConfigUri) - .writeAsString(jsonEncode(config.toJson())); + .writeAsString(jsonEncode(configBuilder.json)); final processResult = await Process.run( dartUri.toFilePath(), @@ -76,8 +76,9 @@ void main() async { expect(processResult.exitCode, 0); final buildOutputUri = outputDirectory.resolve('build_output.json'); - final buildOutput = HookOutputImpl.fromJsonString( - await File.fromUri(buildOutputUri).readAsString()); + final buildOutput = BuildOutput( + json.decode(await File.fromUri(buildOutputUri).readAsString()) + as Map); final assets = buildOutput.encodedAssets; final dependencies = buildOutput.dependencies; if (dryRun) { diff --git a/pkgs/native_assets_cli/test/example/native_dynamic_linking_test.dart b/pkgs/native_assets_cli/test/example/native_dynamic_linking_test.dart index 4d7ea3feb..dada26501 100644 --- a/pkgs/native_assets_cli/test/example/native_dynamic_linking_test.dart +++ b/pkgs/native_assets_cli/test/example/native_dynamic_linking_test.dart @@ -49,25 +49,25 @@ void main() async { final testPackageUri = packageUri.resolve('example/build/$name/'); final dartUri = Uri.file(Platform.resolvedExecutable); - final config = BuildConfigImpl( - outputDirectory: outputDirectory, - outputDirectoryShared: outputDirectoryShared, - packageName: name, - packageRoot: testPackageUri, - targetOS: OS.current, - version: HookConfigImpl.latestVersion, - linkModePreference: LinkModePreference.dynamic, - dryRun: dryRun, - linkingEnabled: false, - targetArchitecture: dryRun ? null : Architecture.current, - buildMode: dryRun ? null : BuildMode.debug, - cCompiler: dryRun ? null : cCompiler, - supportedAssetTypes: [CodeAsset.type], - ); + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageRoot: testPackageUri, + packageName: name, + targetOS: OS.current, + supportedAssetTypes: [CodeAsset.type], + buildMode: dryRun ? null : BuildMode.debug) + ..setupBuildRunConfig( + outputDirectory: outputDirectory, + outputDirectoryShared: outputDirectoryShared) + ..setupBuildConfig(linkingEnabled: false, dryRun: dryRun) + ..setupCodeConfig( + targetArchitecture: dryRun ? null : Architecture.current, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: dryRun ? null : cCompiler); final buildConfigUri = testTempUri.resolve('build_config.json'); - File.fromUri(buildConfigUri) - .writeAsStringSync(jsonEncode(config.toJson())); + await File.fromUri(buildConfigUri) + .writeAsString(jsonEncode(configBuilder.json)); final processResult = await Process.run( dartUri.toFilePath(), @@ -85,8 +85,9 @@ void main() async { expect(processResult.exitCode, 0); final buildOutputUri = outputDirectory.resolve('build_output.json'); - final buildOutput = HookOutputImpl.fromJsonString( - await File.fromUri(buildOutputUri).readAsString()); + final buildOutput = BuildOutput( + json.decode(await File.fromUri(buildOutputUri).readAsString()) + as Map); final assets = buildOutput.encodedAssets; final dependencies = buildOutput.dependencies; if (dryRun) { diff --git a/pkgs/native_assets_cli/test/link_config_test.dart b/pkgs/native_assets_cli/test/link_config_test.dart new file mode 100644 index 000000000..44440d254 --- /dev/null +++ b/pkgs/native_assets_cli/test/link_config_test.dart @@ -0,0 +1,216 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:io'; + +import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:test/test.dart'; + +void main() async { + late Uri outDirUri; + late Uri outputDirectoryShared; + late String packageName; + late Uri packageRootUri; + late Uri fakeClang; + late Uri fakeLd; + late Uri fakeAr; + late List assets; + + setUp(() async { + final tempUri = Directory.systemTemp.uri; + outDirUri = tempUri.resolve('out1/'); + outputDirectoryShared = tempUri.resolve('out_shared1/'); + packageName = 'my_package'; + packageRootUri = tempUri.resolve('$packageName/'); + fakeClang = tempUri.resolve('fake_clang'); + fakeLd = tempUri.resolve('fake_ld'); + fakeAr = tempUri.resolve('fake_ar'); + + assets = [ + DataAsset( + package: packageName, + name: 'name', + file: Uri.file('nonexistent'), + ).encode(), + CodeAsset( + package: packageName, + name: 'name2', + linkMode: DynamicLoadingBundled(), + os: OS.android, + file: Uri.file('not there'), + architecture: Architecture.riscv64, + ).encode(), + ]; + }); + + test('LinkConfigBuilder->JSON->LinkConfig', () { + final configBuilder = LinkConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: packageRootUri, + targetOS: OS.android, + buildMode: BuildMode.release, + supportedAssetTypes: [CodeAsset.type], + ) + ..setupLinkConfig(assets: assets) + ..setupLinkRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + recordedUsesFile: null, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + targetAndroidNdkApi: 30, + linkModePreference: LinkModePreference.preferStatic, + cCompilerConfig: CCompilerConfig( + compiler: fakeClang, + linker: fakeLd, + archiver: fakeAr, + ), + ); + final config = LinkConfig(configBuilder.json); + + final expectedConfigJson = { + 'build_mode': 'release', + 'supported_asset_types': [CodeAsset.type], + 'link_mode_preference': 'prefer-static', + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_android_ndk_api': 30, + 'target_architecture': 'arm64', + 'target_os': 'android', + 'version': HookConfig.currentVersion.toString(), + 'c_compiler.ar': fakeAr.toFilePath(), + 'c_compiler.ld': fakeLd.toFilePath(), + 'c_compiler.cc': fakeClang.toFilePath(), + 'assets': [for (final asset in assets) asset.toJson()], + }; + expect(config.json, expectedConfigJson); + expect(json.decode(config.toString()), expectedConfigJson); + + expect(config.outputDirectory, outDirUri); + expect(config.outputDirectoryShared, outputDirectoryShared); + + expect(config.packageName, packageName); + expect(config.packageRoot, packageRootUri); + expect(config.targetOS, OS.android); + expect(config.buildMode, BuildMode.release); + expect(config.supportedAssetTypes, [CodeAsset.type]); + expect(config.encodedAssets, assets); + + final codeConfig = config.codeConfig; + expect(codeConfig.targetArchitecture, Architecture.arm64); + expect(codeConfig.targetAndroidNdkApi, 30); + expect(codeConfig.linkModePreference, LinkModePreference.preferStatic); + expect(codeConfig.cCompiler.compiler, fakeClang); + expect(codeConfig.cCompiler.linker, fakeLd); + expect(codeConfig.cCompiler.archiver, fakeAr); + }); + + group('LinkConfig FormatExceptions', () { + for (final version in ['9001.0.0', '0.0.1']) { + test('LinkConfig version $version', () { + final outDir = outDirUri; + final config = { + 'link_mode_preference': 'prefer-static', + 'out_dir': outDir.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_root': packageRootUri.toFilePath(), + 'target_os': 'linux', + 'version': version, + 'package_name': packageName, + 'supported_asset_types': [CodeAsset.type], + 'dry_run': true, + }; + expect( + () => LinkConfig(config), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains(version) && + e.message.contains(HookConfig.currentVersion.toString()), + )), + ); + }); + } + + test('invalid architecture', () { + final config = { + 'supported_asset_types': [CodeAsset.type], + 'build_mode': 'release', + 'dry_run': false, + 'link_mode_preference': 'prefer-static', + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_android_ndk_api': 30, + 'target_architecture': 'invalid_architecture', + 'target_os': 'android', + 'version': HookOutput.latestVersion.toString(), + }; + expect( + () => LinkConfig(config), + throwsFormatException, + ); + }); + + test('LinkConfig FormatExceptions', () { + expect( + () => LinkConfig({}), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains('No value was provided for required key: '), + )), + ); + expect( + () => LinkConfig({ + 'version': HookConfig.currentVersion.toString(), + 'supported_asset_types': [CodeAsset.type], + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_architecture': 'arm64', + 'target_os': 'android', + 'target_android_ndk_api': 30, + 'assets': [], + }), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains( + 'No value was provided for required key: out_dir', + ), + )), + ); + expect( + () => LinkConfig({ + 'version': HookConfig.currentVersion.toString(), + 'supported_asset_types': [CodeAsset.type], + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_architecture': 'arm64', + 'target_os': 'android', + 'target_android_ndk_api': 30, + 'build_mode': BuildMode.release.name, + 'assets': 'astring', + 'link_mode_preference': LinkModePreference.preferStatic.name, + }), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains( + "Unexpected value 'astring' for key '.assets' in config file. " + 'Expected a List?.', + ), + )), + ); + }); + }); +} diff --git a/pkgs/native_assets_cli/test/model/build_config_test.dart b/pkgs/native_assets_cli/test/model/build_config_test.dart deleted file mode 100644 index 08afdbb0d..000000000 --- a/pkgs/native_assets_cli/test/model/build_config_test.dart +++ /dev/null @@ -1,604 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:native_assets_cli/native_assets_cli_internal.dart'; -import 'package:test/test.dart'; - -void main() async { - const packageName = 'my_package'; - late Uri tempUri; - late Uri outDirUri; - late Uri outDir2Uri; - late Uri outputDirectoryShared; - late Uri outputDirectoryShared2; - late Uri packageRootUri; - late Uri fakeClang; - late Uri fakeLd; - late Uri fakeAr; - late Uri fakeCl; - late Uri fakeVcVars; - - setUp(() async { - tempUri = (await Directory.systemTemp.createTemp()).uri; - outDirUri = tempUri.resolve('out1/'); - await Directory.fromUri(outDirUri).create(); - outDir2Uri = tempUri.resolve('out2/'); - await Directory.fromUri(outDir2Uri).create(); - outputDirectoryShared = tempUri.resolve('out_shared1/'); - await Directory.fromUri(outputDirectoryShared).create(); - outputDirectoryShared2 = tempUri.resolve('out_shared2/'); - await Directory.fromUri(outputDirectoryShared2).create(); - packageRootUri = tempUri.resolve('$packageName/'); - await Directory.fromUri(packageRootUri).create(); - fakeClang = tempUri.resolve('fake_clang'); - await File.fromUri(fakeClang).create(); - fakeLd = tempUri.resolve('fake_ld'); - await File.fromUri(fakeLd).create(); - fakeAr = tempUri.resolve('fake_ar'); - await File.fromUri(fakeAr).create(); - fakeCl = tempUri.resolve('cl.exe'); - await File.fromUri(fakeCl).create(); - fakeVcVars = tempUri.resolve('vcvarsall.bat'); - await File.fromUri(fakeVcVars).create(); - }); - - tearDown(() async { - await Directory.fromUri(tempUri).delete(recursive: true); - }); - - test('BuildConfig ==', () { - final config1 = BuildConfigImpl( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - archiver: fakeAr, - ), - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final config2 = BuildConfigImpl( - outputDirectory: outDir2Uri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - expect(config1, equals(config1)); - expect(config1 == config2, false); - expect(config1.outputDirectory != config2.outputDirectory, true); - expect(config1.packageRoot, config2.packageRoot); - expect(config1.targetArchitecture == config2.targetArchitecture, true); - expect(config1.targetOS != config2.targetOS, true); - expect(config1.targetIOSSdk, IOSSdk.iPhoneOS); - expect(() => config2.targetIOSSdk, throwsStateError); - expect(config1.cCompiler.compiler != config2.cCompiler.compiler, true); - expect(config1.cCompiler.linker != config2.cCompiler.linker, true); - expect(config1.cCompiler.archiver != config2.cCompiler.archiver, true); - expect(config1.cCompiler.envScript == config2.cCompiler.envScript, true); - expect(config1.cCompiler.envScriptArgs == config2.cCompiler.envScriptArgs, - true); - expect(config1.cCompiler != config2.cCompiler, true); - expect(config1.linkModePreference, config2.linkModePreference); - expect(config1.linkingEnabled, config2.linkingEnabled); - }); - - test('BuildConfig fromConfig', () { - final buildConfig2 = BuildConfigImpl( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final config = { - 'supported_asset_types': [CodeAsset.type], - 'build_mode': 'release', - 'dry_run': false, - 'linking_enabled': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'arm64', - 'target_os': 'android', - 'version': HookOutputImpl.latestVersion.toString(), - }; - - final fromConfig = BuildConfigImpl.fromJson(config); - expect(fromConfig, equals(buildConfig2)); - }); - - test('BuildConfig.dryRun', () { - final buildConfig2 = BuildConfigImpl.dryRun( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetOS: OS.android, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final config = { - 'dry_run': true, - 'supported_asset_types': [CodeAsset.type], - 'linking_enabled': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_os': 'android', - 'version': HookOutputImpl.latestVersion.toString(), - }; - - final fromConfig = BuildConfigImpl.fromJson(config); - expect(fromConfig, equals(buildConfig2)); - }); - - test('BuildConfig toJson fromConfig', () { - final buildConfig1 = BuildConfigImpl( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - ), - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final configFile = buildConfig1.toJson(); - final fromConfig = BuildConfigImpl.fromJson(configFile); - expect(fromConfig, equals(buildConfig1)); - }); - - test('BuildConfig == dependency metadata', () { - final buildConfig1 = BuildConfigImpl( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - dependencyMetadata: { - 'bar': const Metadata({ - 'key': 'value', - 'foo': ['asdf', 'fdsa'], - }), - 'foo': const Metadata({ - 'key': 321, - }), - }, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final buildConfig2 = BuildConfigImpl( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - dependencyMetadata: { - 'bar': const Metadata({ - 'key': 'value', - }), - 'foo': const Metadata({ - 'key': 123, - }), - }, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - expect(buildConfig1, equals(buildConfig1)); - expect(buildConfig1 == buildConfig2, false); - expect(buildConfig1.hashCode == buildConfig2.hashCode, false); - }); - - test('BuildConfig toJson fromJson', () { - final outDir = outDirUri; - final buildConfig1 = BuildConfigImpl( - outputDirectory: outDir, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - ), - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - // This map should be sorted on key for two layers. - dependencyMetadata: { - 'foo': const Metadata({ - 'z': ['z', 'a'], - 'a': 321, - }), - 'bar': const Metadata({ - 'key': 'value', - }), - }, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final jsonObject = buildConfig1.toJson(); - final expectedJson = { - 'build_mode': 'release', - 'c_compiler': {'cc': fakeClang.toFilePath(), 'ld': fakeLd.toFilePath()}, - 'dependency_metadata': { - 'bar': {'key': 'value'}, - 'foo': { - 'a': 321, - 'z': ['z', 'a'] - } - }, - 'linking_enabled': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'supported_asset_types': [CodeAsset.type], - 'target_architecture': 'arm64', - 'target_ios_sdk': 'iphoneos', - 'target_os': 'ios', - 'version': '${HookConfigImpl.latestVersion}' - }; - expect( - jsonObject, - equals(expectedJson), - ); - - final buildConfig2 = BuildConfigImpl.fromJson(jsonObject); - expect(buildConfig2, buildConfig1); - }); - - test('BuildConfig FormatExceptions', () { - expect( - () => BuildConfigImpl.fromJson({}), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains( - 'No value was provided for required key: target_os', - ), - )), - ); - expect( - () => BuildConfigImpl.fromJson({ - 'version': HookConfigImpl.latestVersion.toString(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', - 'target_os': 'android', - 'target_android_ndk_api': 30, - 'link_mode_preference': 'prefer-static', - 'supported_asset_types': [CodeAsset.type], - }), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains( - 'No value was provided for required key: out_dir', - ), - )), - ); - expect( - () => BuildConfigImpl.fromJson({ - 'version': HookConfigImpl.latestVersion.toString(), - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', - 'target_os': 'android', - 'target_android_ndk_api': 30, - 'link_mode_preference': 'prefer-static', - 'build_mode': BuildMode.release.name, - 'supported_asset_types': [CodeAsset.type], - 'dependency_metadata': { - 'bar': {'key': 'value'}, - 'foo': [], - }, - }), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains( - "Unexpected value '[]' for key 'dependency_metadata.foo' in " - 'config file. Expected a Map.', - ), - )), - ); - expect( - () => BuildConfigImpl.fromJson({ - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'version': HookConfigImpl.latestVersion.toString(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', - 'target_os': 'android', - 'link_mode_preference': 'prefer-static', - 'supported_asset_types': [CodeAsset.type], - 'build_mode': BuildMode.release.name, - }), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains( - 'No value was provided for required key: target_android_ndk_api', - ), - )), - ); - }); - - test('BuildConfig toString', () { - final config = BuildConfigImpl( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - ), - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - config.toString(); - }); - - test('BuildConfig fromArgs', () async { - final buildConfig = BuildConfigImpl( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.preferStatic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - final configFileContents = buildConfig.toJsonString(); - final configUri = tempUri.resolve('config.json'); - final configFile = File.fromUri(configUri); - await configFile.writeAsString(configFileContents); - final buildConfig2 = BuildConfigImpl.fromArguments( - ['--config', configUri.toFilePath()], - environment: {}, // Don't inherit the test environment. - ); - expect(buildConfig2, buildConfig); - }); - - test('envScript', () { - final buildConfig1 = BuildConfigImpl( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetArchitecture: Architecture.x64, - targetOS: OS.windows, - cCompiler: CCompilerConfig( - compiler: fakeCl, - envScript: fakeVcVars, - envScriptArgs: ['x64'], - ), - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - - final configFile = buildConfig1.toJson(); - final fromConfig = BuildConfigImpl.fromJson(configFile); - expect(fromConfig, equals(buildConfig1)); - }); - - for (final version in ['9001.0.0', '0.0.1']) { - test('BuildConfig version $version', () { - final outDir = outDirUri; - final config = { - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_root': tempUri.toFilePath(), - 'target_os': 'linux', - 'version': version, - 'package_name': packageName, - 'supported_asset_types': [CodeAsset.type], - 'dry_run': true, - }; - expect( - () => BuildConfigImpl.fromJson(config), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains(version) && - e.message.contains(HookConfigImpl.latestVersion.toString()), - )), - ); - }); - } - - test('BuildConfig invalid target os architecture combination', () { - final outDir = outDirUri; - final config = { - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_os': 'windows', - 'target_architecture': 'arm', - 'build_mode': 'debug', - 'supported_asset_types': [CodeAsset.type], - 'version': HookConfigImpl.latestVersion.toString(), - }; - expect( - () => BuildConfigImpl.fromJson(config), - throwsA(predicate( - (e) => e is FormatException && e.message.contains('arm'), - )), - ); - }); - - test('BuildConfig dry_run access invalid args', () { - final outDir = outDirUri; - final config = { - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_os': 'windows', - 'target_architecture': 'arm64', - 'build_mode': 'debug', - 'dry_run': true, - 'supported_asset_types': [CodeAsset.type], - 'version': HookConfigImpl.latestVersion.toString(), - }; - expect( - () => BuildConfigImpl.fromJson(config), - throwsA(predicate( - (e) => - e is FormatException && e.message.contains('In Flutter projects'), - )), - ); - }); - - test('BuildConfig dry_run access invalid args', () { - final outDir = outDirUri; - final config = { - 'dry_run': true, - 'linking_enabled': true, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_os': 'android', - 'supported_asset_types': [CodeAsset.type], - 'version': HookConfigImpl.latestVersion.toString(), - }; - final buildConfig = BuildConfigImpl.fromJson(config); - expect( - () => buildConfig.targetAndroidNdkApi, - throwsA(predicate( - (e) => e is StateError && e.message.contains('In Flutter projects'), - )), - ); - }); - - test('BuildConfig dry_run target arch', () { - final outDir = outDirUri; - final config = { - 'dry_run': true, - 'linking_enabled': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_os': 'windows', - 'supported_asset_types': [CodeAsset.type], - 'version': HookConfigImpl.latestVersion.toString(), - }; - final buildConfig = BuildConfigImpl.fromJson(config); - expect(buildConfig.targetArchitecture, isNull); - }); - - test('BuildConfig dry_run toString', () { - final buildConfig = BuildConfigImpl.dryRun( - packageName: packageName, - outputDirectoryShared: outputDirectoryShared, - outputDirectory: outDirUri, - packageRoot: tempUri, - targetOS: OS.windows, - linkModePreference: LinkModePreference.dynamic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - buildConfig.toJsonString(); - // No crash. - }); - - test('invalid architecture', () { - final config = { - 'build_mode': 'release', - 'dry_run': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'invalid_architecture', - 'target_os': 'android', - 'supported_asset_types': [CodeAsset.type], - 'version': HookOutputImpl.latestVersion.toString(), - }; - expect( - () => BuildConfigImpl.fromJson(config), - throwsFormatException, - ); - }); -} diff --git a/pkgs/native_assets_cli/test/model/build_output_test.dart b/pkgs/native_assets_cli/test/model/build_output_test.dart deleted file mode 100644 index 7f28a0ffb..000000000 --- a/pkgs/native_assets_cli/test/model/build_output_test.dart +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:native_assets_cli/native_assets_cli_internal.dart'; -import 'package:pub_semver/pub_semver.dart'; -import 'package:test/test.dart'; - -void main() { - late Uri tempUri; - - setUp(() async { - tempUri = (await Directory.systemTemp.createTemp()).uri; - }); - - tearDown(() async { - await Directory.fromUri(tempUri).delete(recursive: true); - }); - - final jsonEncoding = { - 'timestamp': '2022-11-10 13:25:01.000', - 'assets': [ - { - 'architecture': 'x64', - 'file': Uri.file('path/to/libfoo.so').toFilePath(), - 'id': 'package:my_package/foo', - 'link_mode': {'type': 'dynamic_loading_bundle'}, - 'os': 'android', - 'type': 'native_code' - }, - { - 'architecture': 'x64', - 'id': 'package:my_package/foo2', - 'link_mode': { - 'type': 'dynamic_loading_system', - 'uri': Uri.file('path/to/libfoo2.so').toFilePath(), - }, - 'os': 'android', - 'type': 'native_code' - }, - { - 'architecture': 'x64', - 'id': 'package:my_package/foo3', - 'link_mode': {'type': 'dynamic_loading_process'}, - 'os': 'android', - 'type': 'native_code' - }, - { - 'architecture': 'x64', - 'id': 'package:my_package/foo4', - 'link_mode': {'type': 'dynamic_loading_executable'}, - 'os': 'android', - 'type': 'native_code' - } - ], - 'assetsForLinking': { - 'my_package': [ - { - 'name': 'data', - 'package': 'my_package', - 'file': Uri.file('path/to/data').toFilePath(), - 'type': 'data' - } - ], - 'my_package_2': [ - { - 'name': 'data', - 'package': 'my_package', - 'file': Uri.file('path/to/data2').toFilePath(), - 'type': 'data' - } - ] - }, - 'dependencies': [ - Uri.file('path/to/file.ext').toFilePath(), - ], - 'metadata': {'key': 'value'}, - 'version': '${HookOutputImpl.latestVersion}' - }; - - test('built info json', () { - final buildOutput = getBuildOutput(); - final json = buildOutput.toJson(HookOutputImpl.latestVersion); - expect(json, jsonEncoding); - - final buildOutput2 = HookOutputImpl.fromJson(json); - expect(buildOutput.hashCode, buildOutput2.hashCode); - expect(buildOutput, buildOutput2); - }); - - test('BuildOutput.toString', getBuildOutput().toString); - - test('BuildOutput.hashCode', () { - final buildOutput = getBuildOutput(); - final buildOutput2 = HookOutputImpl.fromJson(jsonEncoding); - expect(buildOutput.hashCode, buildOutput2.hashCode); - - final buildOutput3 = HookOutputImpl( - timestamp: DateTime.parse('2022-11-10 13:25:01.000'), - ); - expect(buildOutput.hashCode != buildOutput3.hashCode, true); - }); - - test('BuildOutput.readFromFile BuildOutput.writeToFile', () async { - final outDir = tempUri.resolve('out_dir/'); - final outDirShared = tempUri.resolve('out_dir_shared/'); - final packageRoot = tempUri.resolve('package_root/'); - await Directory.fromUri(outDir).create(); - await Directory.fromUri(outDirShared).create(); - await Directory.fromUri(packageRoot).create(); - final config = BuildConfigImpl( - outputDirectory: outDir, - outputDirectoryShared: outDirShared, - packageName: 'dontcare', - packageRoot: packageRoot, - buildMode: BuildMode.debug, - targetArchitecture: Architecture.arm64, - targetOS: OS.macOS, - linkModePreference: LinkModePreference.dynamic, - linkingEnabled: false, - supportedAssetTypes: [CodeAsset.type], - ); - final buildOutput = getBuildOutput(); - await buildOutput.writeToFile(config: config); - final buildOutput2 = HookOutputImpl.readFromFile(file: config.outputFile); - expect(buildOutput2, buildOutput); - }); - - test('BuildOutput.readFromFile BuildOutput.writeToFile V1.1.0', () async { - final outDir = tempUri.resolve('out_dir/'); - final outDirShared = tempUri.resolve('out_dir_shared/'); - final packageRoot = tempUri.resolve('package_root/'); - await Directory.fromUri(outDir).create(); - await Directory.fromUri(outDirShared).create(); - await Directory.fromUri(packageRoot).create(); - final config = BuildConfigImpl( - outputDirectory: outDir, - outputDirectoryShared: outDirShared, - packageName: 'dontcare', - packageRoot: packageRoot, - buildMode: BuildMode.debug, - targetArchitecture: Architecture.arm64, - targetOS: OS.macOS, - linkModePreference: LinkModePreference.dynamic, - version: Version(1, 1, 0), - linkingEnabled: null, // version < 1.4.0 - supportedAssetTypes: [CodeAsset.type], - ); - final buildOutput = getBuildOutput(withLinkedAssets: false); - await buildOutput.writeToFile(config: config); - final buildOutput2 = HookOutputImpl.readFromFile(file: config.outputFile); - expect(buildOutput2, buildOutput); - }); - - test('Round timestamp', () { - final buildOutput3 = HookOutputImpl( - timestamp: DateTime.parse('2022-11-10 13:25:01.372257'), - ); - expect(buildOutput3.timestamp, DateTime.parse('2022-11-10 13:25:01.000')); - }); - - for (final version in ['9001.0.0', '0.0.1']) { - test('BuildOutput version $version', () { - expect( - () => HookOutputImpl.fromJsonString('{"version": "$version"}'), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains(version) && - e.message.contains(HookOutputImpl.latestVersion.toString()), - )), - ); - }); - } - - test('BuildOutput dependencies can be modified', () { - final buildOutput = HookOutputImpl(); - expect( - () => buildOutput.addDependencies([Uri.file('path/to/file.ext')]), - returnsNormally, - ); - }); - - test('BuildOutput setters', () { - final buildOutput = HookOutputImpl( - timestamp: DateTime.parse('2022-11-10 13:25:01.000'), - encodedAssets: [ - CodeAsset( - package: 'my_package', - name: 'foo', - file: Uri(path: 'path/to/libfoo.so'), - linkMode: DynamicLoadingBundled(), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - CodeAsset( - package: 'my_package', - name: 'foo2', - linkMode: DynamicLoadingSystem(Uri(path: 'path/to/libfoo2.so')), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - ], - dependencies: Dependencies([ - Uri.file('path/to/file.ext'), - Uri.file('path/to/file2.ext'), - ]), - metadata: const Metadata({ - 'key': 'value', - 'key2': 'value2', - }), - ); - - final buildOutput2 = HookOutputImpl( - timestamp: DateTime.parse('2022-11-10 13:25:01.000'), - ); - buildOutput2.addEncodedAsset( - CodeAsset( - package: 'my_package', - name: 'foo', - file: Uri(path: 'path/to/libfoo.so'), - linkMode: DynamicLoadingBundled(), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - ); - buildOutput2.addEncodedAssets([ - CodeAsset( - package: 'my_package', - name: 'foo2', - linkMode: DynamicLoadingSystem(Uri(path: 'path/to/libfoo2.so')), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - ]); - buildOutput2.addDependency( - Uri.file('path/to/file.ext'), - ); - buildOutput2.addDependencies([ - Uri.file('path/to/file2.ext'), - ]); - buildOutput2.addMetadata({ - 'key': 'value', - }); - buildOutput2.addMetadatum('key2', 'value2'); - - expect(buildOutput2, equals(buildOutput)); - expect( - buildOutput2.dependenciesModel, equals(buildOutput.dependenciesModel)); - expect(buildOutput2.metadataModel, equals(buildOutput.metadataModel)); - }); -} - -HookOutputImpl getBuildOutput({bool withLinkedAssets = true}) => HookOutputImpl( - timestamp: DateTime.parse('2022-11-10 13:25:01.000'), - encodedAssets: [ - CodeAsset( - package: 'my_package', - name: 'foo', - file: Uri(path: 'path/to/libfoo.so'), - linkMode: DynamicLoadingBundled(), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - CodeAsset( - package: 'my_package', - name: 'foo2', - linkMode: DynamicLoadingSystem(Uri(path: 'path/to/libfoo2.so')), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - CodeAsset( - package: 'my_package', - name: 'foo3', - linkMode: LookupInProcess(), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - CodeAsset( - package: 'my_package', - name: 'foo4', - linkMode: LookupInExecutable(), - os: OS.android, - architecture: Architecture.x64, - ).encode(), - ], - encodedAssetsForLinking: withLinkedAssets - ? { - 'my_package': [ - DataAsset( - file: Uri.file('path/to/data'), - name: 'data', - package: 'my_package', - ).encode() - ], - 'my_package_2': [ - DataAsset( - file: Uri.file('path/to/data2'), - name: 'data', - package: 'my_package', - ).encode() - ] - } - : null, - dependencies: Dependencies([ - Uri.file('path/to/file.ext'), - ]), - metadata: const Metadata({ - 'key': 'value', - }), - ); diff --git a/pkgs/native_assets_cli/test/model/checksum_test.dart b/pkgs/native_assets_cli/test/model/checksum_test.dart deleted file mode 100644 index cff247336..000000000 --- a/pkgs/native_assets_cli/test/model/checksum_test.dart +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:native_assets_cli/native_assets_cli_internal.dart'; -import 'package:test/test.dart'; - -import '../helpers.dart'; - -void main() { - const packageName = 'my_package'; - test('checksum', () async { - await inTempDir((tempUri) async { - final nativeAddUri = tempUri.resolve('native_add/'); - final fakeClangUri = tempUri.resolve('fake_clang'); - await File.fromUri(fakeClangUri).create(); - - final name1 = HookConfigImpl.checksum( - packageName: packageName, - packageRoot: nativeAddUri, - targetArchitecture: Architecture.x64, - targetOS: OS.linux, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - hook: Hook.build, - version: HookConfigImpl.latestVersion, - linkingEnabled: true, - ); - - // Using the checksum for a build folder should be stable. - expect(name1, '8780162e48a4539f01ea483fda6c1efc'); - - // Build folder different due to metadata. - final name2 = HookConfigImpl.checksum( - packageName: packageName, - packageRoot: nativeAddUri, - targetArchitecture: Architecture.x64, - targetOS: OS.linux, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - dependencyMetadata: { - 'foo': const Metadata({'key': 'value'}) - }, - hook: Hook.build, - version: HookConfigImpl.latestVersion, - linkingEnabled: true, - ); - printOnFailure([name1, name2].toString()); - expect(name1 != name2, true); - - // Build folder different due to cc. - final name3 = HookConfigImpl.checksum( - packageName: packageName, - packageRoot: nativeAddUri, - targetArchitecture: Architecture.x64, - targetOS: OS.linux, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - cCompiler: CCompilerConfig( - compiler: fakeClangUri, - ), - hook: Hook.build, - version: HookConfigImpl.latestVersion, - linkingEnabled: true, - ); - printOnFailure([name1, name3].toString()); - expect(name1 != name3, true); - - // Build folder different due to hook. - final name4 = HookConfigImpl.checksum( - packageName: packageName, - packageRoot: nativeAddUri, - targetArchitecture: Architecture.x64, - targetOS: OS.linux, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - cCompiler: CCompilerConfig( - compiler: fakeClangUri, - ), - hook: Hook.link, - version: HookConfigImpl.latestVersion, - linkingEnabled: true, - ); - printOnFailure([name1, name4].toString()); - expect(name1 != name4, true); - - // Build folder different due to haslinkPhase. - final name5 = HookConfigImpl.checksum( - packageName: packageName, - packageRoot: nativeAddUri, - targetArchitecture: Architecture.x64, - targetOS: OS.linux, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - hook: Hook.build, - version: HookConfigImpl.latestVersion, - linkingEnabled: false, - ); - printOnFailure([name1, name5].toString()); - expect(name1, isNot(name5)); - }); - }); -} diff --git a/pkgs/native_assets_cli/test/model/link_config_test.dart b/pkgs/native_assets_cli/test/model/link_config_test.dart deleted file mode 100644 index 1f07cc4e2..000000000 --- a/pkgs/native_assets_cli/test/model/link_config_test.dart +++ /dev/null @@ -1,517 +0,0 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:io'; - -import 'package:native_assets_cli/native_assets_cli_internal.dart'; -import 'package:test/test.dart'; - -void main() async { - late Uri tempUri; - late Uri outDirUri; - late Uri outDir2Uri; - late Uri outputDirectoryShared; - late Uri outputDirectoryShared2; - const packageName = 'my_package'; - late Uri packageRootUri; - late Uri fakeClang; - late Uri fakeLd; - late Uri fakeAr; - late Uri fakeCl; - late Uri fakeVcVars; - late Uri recordedUsagesFile; - final assets = [ - DataAsset( - package: packageName, - name: 'name', - file: Uri.file('nonexistent'), - ).encode(), - CodeAsset( - package: packageName, - name: 'name2', - linkMode: DynamicLoadingBundled(), - os: OS.android, - file: Uri.file('not there'), - architecture: Architecture.riscv64, - ).encode(), - ]; - - setUp(() async { - tempUri = (await Directory.systemTemp.createTemp()).uri; - outDirUri = tempUri.resolve('out1/'); - await Directory.fromUri(outDirUri).create(); - outDir2Uri = tempUri.resolve('out2/'); - await Directory.fromUri(outDir2Uri).create(); - outputDirectoryShared = tempUri.resolve('out_shared1/'); - await Directory.fromUri(outputDirectoryShared).create(); - outputDirectoryShared2 = tempUri.resolve('out_shared2/'); - await Directory.fromUri(outputDirectoryShared2).create(); - packageRootUri = tempUri.resolve('$packageName/'); - await Directory.fromUri(packageRootUri).create(); - fakeClang = tempUri.resolve('fake_clang'); - await File.fromUri(fakeClang).create(); - fakeLd = tempUri.resolve('fake_ld'); - await File.fromUri(fakeLd).create(); - fakeAr = tempUri.resolve('fake_ar'); - await File.fromUri(fakeAr).create(); - fakeCl = tempUri.resolve('cl.exe'); - await File.fromUri(fakeCl).create(); - fakeVcVars = tempUri.resolve('vcvarsall.bat'); - await File.fromUri(fakeVcVars).create(); - recordedUsagesFile = tempUri.resolve('recorded_usages.json'); - File.fromUri(recordedUsagesFile).createSync(); - }); - - tearDown(() async { - await Directory.fromUri(tempUri).delete(recursive: true); - }); - - test('LinkConfig ==', () { - final config1 = LinkConfigImpl( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - archiver: fakeAr, - ), - buildMode: BuildMode.release, - encodedAssets: assets, - recordedUsagesFile: recordedUsagesFile, - linkModePreference: LinkModePreference.preferStatic, - ); - - final config2 = LinkConfigImpl( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: outDir2Uri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - encodedAssets: [], - recordedUsagesFile: null, - linkModePreference: LinkModePreference.preferStatic, - ); - - expect(config1, equals(config1)); - expect(config1 == config2, false); - expect(config1.outputDirectory != config2.outputDirectory, true); - expect(config1.packageRoot, config2.packageRoot); - expect(config1.targetArchitecture == config2.targetArchitecture, true); - expect(config1.targetOS != config2.targetOS, true); - expect(config1.targetIOSSdk, IOSSdk.iPhoneOS); - expect(() => config2.targetIOSSdk, throwsStateError); - expect(config1.cCompiler.compiler != config2.cCompiler.compiler, true); - expect(config1.cCompiler.linker != config2.cCompiler.linker, true); - expect(config1.cCompiler.archiver != config2.cCompiler.archiver, true); - expect(config1.cCompiler.envScript == config2.cCompiler.envScript, true); - expect(config1.cCompiler.envScriptArgs == config2.cCompiler.envScriptArgs, - true); - expect(config1.cCompiler != config2.cCompiler, true); - expect(config1.encodedAssets != config2.encodedAssets, true); - }); - - test('LinkConfig fromConfig', () { - final buildConfig2 = LinkConfigImpl( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - encodedAssets: assets, - linkModePreference: LinkModePreference.preferStatic, - ); - - final config = { - 'build_mode': 'release', - 'supported_asset_types': [CodeAsset.type], - 'dry_run': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'arm64', - 'target_os': 'android', - 'version': HookOutputImpl.latestVersion.toString(), - 'assets': [for (final asset in assets) asset.toJson()], - }; - - final fromConfig = LinkConfigImpl.fromJson(config); - expect(fromConfig, equals(buildConfig2)); - }); - - test('LinkConfig.dryRun', () { - final buildConfig2 = LinkConfigImpl.dryRun( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetOS: OS.android, - encodedAssets: [], - linkModePreference: LinkModePreference.preferStatic, - ); - - final config = { - 'dry_run': true, - 'supported_asset_types': [CodeAsset.type], - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_os': 'android', - 'version': HookOutputImpl.latestVersion.toString(), - 'assets': [], - }; - - final fromConfig = LinkConfigImpl.fromJson(config); - expect(fromConfig, equals(buildConfig2)); - }); - - test('LinkConfig toJson fromConfig', () { - final buildConfig1 = LinkConfigImpl( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: packageRootUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - ), - buildMode: BuildMode.release, - encodedAssets: assets, - linkModePreference: LinkModePreference.preferStatic, - ); - - final configFile = buildConfig1.toJson(); - final fromConfig = LinkConfigImpl.fromJson(configFile); - expect(fromConfig, equals(buildConfig1)); - }); - - test('LinkConfig toJson fromJson', () { - final outDir = outDirUri; - final buildConfig1 = LinkConfigImpl( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: outDir, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - ), - buildMode: BuildMode.release, - encodedAssets: assets, - linkModePreference: LinkModePreference.preferStatic, - ); - - final jsonObject = buildConfig1.toJson(); - final expectedJson = { - 'assets': [for (final asset in assets) asset.toJson()], - 'supported_asset_types': [CodeAsset.type], - 'build_mode': 'release', - 'c_compiler': {'cc': fakeClang.toFilePath(), 'ld': fakeLd.toFilePath()}, - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_architecture': 'arm64', - 'target_ios_sdk': 'iphoneos', - 'target_os': 'ios', - 'version': '${HookConfigImpl.latestVersion}', - 'link_mode_preference': 'prefer-static', - }; - expect(jsonObject, equals(expectedJson)); - - final buildConfig2 = LinkConfigImpl.fromJson(jsonObject); - expect(buildConfig2, buildConfig1); - }); - - test('LinkConfig FormatExceptions', () { - expect( - () => LinkConfigImpl.fromJson({}), - throwsA(predicate( - (e) => - e is FormatException && - e.message - .contains('No value was provided for required key: target_os'), - )), - ); - expect( - () => LinkConfigImpl.fromJson({ - 'version': HookConfigImpl.latestVersion.toString(), - 'supported_asset_types': [CodeAsset.type], - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', - 'target_os': 'android', - 'target_android_ndk_api': 30, - 'assets': [], - }), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains( - 'No value was provided for required key: out_dir', - ), - )), - ); - expect( - () => LinkConfigImpl.fromJson({ - 'version': HookConfigImpl.latestVersion.toString(), - 'supported_asset_types': [CodeAsset.type], - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', - 'target_os': 'android', - 'target_android_ndk_api': 30, - 'build_mode': BuildMode.release.name, - 'assets': 'astring', - 'link_mode_preference': LinkModePreference.preferStatic.name, - }), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains( - "Unexpected value 'astring' for key '.assets' in config file. " - 'Expected a List?.', - ), - )), - ); - expect( - () => LinkConfigImpl.fromJson({ - 'supported_asset_types': [CodeAsset.type], - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'version': HookConfigImpl.latestVersion.toString(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', - 'target_os': 'android', - 'build_mode': BuildMode.release.name, - 'link_mode_preference': LinkModePreference.preferStatic.name, - }), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains( - 'No value was provided for required key: target_android_ndk_api', - ), - )), - ); - }); - - test('LinkConfig toString', () { - final config = LinkConfigImpl( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - cCompiler: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - ), - buildMode: BuildMode.release, - encodedAssets: assets, - linkModePreference: LinkModePreference.preferStatic, - ); - expect(config.toString(), isNotEmpty); - }); - - test('LinkConfig fromArgs', () async { - final buildConfig = LinkConfigImpl( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.android, - targetAndroidNdkApi: 30, - buildMode: BuildMode.release, - encodedAssets: assets, - recordedUsagesFile: recordedUsagesFile, - linkModePreference: LinkModePreference.preferStatic, - ); - final configFileContents = buildConfig.toJsonString(); - final configUri = tempUri.resolve('config.json'); - final configFile = File.fromUri(configUri); - await configFile.writeAsString(configFileContents); - final buildConfig2 = - LinkConfigImpl.fromArguments(['--config', configUri.toFilePath()]); - expect(buildConfig2, buildConfig); - }); - - for (final version in ['9001.0.0', '0.0.1']) { - test('LinkConfig version $version', () { - final outDir = outDirUri; - final config = { - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_root': tempUri.toFilePath(), - 'target_os': 'linux', - 'version': version, - 'package_name': packageName, - 'dry_run': true, - }; - expect( - () => LinkConfigImpl.fromJson(config), - throwsA(predicate( - (e) => - e is FormatException && - e.message.contains(version) && - e.message.contains(HookConfigImpl.latestVersion.toString()), - )), - ); - }); - } - - test('LinkConfig invalid target os architecture combination', () { - final outDir = outDirUri; - final config = { - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_os': 'windows', - 'target_architecture': 'arm', - 'build_mode': 'debug', - 'version': HookConfigImpl.latestVersion.toString(), - }; - expect( - () => LinkConfigImpl.fromJson(config), - throwsA(predicate( - (e) => e is FormatException && e.message.contains('arm'), - )), - ); - }); - - test('LinkConfig dry_run access invalid args', () { - final outDir = outDirUri; - final config = { - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_os': 'windows', - 'target_architecture': 'arm64', - 'build_mode': 'debug', - 'dry_run': true, - 'version': HookConfigImpl.latestVersion.toString(), - }; - expect( - () => LinkConfigImpl.fromJson(config), - throwsA(predicate( - (e) => - e is FormatException && e.message.contains('In Flutter projects'), - )), - ); - }); - - test('LinkConfig dry_run access invalid args', () { - final outDir = outDirUri; - final config = { - 'link_mode_preference': 'prefer-static', - 'supported_asset_types': [CodeAsset.type], - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_os': 'android', - 'dry_run': true, - 'version': HookConfigImpl.latestVersion.toString(), - }; - final buildConfig = LinkConfigImpl.fromJson(config); - expect( - () => buildConfig.targetAndroidNdkApi, - throwsA(predicate( - (e) => e is StateError && e.message.contains('In Flutter projects'), - )), - ); - }); - - test('LinkConfig dry_run target arch', () { - final outDir = outDirUri; - final config = { - 'supported_asset_types': [CodeAsset.type], - 'link_mode_preference': 'prefer-static', - 'out_dir': outDir.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': tempUri.toFilePath(), - 'target_os': 'windows', - 'dry_run': true, - 'version': HookConfigImpl.latestVersion.toString(), - }; - final buildConfig = LinkConfigImpl.fromJson(config); - expect(buildConfig.targetArchitecture, isNull); - }); - - test('LinkConfig dry_run toString', () { - final buildConfig = LinkConfigImpl.dryRun( - supportedAssetTypes: [CodeAsset.type], - packageName: packageName, - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - packageRoot: tempUri, - targetOS: OS.windows, - encodedAssets: assets, - linkModePreference: LinkModePreference.preferStatic, - ); - expect(buildConfig.toJsonString(), isNotEmpty); - }); - - test('invalid architecture', () { - final config = { - 'supported_asset_types': [CodeAsset.type], - 'build_mode': 'release', - 'dry_run': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'invalid_architecture', - 'target_os': 'android', - 'version': HookOutputImpl.latestVersion.toString(), - }; - expect( - () => LinkConfigImpl.fromJson(config), - throwsFormatException, - ); - }); -} diff --git a/pkgs/native_assets_cli/test/validator/validator_test.dart b/pkgs/native_assets_cli/test/validator/validator_test.dart index e37ab9de7..ba732ce20 100644 --- a/pkgs/native_assets_cli/test/validator/validator_test.dart +++ b/pkgs/native_assets_cli/test/validator/validator_test.dart @@ -29,35 +29,92 @@ void main() { await Directory.fromUri(tempUri).delete(recursive: true); }); + BuildConfig makeCodeBuildConfig( + {LinkModePreference linkModePreference = LinkModePreference.dynamic}) { + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + supportedAssetTypes: [CodeAsset.type], + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outDirSharedUri, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + targetIOSSdk: IOSSdk.iPhoneOS, + linkModePreference: linkModePreference, + ); + return BuildConfig(configBuilder.json); + } + + LinkConfig makeCodeLinkConfig() { + final configBuilder = LinkConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + supportedAssetTypes: [CodeAsset.type], + ) + ..setupLinkConfig(assets: []) + ..setupLinkRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outDirSharedUri, + recordedUsesFile: null, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + targetIOSSdk: IOSSdk.iPhoneOS, + linkModePreference: LinkModePreference.dynamic, + ); + return LinkConfig(configBuilder.json); + } + + BuildConfig makeDataBuildConfig() { + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + supportedAssetTypes: [DataAsset.type]) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outDirSharedUri, + ); + return BuildConfig(configBuilder.json); + } + test('linking not enabled', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeCodeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.codeAssets.add( + outputBuilder.codeAssets.add( CodeAsset( package: config.packageName, name: 'foo.dart', file: assetFile.uri, linkMode: DynamicLoadingBundled(), os: config.targetOS, - architecture: config.targetArchitecture, + architecture: config.codeConfig.targetArchitecture, ), linkInPackage: 'bar', ); - final errors = await validateBuildOutput(config, output); + final errors = + await validateBuildOutput(config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains('linkingEnabled is false')), @@ -65,28 +122,17 @@ void main() { }); test('supported asset type', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeCodeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.dataAssets.add(DataAsset( + outputBuilder.dataAssets.add(DataAsset( package: config.packageName, name: 'foo.txt', file: assetFile.uri, )); - final errors = await validateBuildOutput(config, output); + final errors = + await validateBuildOutput(config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains('"data" is not a supported asset type')), @@ -94,27 +140,16 @@ void main() { }); test('file exists', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [DataAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeCodeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); - output.dataAssets.add(DataAsset( + outputBuilder.dataAssets.add(DataAsset( package: config.packageName, name: 'foo.txt', file: assetFile.uri, )); - final errors = await validateDataAssetBuildOutput(config, output); + final errors = await validateDataAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains('which does not exist')), @@ -122,28 +157,17 @@ void main() { }); test('file not set', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); - output.codeAssets.add(CodeAsset( + final config = makeCodeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); + outputBuilder.codeAssets.add(CodeAsset( package: config.packageName, name: 'foo.dylib', - architecture: config.targetArchitecture, + architecture: config.codeConfig.targetArchitecture, os: config.targetOS, linkMode: DynamicLoadingBundled(), )); - final errors = await validateCodeAssetBuildOutput(config, output); + final errors = await validateCodeAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains('has no file')), @@ -155,33 +179,23 @@ void main() { (LinkModePreference.dynamic, StaticLinking()), ]) { test('native code asset wrong linking $linkModePreference', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: linkModePreference, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = + makeCodeBuildConfig(linkModePreference: linkModePreference); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.codeAssets.add( + outputBuilder.codeAssets.add( CodeAsset( package: config.packageName, name: 'foo.dart', file: assetFile.uri, linkMode: linkMode, os: config.targetOS, - architecture: config.targetArchitecture, + architecture: config.codeConfig.targetArchitecture, ), ); - final errors = await validateCodeAssetBuildOutput(config, output); + final errors = await validateCodeAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains( @@ -192,23 +206,11 @@ void main() { } test('native code wrong architecture', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeCodeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.codeAssets.add( + outputBuilder.codeAssets.add( CodeAsset( package: config.packageName, name: 'foo.dart', @@ -218,7 +220,8 @@ void main() { architecture: Architecture.x64, ), ); - final errors = await validateCodeAssetBuildOutput(config, output); + final errors = await validateCodeAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains( @@ -228,23 +231,11 @@ void main() { }); test('native code no architecture', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeCodeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.codeAssets.add( + outputBuilder.codeAssets.add( CodeAsset( package: config.packageName, name: 'foo.dart', @@ -253,7 +244,8 @@ void main() { os: config.targetOS, ), ); - final errors = await validateCodeAssetBuildOutput(config, output); + final errors = await validateCodeAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains( @@ -263,33 +255,22 @@ void main() { }); test('native code asset wrong os', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeCodeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.codeAssets.add( + outputBuilder.codeAssets.add( CodeAsset( package: config.packageName, name: 'foo.dart', file: assetFile.uri, linkMode: DynamicLoadingBundled(), os: OS.windows, - architecture: config.targetArchitecture, + architecture: config.codeConfig.targetArchitecture, ), ); - final errors = await validateCodeAssetBuildOutput(config, output); + final errors = await validateCodeAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains( @@ -299,28 +280,17 @@ void main() { }); test('asset id in wrong package', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [DataAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeDataBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.dataAssets.add(DataAsset( + outputBuilder.dataAssets.add(DataAsset( package: 'different_package', name: 'foo.txt', file: assetFile.uri, )); - final errors = await validateDataAssetBuildOutput(config, output); + final errors = await validateDataAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains('Data asset must have package name my_package')), @@ -328,23 +298,11 @@ void main() { }); test('duplicate asset id', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [DataAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeDataBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.dataAssets.addAll([ + outputBuilder.dataAssets.addAll([ DataAsset( package: config.packageName, name: 'foo.txt', @@ -356,7 +314,8 @@ void main() { file: assetFile.uri, ), ]); - final errors = await validateDataAssetBuildOutput(config, output); + final errors = await validateDataAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains('More than one')), @@ -364,28 +323,17 @@ void main() { }); test('link hook validation', () async { - final config = LinkConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - assets: [], - ); - final output = LinkOutput(); + final config = makeCodeLinkConfig(); + final outputBuilder = LinkOutputBuilder(); final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); await assetFile.writeAsBytes([1, 2, 3]); - output.dataAssets.add(DataAsset( + outputBuilder.dataAssets.add(DataAsset( package: config.packageName, name: 'foo.txt', file: assetFile.uri, )); - final errors = await validateLinkOutput(config, output); + final errors = + await validateLinkOutput(config, LinkOutput(outputBuilder.json)); expect( errors, contains(contains('"data" is not a supported asset type')), @@ -393,31 +341,19 @@ void main() { }); test('duplicate dylib name', () async { - final config = BuildConfig.build( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - packageName: packageName, - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - supportedAssetTypes: [CodeAsset.type], - linkingEnabled: false, - ); - final output = BuildOutput(); + final config = makeCodeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); final fileName = config.targetOS.dylibFileName('foo'); final assetFile = File.fromUri(outDirUri.resolve(fileName)); await assetFile.writeAsBytes([1, 2, 3]); - output.codeAssets.addAll([ + outputBuilder.codeAssets.addAll([ CodeAsset( package: config.packageName, name: 'src/foo.dart', file: assetFile.uri, linkMode: DynamicLoadingBundled(), os: config.targetOS, - architecture: config.targetArchitecture, + architecture: config.codeConfig.targetArchitecture, ), CodeAsset( package: config.packageName, @@ -425,10 +361,11 @@ void main() { file: assetFile.uri, linkMode: DynamicLoadingBundled(), os: config.targetOS, - architecture: config.targetArchitecture, + architecture: config.codeConfig.targetArchitecture, ), ]); - final errors = await validateCodeAssetBuildOutput(config, output); + final errors = await validateCodeAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); expect( errors, contains(contains('Duplicate dynamic library file name')), diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart index 34c28ae1e..2468589cd 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart @@ -101,7 +101,7 @@ class CBuilder extends CTool implements Builder { @override Future run({ required BuildConfig config, - required BuildOutput output, + required BuildOutputBuilder output, required Logger? logger, String? linkInPackage, }) async { @@ -113,7 +113,7 @@ class CBuilder extends CTool implements Builder { final packageRoot = config.packageRoot; await Directory.fromUri(outDir).create(recursive: true); final linkMode = - getLinkMode(linkModePreference ?? config.linkModePreference); + getLinkMode(linkModePreference ?? config.codeConfig.linkModePreference); final libUri = outDir.resolve(config.targetOS.libraryFileName(name, linkMode)); final exeUri = outDir.resolve(config.targetOS.executableFileName(name)); @@ -132,6 +132,7 @@ class CBuilder extends CTool implements Builder { if (!config.dryRun) { final task = RunCBuilder( config: config, + codeConfig: config.codeConfig, logger: logger, sources: sources, includes: includes, @@ -169,7 +170,8 @@ class CBuilder extends CTool implements Builder { file: libUri, linkMode: linkMode, os: config.targetOS, - architecture: config.dryRun ? null : config.targetArchitecture, + architecture: + config.dryRun ? null : config.codeConfig.targetArchitecture, ), linkInPackage: linkInPackage, ); diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart index 3ac153901..55c5ef997 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart @@ -44,7 +44,7 @@ class CLinker extends CTool implements Linker { @override Future run({ required LinkConfig config, - required LinkOutput output, + required LinkOutputBuilder output, required Logger? logger, }) async { if (OS.current != OS.linux || config.targetOS != OS.linux) { @@ -55,7 +55,7 @@ class CLinker extends CTool implements Linker { final packageRoot = config.packageRoot; await Directory.fromUri(outDir).create(recursive: true); final linkMode = - getLinkMode(linkModePreference ?? config.linkModePreference); + getLinkMode(linkModePreference ?? config.codeConfig.linkModePreference); final libUri = outDir.resolve(config.targetOS.libraryFileName(name, linkMode)); final sources = [ @@ -66,55 +66,50 @@ class CLinker extends CTool implements Linker { for (final directory in this.includes) packageRoot.resolveUri(Uri.file(directory)), ]; - if (!config.dryRun) { - final task = RunCBuilder( - config: config, - linkerOptions: linkerOptions, - logger: logger, - sources: sources, - includes: includes, - frameworks: frameworks, - dynamicLibrary: linkMode == DynamicLoadingBundled() ? libUri : null, - staticLibrary: linkMode == StaticLinking() ? libUri : null, - // ignore: invalid_use_of_visible_for_testing_member - installName: installName, - flags: flags, - defines: defines, - pic: pic, - std: std, - language: language, - cppLinkStdLib: cppLinkStdLib, - ); - await task.run(); - } + final task = RunCBuilder( + config: config, + codeConfig: config.codeConfig, + linkerOptions: linkerOptions, + logger: logger, + sources: sources, + includes: includes, + frameworks: frameworks, + dynamicLibrary: linkMode == DynamicLoadingBundled() ? libUri : null, + staticLibrary: linkMode == StaticLinking() ? libUri : null, + // ignore: invalid_use_of_visible_for_testing_member + installName: installName, + flags: flags, + defines: defines, + pic: pic, + std: std, + language: language, + cppLinkStdLib: cppLinkStdLib, + ); + await task.run(); if (assetName != null) { - output.codeAssets.add( - CodeAsset( - package: config.packageName, - name: assetName!, - file: libUri, - linkMode: linkMode, - os: config.targetOS, - architecture: config.dryRun ? null : config.targetArchitecture, - ), - ); + output.codeAssets.add(CodeAsset( + package: config.packageName, + name: assetName!, + file: libUri, + linkMode: linkMode, + os: config.targetOS, + architecture: config.codeConfig.targetArchitecture, + )); } - if (!config.dryRun) { - final includeFiles = await Stream.fromIterable(includes) - .asyncExpand( - (include) => Directory(include.toFilePath()) - .list(recursive: true) - .where((entry) => entry is File) - .map((file) => file.uri), - ) - .toList(); + final includeFiles = await Stream.fromIterable(includes) + .asyncExpand( + (include) => Directory(include.toFilePath()) + .list(recursive: true) + .where((entry) => entry is File) + .map((file) => file.uri), + ) + .toList(); - output.addDependencies({ - // Note: We use a Set here to deduplicate the dependencies. - ...sources, - ...includeFiles, - }); - } + output.addDependencies({ + // Note: We use a Set here to deduplicate the dependencies. + ...sources, + ...includeFiles, + }); } } diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart index b33a12199..392d6324f 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart @@ -21,12 +21,14 @@ import '../tool/tool_instance.dart'; // For example use Clang or MSVC on Windows. class CompilerResolver { final HookConfig hookConfig; + final CodeConfig codeConfig; final Logger? logger; final OS hostOS; final Architecture hostArchitecture; CompilerResolver({ required this.hookConfig, + required this.codeConfig, required this.logger, OS? hostOS, // Only visible for testing. Architecture? hostArchitecture, // Only visible for testing. @@ -48,7 +50,7 @@ class CompilerResolver { } final targetOS = hookConfig.targetOS; - final targetArchitecture = hookConfig.targetArchitecture; + final targetArchitecture = codeConfig.targetArchitecture; final errorMessage = "No tools configured on host '${hostOS}_$hostArchitecture' with target " "'${targetOS}_$targetArchitecture'."; @@ -59,7 +61,7 @@ class CompilerResolver { /// Select the right compiler for cross compiling to the specified target. Tool? _selectCompiler() { final targetOS = hookConfig.targetOS; - final targetArch = hookConfig.targetArchitecture; + final targetArch = codeConfig.targetArchitecture; // TODO(dacoharkes): Support falling back on other tools. if (targetArch == hostArchitecture && @@ -99,7 +101,7 @@ class CompilerResolver { } Future _tryLoadCompilerFromConfig() async { - final configCcUri = hookConfig.cCompiler.compiler; + final configCcUri = codeConfig.cCompiler.compiler; if (configCcUri != null) { assert(await File.fromUri(configCcUri).exists()); logger?.finer('Using compiler ${configCcUri.toFilePath()} ' @@ -134,7 +136,7 @@ class CompilerResolver { } final targetOS = hookConfig.targetOS; - final targetArchitecture = hookConfig.targetArchitecture; + final targetArchitecture = codeConfig.targetArchitecture; final errorMessage = "No tools configured on host '${hostOS}_$hostArchitecture' with target " "'${targetOS}_$targetArchitecture'."; @@ -145,7 +147,7 @@ class CompilerResolver { /// Select the right archiver for cross compiling to the specified target. Tool? _selectArchiver() { final targetOS = hookConfig.targetOS; - final targetArchitecture = hookConfig.targetArchitecture; + final targetArchitecture = codeConfig.targetArchitecture; // TODO(dacoharkes): Support falling back on other tools. if (targetArchitecture == hostArchitecture && @@ -184,7 +186,7 @@ class CompilerResolver { } Future _tryLoadArchiverFromConfig() async { - final configArUri = hookConfig.cCompiler.archiver; + final configArUri = codeConfig.cCompiler.archiver; if (configArUri != null) { assert(await File.fromUri(configArUri).exists()); logger?.finer('Using archiver ${configArUri.toFilePath()} ' @@ -197,7 +199,7 @@ class CompilerResolver { } Future toolchainEnvironmentScript(ToolInstance compiler) async { - final fromConfig = hookConfig.cCompiler.envScript; + final fromConfig = codeConfig.cCompiler.envScript; if (fromConfig != null) { logger?.fine('Using envScript from config: $fromConfig'); return fromConfig; @@ -211,7 +213,7 @@ class CompilerResolver { } List? toolchainEnvironmentScriptArguments() { - final fromConfig = hookConfig.cCompiler.envScriptArgs; + final fromConfig = codeConfig.cCompiler.envScriptArgs; if (fromConfig != null) { logger?.fine('Using envScriptArgs from config: $fromConfig'); return fromConfig; @@ -223,7 +225,7 @@ class CompilerResolver { Future resolveLinker() async { final targetOS = hookConfig.targetOS; - final targetArchitecture = hookConfig.targetArchitecture; + final targetArchitecture = codeConfig.targetArchitecture; // First, check if the launcher provided a direct path to the compiler. var result = await _tryLoadLinkerFromConfig(); @@ -245,7 +247,7 @@ class CompilerResolver { } Future _tryLoadLinkerFromConfig() async { - final configLdUri = hookConfig.cCompiler.linker; + final configLdUri = codeConfig.cCompiler.linker; if (configLdUri != null) { assert(await File.fromUri(configLdUri).exists()); logger?.finer('Using linker ${configLdUri.toFilePath()} ' @@ -260,7 +262,7 @@ class CompilerResolver { /// Select the right compiler for cross compiling to the specified target. Tool? _selectLinker() { final targetOS = hookConfig.targetOS; - final targetArchitecture = hookConfig.targetArchitecture; + final targetArchitecture = codeConfig.targetArchitecture; if (targetOS == OS.macOS || targetOS == OS.iOS) return appleLd; if (targetOS == OS.android) return androidNdkLld; diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart index 3b31c92c4..4cf0c99d3 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart @@ -22,6 +22,7 @@ class RunCBuilder { /// should be run. final LinkerOptions? linkerOptions; final HookConfig config; + final CodeConfig codeConfig; final Logger? logger; final List sources; final List includes; @@ -47,6 +48,7 @@ class RunCBuilder { RunCBuilder({ required this.config, + required this.codeConfig, this.linkerOptions, this.logger, this.sources = const [], @@ -76,7 +78,8 @@ class RunCBuilder { } } - late final _resolver = CompilerResolver(hookConfig: config, logger: logger); + late final _resolver = CompilerResolver( + hookConfig: config, codeConfig: codeConfig, logger: logger); Future compiler() async => await _resolver.resolveCompiler(); @@ -130,7 +133,7 @@ class RunCBuilder { final IOSSdk? targetIosSdk; if (config.targetOS == OS.iOS) { - targetIosSdk = config.targetIOSSdk; + targetIosSdk = codeConfig.targetIOSSdk; } else { targetIosSdk = null; } @@ -141,18 +144,18 @@ class RunCBuilder { final int? targetAndroidNdkApi; if (config.targetOS == OS.android) { final minimumApi = - config.targetArchitecture == Architecture.riscv64 ? 35 : 21; - targetAndroidNdkApi = max(config.targetAndroidNdkApi!, minimumApi); + codeConfig.targetArchitecture == Architecture.riscv64 ? 35 : 21; + targetAndroidNdkApi = max(codeConfig.targetAndroidNdkApi!, minimumApi); } else { targetAndroidNdkApi = null; } final targetIOSVersion = - config.targetOS == OS.iOS ? config.targetIOSVersion : null; + config.targetOS == OS.iOS ? codeConfig.targetIOSVersion : null; final targetMacOSVersion = - config.targetOS == OS.macOS ? config.targetMacOSVersion : null; + config.targetOS == OS.macOS ? codeConfig.targetMacOSVersion : null; - final architecture = config.targetArchitecture; + final architecture = codeConfig.targetArchitecture; final sourceFiles = sources.map((e) => e.toFilePath()).toList(); final objectFiles = []; if (staticLibrary != null) { diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_build_failure_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_build_failure_test.dart index 1d9b85f37..ea920c0f7 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_build_failure_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_build_failure_test.dart @@ -10,7 +10,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; @@ -30,20 +30,30 @@ void main() { await File.fromUri(addCUri).writeAsString(addCBrokenContents); const name = 'add'; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - linkModePreference: LinkModePreference.dynamic, - buildMode: BuildMode.release, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( sources: [addCUri.toFilePath()], diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_android_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_android_test.dart index 12c0cd713..dcbd0e236 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_android_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_android_test.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; @@ -109,23 +109,33 @@ Future buildLib( final tempUriShared = tempUri.resolve('shared/'); await Directory.fromUri(tempUriShared).create(); - - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.android, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: targetArchitecture, + cCompilerConfig: cCompiler, + targetAndroidNdkApi: androidNdkApi, + linkModePreference: linkMode == DynamicLoadingBundled() + ? LinkModePreference.dynamic + : LinkModePreference.static, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUriShared, - packageName: name, - packageRoot: tempUri, - targetArchitecture: targetArchitecture, - targetOS: OS.android, - targetAndroidNdkApi: androidNdkApi, - buildMode: BuildMode.release, - linkModePreference: linkMode == DynamicLoadingBundled() - ? LinkModePreference.dynamic - : LinkModePreference.static, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_ios_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_ios_test.dart index 34afa5f47..06577cdd3 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_ios_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_ios_test.dart @@ -10,7 +10,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; @@ -63,22 +63,34 @@ void main() { 'test/cbuilder/testfiles/add_objective_c/src/add.m'), Language() => throw UnimplementedError(), }; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: target, + linkModePreference: linkMode == DynamicLoadingBundled() + ? LinkModePreference.dynamic + : LinkModePreference.static, + targetIOSSdk: targetIOSSdk, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: target, - targetOS: OS.iOS, - buildMode: BuildMode.release, - linkModePreference: linkMode == DynamicLoadingBundled() - ? LinkModePreference.dynamic - : LinkModePreference.static, - targetIOSSdk: targetIOSSdk, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, @@ -209,23 +221,34 @@ Future buildLib( final addCUri = packageUri.resolve('test/cbuilder/testfiles/add/src/add.c'); const name = 'add'; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: targetArchitecture, + linkModePreference: linkMode == DynamicLoadingBundled() + ? LinkModePreference.dynamic + : LinkModePreference.static, + targetIOSSdk: IOSSdk.iPhoneOS, + targetIOSVersion: targetIOSVersion, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: targetArchitecture, - targetOS: OS.iOS, - targetIOSSdk: IOSSdk.iPhoneOS, - targetIOSVersion: targetIOSVersion, - buildMode: BuildMode.release, - linkModePreference: linkMode == DynamicLoadingBundled() - ? LinkModePreference.dynamic - : LinkModePreference.static, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_linux_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_linux_host_test.dart index c659f2f7a..63e3aaeec 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_linux_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_linux_host_test.dart @@ -7,7 +7,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; @@ -36,21 +36,32 @@ void main() { packageUri.resolve('test/cbuilder/testfiles/add/src/add.c'); const name = 'add'; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.linux, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: target, + linkModePreference: linkMode == DynamicLoadingBundled() + ? LinkModePreference.dynamic + : LinkModePreference.static, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: target, - targetOS: OS.linux, - buildMode: BuildMode.release, - linkModePreference: linkMode == DynamicLoadingBundled() - ? LinkModePreference.dynamic - : LinkModePreference.static, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart index a24bd5c7b..9a92e3649 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart @@ -10,7 +10,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; @@ -49,21 +49,31 @@ void main() { }; const name = 'add'; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.macOS, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: target, + linkModePreference: linkMode == DynamicLoadingBundled() + ? LinkModePreference.dynamic + : LinkModePreference.static, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: target, - targetOS: OS.macOS, - buildMode: BuildMode.release, - linkModePreference: linkMode == DynamicLoadingBundled() - ? LinkModePreference.dynamic - : LinkModePreference.static, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, @@ -139,22 +149,33 @@ Future buildLib( final addCUri = packageUri.resolve('test/cbuilder/testfiles/add/src/add.c'); const name = 'add'; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: targetArchitecture, + linkModePreference: linkMode == DynamicLoadingBundled() + ? LinkModePreference.dynamic + : LinkModePreference.static, + targetMacOSVersion: targetMacOSVersion, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: targetArchitecture, - targetOS: OS.macOS, - targetMacOSVersion: targetMacOSVersion, - buildMode: BuildMode.release, - linkModePreference: linkMode == DynamicLoadingBundled() - ? LinkModePreference.dynamic - : LinkModePreference.static, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart index 9fe63c0ee..5cba2fba3 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart @@ -10,7 +10,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/native_toolchain/msvc.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; @@ -55,21 +55,32 @@ void main() { packageUri.resolve('test/cbuilder/testfiles/add/src/add.c'); const name = 'add'; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.windows, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: target, + linkModePreference: linkMode == DynamicLoadingBundled() + ? LinkModePreference.dynamic + : LinkModePreference.static, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetOS: OS.windows, - targetArchitecture: target, - buildMode: BuildMode.release, - linkModePreference: linkMode == DynamicLoadingBundled() - ? LinkModePreference.dynamic - : LinkModePreference.static, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart index faa0c7ece..3482144d8 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart @@ -11,7 +11,7 @@ library; import 'dart:ffi'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; @@ -44,21 +44,32 @@ void main() { final logMessages = []; final logger = createCapturingLogger(logMessages); - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: buildMode, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + // Ignored by executables. + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - buildMode: buildMode, - // Ignored by executables. - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); + final cbuilder = CBuilder.executable( name: name, sources: [helloWorldCUri.toFilePath()], @@ -115,31 +126,29 @@ void main() { final logMessages = []; final logger = createCapturingLogger(logMessages); - final buildConfig = dryRun - ? BuildConfig.dryRun( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: tempUri, - outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetOS: OS.current, - linkModePreference: LinkModePreference.dynamic, - linkingEnabled: false, - ) - : BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: tempUri, - outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, - ); - final buildOutput = BuildOutput(); + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: dryRun, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: dryRun ? null : cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( + outputDirectory: tempUri, + outputDirectoryShared: tempUri2, + ); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( sources: [addCUri.toFilePath()], @@ -218,21 +227,30 @@ void main() { final logMessages = []; final logger = createCapturingLogger(logMessages); - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + // Ignored by executables. + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - buildMode: BuildMode.release, - // Ignored by executables. - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final flag = switch (buildConfig.targetOS) { OS.windows => '/DFOO=USER_FLAG', @@ -276,20 +294,30 @@ void main() { packageUri.resolve('test/cbuilder/testfiles/includes/src/includes.c'); const name = 'includes'; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + // Ignored by executables. + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutputBuilder = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, @@ -299,10 +327,11 @@ void main() { ); await cbuilder.run( config: buildConfig, - output: buildOutput, + output: buildOutputBuilder, logger: logger, ); + final buildOutput = BuildOutput(buildOutputBuilder.json); expect(buildOutput.dependencies, contains(includesHUri)); final dylibUri = tempUri.resolve(OS.current.dylibFileName(name)); @@ -321,20 +350,30 @@ void main() { final logMessages = []; final logger = createCapturingLogger(logMessages); - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + // Ignored by executables. + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final stdFlag = switch (buildConfig.targetOS) { OS.windows => '/std:$std', @@ -379,21 +418,30 @@ void main() { final logMessages = []; final logger = createCapturingLogger(logMessages); - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], - buildMode: BuildMode.release, + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + // Ignored by executables. + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - // Ignored by executables. - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final defaultStdLibLinkFlag = switch (buildConfig.targetOS) { OS.windows => null, @@ -443,21 +491,31 @@ void main() { final logMessages = []; final logger = createCapturingLogger(logMessages); - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], - buildMode: BuildMode.release, + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + // Ignored by executables. + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - // Ignored by executables. - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); + final cbuilder = CBuilder.executable( name: name, sources: [helloWorldCppUri.toFilePath()], @@ -514,21 +572,31 @@ Future testDefines({ } const name = 'defines'; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: buildMode, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + // Ignored by executables. + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - buildMode: buildMode, - // Ignored by executables. - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); + final cbuilder = CBuilder.executable( name: name, sources: [definesCUri.toFilePath()], diff --git a/pkgs/native_toolchain_c/test/cbuilder/compiler_resolver_test.dart b/pkgs/native_toolchain_c/test/cbuilder/compiler_resolver_test.dart index 4f1b58e98..6c13c5257 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/compiler_resolver_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/compiler_resolver_test.dart @@ -9,7 +9,7 @@ library; import 'package:collection/collection.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/src/cbuilder/compiler_resolver.dart'; import 'package:native_toolchain_c/src/native_toolchain/apple_clang.dart'; import 'package:native_toolchain_c/src/native_toolchain/clang.dart'; @@ -41,48 +41,74 @@ void main() { final envScript = [ ...await msvc.vcvars64.defaultResolver!.resolve(logger: logger) ].firstOrNull?.uri; - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: 'dummy', + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: CCompilerConfig( + archiver: ar, + compiler: cc, + linker: ld, + envScript: envScript, + ), + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: 'dummy', - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - cCompiler: CCompilerConfig( - archiver: ar, - compiler: cc, - linker: ld, - envScript: envScript, - ), - linkingEnabled: false, ); - final resolver = CompilerResolver(hookConfig: buildConfig, logger: logger); + final buildConfig = BuildConfig(buildConfigBuilder.json); + final resolver = CompilerResolver( + hookConfig: buildConfig, + codeConfig: buildConfig.codeConfig, + logger: logger); final compiler = await resolver.resolveCompiler(); final archiver = await resolver.resolveArchiver(); - expect(compiler.uri, buildConfig.cCompiler.compiler); - expect(archiver.uri, buildConfig.cCompiler.archiver); + expect(compiler.uri, buildConfig.codeConfig.cCompiler.compiler); + expect(archiver.uri, buildConfig.codeConfig.cCompiler.archiver); }); test('No compiler found', () async { final tempUri = await tempDirForTest(); final tempUri2 = await tempDirForTest(); - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: tempUri, + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: 'dummy', + packageRoot: tempUri, + targetOS: OS.windows, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectoryShared: tempUri2, - packageName: 'dummy', - packageRoot: tempUri, - targetArchitecture: Architecture.arm64, - targetOS: OS.windows, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - linkingEnabled: false, + outputDirectory: tempUri, ); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final resolver = CompilerResolver( hookConfig: buildConfig, + codeConfig: buildConfig.codeConfig, logger: logger, hostOS: OS.android, // This is never a host. hostArchitecture: Architecture.arm64, // This is never a host. diff --git a/pkgs/native_toolchain_c/test/cbuilder/objective_c_test.dart b/pkgs/native_toolchain_c/test/cbuilder/objective_c_test.dart index 4d76aaf14..737a3e941 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/objective_c_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/objective_c_test.dart @@ -11,7 +11,7 @@ library; import 'dart:ffi'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; @@ -36,20 +36,30 @@ void main() { final logMessages = []; final logger = createCapturingLogger(logMessages); - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], - buildMode: BuildMode.release, + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: OS.current, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.current, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: Architecture.current, - targetOS: OS.current, - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutput = BuildOutputBuilder(); final cbuilder = CBuilder.library( name: name, diff --git a/pkgs/native_toolchain_c/test/clinker/build_testfiles.dart b/pkgs/native_toolchain_c/test/clinker/build_testfiles.dart index 57f37bbda..39c22e4fe 100644 --- a/pkgs/native_toolchain_c/test/clinker/build_testfiles.dart +++ b/pkgs/native_toolchain_c/test/clinker/build_testfiles.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import '../helpers.dart'; @@ -26,20 +26,31 @@ Future buildTestArchive( final logMessages = []; final logger = createCapturingLogger(logMessages); - final buildConfig = BuildConfig.build( - supportedAssetTypes: [CodeAsset.type], + final buildConfigBuilder = BuildConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: name, + packageRoot: tempUri, + targetOS: os, + buildMode: BuildMode.release, + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupCodeConfig( + targetArchitecture: architecture, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + buildConfigBuilder.setupBuildRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: name, - packageRoot: tempUri, - targetArchitecture: architecture, - targetOS: os, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - cCompiler: cCompiler, - linkingEnabled: false, ); - final buildOutput = BuildOutput(); + + final buildConfig = BuildConfig(buildConfigBuilder.json); + final buildOutputBuilder = BuildOutputBuilder(); + final cbuilder = CBuilder.library( name: name, assetName: '', @@ -48,9 +59,10 @@ Future buildTestArchive( ); await cbuilder.run( config: buildConfig, - output: buildOutput, + output: buildOutputBuilder, logger: logger, ); - return buildOutput.codeAssets.all.first.file!; + final buildOutput = BuildOutput(buildOutputBuilder.json); + return buildOutput.codeAssets.first.file!; } diff --git a/pkgs/native_toolchain_c/test/clinker/objects_test.dart b/pkgs/native_toolchain_c/test/clinker/objects_test.dart index 1f9654732..3e5300e86 100644 --- a/pkgs/native_toolchain_c/test/clinker/objects_test.dart +++ b/pkgs/native_toolchain_c/test/clinker/objects_test.dart @@ -9,7 +9,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; @@ -27,25 +27,36 @@ Future main() async { const name = 'mylibname'; test('link two objects', () async { - final linkOutput = LinkOutput(); final tempUri = await tempDirForTest(); final tempUri2 = await tempDirForTest(); final uri = await buildTestArchive(tempUri, tempUri2, os, architecture); - final linkConfig = LinkConfig.build( - supportedAssetTypes: [CodeAsset.type], + + final linkConfigBuilder = LinkConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: 'testpackage', + packageRoot: tempUri, + targetOS: os, + buildMode: BuildMode.debug, + ) + ..setupLinkConfig( + assets: [], + ) + ..setupCodeConfig( + targetArchitecture: architecture, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + linkConfigBuilder.setupLinkRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: 'testpackage', - packageRoot: tempUri, - targetArchitecture: architecture, - targetOS: os, - buildMode: BuildMode.debug, - linkModePreference: LinkModePreference.dynamic, - assets: [], - cCompiler: cCompiler, + recordedUsesFile: null, ); - printOnFailure(linkConfig.cCompiler.toString()); + final linkConfig = LinkConfig(linkConfigBuilder.json); + final linkOutput = LinkOutputBuilder(); + + printOnFailure(linkConfig.codeConfig.cCompiler.toString()); printOnFailure(Platform.environment.keys.toList().toString()); await CLinker.library( name: name, @@ -58,8 +69,9 @@ Future main() async { logger: logger, ); - expect(linkOutput.codeAssets.all, hasLength(1)); - final asset = linkOutput.codeAssets.all.first; + final codeAssets = LinkOutput(linkOutput.json).codeAssets; + expect(codeAssets, hasLength(1)); + final asset = codeAssets.first; expect(asset, isA()); await expectSymbols( asset: asset, diff --git a/pkgs/native_toolchain_c/test/clinker/throws_test.dart b/pkgs/native_toolchain_c/test/clinker/throws_test.dart index 48e5838aa..fc88a5d39 100644 --- a/pkgs/native_toolchain_c/test/clinker/throws_test.dart +++ b/pkgs/native_toolchain_c/test/clinker/throws_test.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; @@ -23,25 +23,37 @@ Future main() async { final tempUri = await tempDirForTest(); final tempUri2 = await tempDirForTest(); + final linkConfigBuilder = LinkConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: 'testpackage', + packageRoot: tempUri, + targetOS: os, + buildMode: BuildMode.debug, + ) + ..setupLinkConfig( + assets: [], + ) + ..setupCodeConfig( + targetArchitecture: Architecture.x64, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + linkConfigBuilder.setupLinkRunConfig( + outputDirectoryShared: tempUri2, + outputDirectory: tempUri, + recordedUsesFile: null, + ); + final linkHookConfig = LinkConfig(linkConfigBuilder.json); + final cLinker = CLinker.library( name: 'mylibname', linkerOptions: LinkerOptions.manual(), ); await expectLater( () => cLinker.run( - config: LinkConfig.build( - supportedAssetTypes: [CodeAsset.type], - outputDirectory: tempUri, - outputDirectoryShared: tempUri2, - packageName: 'testpackage', - packageRoot: tempUri, - targetArchitecture: Architecture.x64, - targetOS: os, - buildMode: BuildMode.debug, - linkModePreference: LinkModePreference.dynamic, - assets: [], - ), - output: LinkOutput(), + config: linkHookConfig, + output: LinkOutputBuilder(), logger: logger, ), throwsUnsupportedError, diff --git a/pkgs/native_toolchain_c/test/clinker/treeshake_helper.dart b/pkgs/native_toolchain_c/test/clinker/treeshake_helper.dart index 6bf1b5d71..8a746e516 100644 --- a/pkgs/native_toolchain_c/test/clinker/treeshake_helper.dart +++ b/pkgs/native_toolchain_c/test/clinker/treeshake_helper.dart @@ -9,7 +9,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; @@ -62,30 +62,41 @@ Future runTests(List architectures) async { architecture, ); - final linkOutput = LinkOutput(); - - final config = LinkConfig.build( - supportedAssetTypes: [CodeAsset.type], + final linkConfigBuilder = LinkConfigBuilder() + ..setupHookConfig( + supportedAssetTypes: [CodeAsset.type], + packageName: 'testpackage', + packageRoot: tempUri, + targetOS: os, + buildMode: BuildMode.release, + //outputDirectoryShared: tempUri2, + ) + ..setupLinkConfig( + assets: [], + ) + ..setupCodeConfig( + targetArchitecture: architecture, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + ); + linkConfigBuilder.setupLinkRunConfig( outputDirectory: tempUri, outputDirectoryShared: tempUri2, - packageName: 'testpackage', - packageRoot: tempUri, - targetArchitecture: architecture, - targetOS: os, - buildMode: BuildMode.release, - linkModePreference: LinkModePreference.dynamic, - assets: [], - cCompiler: cCompiler, + recordedUsesFile: null, ); - printOnFailure(config.cCompiler.toString()); + final linkConfig = LinkConfig(linkConfigBuilder.json); + final linkOutputBuilder = LinkOutputBuilder(); + + printOnFailure(linkConfig.codeConfig.cCompiler.toString()); printOnFailure(Platform.environment.keys.toList().toString()); await clinker.linker([testArchive.toFilePath()]).run( - config: config, - output: linkOutput, + config: linkConfig, + output: linkOutputBuilder, logger: logger, ); - final asset = linkOutput.codeAssets.all.first; + final linkOutput = LinkOutput(linkOutputBuilder.json); + final asset = linkOutput.codeAssets.first; final filePath = asset.file!.toFilePath(); final machine = await readelfMachine(filePath); From 251a33445a21df21bd57615ac24deef2687579bb Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Fri, 11 Oct 2024 09:01:13 +0200 Subject: [PATCH 2/7] Fix some tests --- .../build_runner/concurrency_test_helper.dart | 2 + .../test/build_runner/helpers.dart | 38 +++++- .../lib/src/code_assets/code_asset.dart | 4 +- pkgs/native_assets_cli/lib/src/config.dart | 14 +- .../test/build_config_test.dart | 13 +- .../native_assets_cli/test/checksum_test.dart | 128 +++++++++--------- .../test/link_config_test.dart | 13 +- .../cbuilder_cross_macos_host_test.dart | 2 +- 8 files changed, 125 insertions(+), 89 deletions(-) diff --git a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart index 47c80ddba..8aa2746a5 100644 --- a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart +++ b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart @@ -6,6 +6,7 @@ import 'package:logging/logging.dart'; import 'package:native_assets_builder/native_assets_builder.dart'; import '../helpers.dart'; +import 'helpers.dart'; // Is invoked concurrently multiple times in separate processes. void main(List args) async { @@ -28,6 +29,7 @@ void main(List args) async { ..setupCodeConfig( targetArchitecture: Architecture.current, linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: dartCICompilerConfig, ), buildMode: BuildMode.release, targetOS: OS.current, diff --git a/pkgs/native_assets_builder/test/build_runner/helpers.dart b/pkgs/native_assets_builder/test/build_runner/helpers.dart index b40825943..640d8add7 100644 --- a/pkgs/native_assets_builder/test/build_runner/helpers.dart +++ b/pkgs/native_assets_builder/test/build_runner/helpers.dart @@ -57,7 +57,7 @@ Future build( ..setupCodeConfig( targetArchitecture: target?.architecture ?? Architecture.current, linkModePreference: linkModePreference, - cCompilerConfig: cCompilerConfig, + cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, targetIOSSdk: targetIOSSdk, targetIOSVersion: targetIOSVersion, targetMacOSVersion: targetMacOSVersion, @@ -115,7 +115,7 @@ Future link( ..setupCodeConfig( targetArchitecture: target?.architecture ?? Architecture.current, linkModePreference: linkModePreference, - cCompilerConfig: cCompilerConfig, + cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, targetIOSSdk: targetIOSSdk, targetIOSVersion: targetIOSVersion, targetMacOSVersion: targetMacOSVersion, @@ -171,7 +171,7 @@ Future<(BuildResult?, LinkResult?)> buildAndLink( ..setupCodeConfig( targetArchitecture: target?.architecture ?? Architecture.current, linkModePreference: linkModePreference, - cCompilerConfig: cCompilerConfig, + cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, targetIOSSdk: targetIOSSdk, targetIOSVersion: targetIOSVersion, targetMacOSVersion: targetMacOSVersion, @@ -303,3 +303,35 @@ Future expectSymbols({ ); } } + +final CCompilerConfig? dartCICompilerConfig = (() { + // Specifically for running our tests on Dart CI with the test runner, we + // recognize specific variables to setup the C Compiler configuration. + final env = Platform.environment; + final cc = env['DART_HOOK_TESTING_C_COMPILER__CC']; + final ar = env['DART_HOOK_TESTING_C_COMPILER__AR']; + final ld = env['DART_HOOK_TESTING_C_COMPILER__LD']; + final envScript = env['DART_HOOK_TESTING_C_COMPILER__ENV_SCRIPT']; + final envScriptArgs = + env['DART_HOOK_TESTING_C_COMPILER__ENV_SCRIPT_ARGUMENTS'] + ?.split(' ') + .map((arg) => arg.trim()) + .where((arg) => arg.isNotEmpty) + .toList(); + final hasEnvScriptArgs = envScriptArgs != null && envScriptArgs.isNotEmpty; + + if (cc != null || + ar != null || + ld != null || + envScript != null || + hasEnvScriptArgs) { + return CCompilerConfig( + archiver: ar != null ? Uri.file(ar) : null, + compiler: cc != null ? Uri.file(cc) : null, + envScript: envScript != null ? Uri.file(envScript) : null, + envScriptArgs: hasEnvScriptArgs ? envScriptArgs : null, + linker: ld != null ? Uri.file(ld) : null, + ); + } + return null; +})(); diff --git a/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart b/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart index c07b91fb7..399175643 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart @@ -289,8 +289,8 @@ class CodeConfig { config.json.string('link_mode_preference')), _targetArchitecture = (config is BuildConfig && config.dryRun) ? null - : Architecture.fromString( - config.json.string('target_architecture')), + : Architecture.fromString(config.json.string('target_architecture', + validValues: Architecture.values.map((a) => a.name))), cCompiler = (() { final cCompiler = CCompilerConfig( archiver: config.json.optionalPath('c_compiler.ar'), diff --git a/pkgs/native_assets_cli/lib/src/config.dart b/pkgs/native_assets_cli/lib/src/config.dart index 904b36eac..bb370c5ca 100644 --- a/pkgs/native_assets_cli/lib/src/config.dart +++ b/pkgs/native_assets_cli/lib/src/config.dart @@ -77,10 +77,10 @@ sealed class HookConfig { HookConfig(this.json) : version = switch (Version.parse(json.string(_versionKey))) { - final Version version => (version.major != currentVersion.major || - version < currentVersion) + final Version version => (version.major != latestVersion.major || + version < latestVersion) ? throw FormatException( - 'Only compatible versions with $currentVersion are supported ' + 'Only compatible versions with $latestVersion are supported ' '(was: $version).') : version, }, @@ -105,14 +105,11 @@ sealed class HookConfig { @override String toString() => const JsonEncoder.withIndent(' ').convert(json); - - // The latest supported config version. - static Version currentVersion = Version(3, 5, 0); } sealed class HookConfigBuilder { final Map json = { - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), }; void setupHookConfig({ @@ -536,3 +533,6 @@ class LinkOutputBuilder extends HookOutputBuilder { } } } + +// The latest supported config version. +final latestVersion = Version(1, 5, 0); diff --git a/pkgs/native_assets_cli/test/build_config_test.dart b/pkgs/native_assets_cli/test/build_config_test.dart index 85ebf0e6b..3011444b6 100644 --- a/pkgs/native_assets_cli/test/build_config_test.dart +++ b/pkgs/native_assets_cli/test/build_config_test.dart @@ -8,6 +8,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/src/config.dart' show latestVersion; import 'package:test/test.dart'; //XXX TODO @@ -108,7 +109,7 @@ void main() async { 'target_android_ndk_api': 30, 'target_architecture': 'arm64', 'target_os': 'android', - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), 'c_compiler.ar': fakeAr.toFilePath(), 'c_compiler.ld': fakeLd.toFilePath(), 'c_compiler.cc': fakeClang.toFilePath(), @@ -182,7 +183,7 @@ void main() async { 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), 'target_os': 'android', - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), }; expect(config.json, expectedConfigJson); @@ -232,7 +233,7 @@ void main() async { (e) => e is FormatException && e.message.contains(version) && - e.message.contains(HookConfig.currentVersion.toString()), + e.message.contains(latestVersion.toString()), )), ); }); @@ -251,7 +252,7 @@ void main() async { ); expect( () => BuildConfig({ - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), 'target_architecture': 'arm64', @@ -271,7 +272,7 @@ void main() async { ); expect( () => BuildConfig({ - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), 'out_dir': outDirUri.toFilePath(), 'out_dir_shared': outputDirectoryShared.toFilePath(), 'package_name': packageName, @@ -310,7 +311,7 @@ void main() async { 'target_architecture': 'invalid_architecture', 'target_os': 'android', 'supported_asset_types': [CodeAsset.type], - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), }; expect( () => BuildConfig(config), diff --git a/pkgs/native_assets_cli/test/checksum_test.dart b/pkgs/native_assets_cli/test/checksum_test.dart index 246066ade..680e6da2e 100644 --- a/pkgs/native_assets_cli/test/checksum_test.dart +++ b/pkgs/native_assets_cli/test/checksum_test.dart @@ -38,70 +38,70 @@ void main() { // If format or algorithm for checksumming changes we'd like to know (by // needing to update this list). expect(checksums, [ - '49daf3450cda2d6f703fd1c5615723e1', - '5b071ecc8b32a1dd7ae71cec893da765', - '42e0e9ef9b52243b2a033708c5614692', - '779e7bd31c6671c69c15bffe20b9b882', - 'e1684c0558449dc47dd6e95eed9c8f20', - '42264730ed1bac426fd9b0de85ca355a', - 'fae528a60605783f326c1e61af02a943', - '375be74dab1457c8ba637444654a4a3a', - '390e8e89b417572229bf7f2c02883a3c', - 'd2931555f8c5f3610b45012f63fafae4', - '423dc47a44ce262b6d1d30fd159752fe', - '1616bd24aa7745c19272cb7776c740d8', - '1dfafc3008d703fb5670cae22955e7f0', - '27c8a7891663bdea5791f0a4a0b00f0a', - '33628656d5ba5acff5ba6d672e6266e9', - '6a99fa1285cdbdf07e7f2f16dd9c124f', - '6d6fca403370aa7ea4ae309eb3e19272', - '09aadc73a263858f3b0724c3ca1c886a', - '920c1e3d286c746065652bfd2d740698', - 'cbf2c911f9d3e5b0d644b402d8feebd3', - 'ac36f6d4b530ddbd77d7c9fd93514bfc', - 'a77d9a81e1f66c43ba16743263516fc1', - '7619ec268bb1c4da8116db2605bd2ab8', - '3eaa505790a10afc93b4402799c735d2', - 'c9378ada5a069e0ea1f4906e6e981092', - '2915954b795f02d688269214b3db0cf7', - 'c6c895b2c738ff19eba67044f0dbbbd0', - '953a29fc8f4015a57fb44749dd576837', - '4c6c58417ab2e732e9b2952fedacce68', - '9cfb486089a705226ee8a138d14f7fd7', - '8a9fc2ebf5cc1fa39cd03179a5959fad', - 'b956d47a5613b89e09f00763fc7b30b6', - 'fe690851eb75c9566fbf2060f8b37df9', - 'f29ec64febd078bd188041ccb7d545f7', - '3f54f0ceca274275c71c4fa2ca3ef919', - '9896e8326e43a114ca1fa833a00f0e80', - '8f5c3abb4578159f37a3f585a4e52b62', - 'fd2e5b9cd4ccbe35a7b515f49b44a6f4', - '90d3dfc0dab4617da8b3b261c6d42ed6', - '4491024a82b1ae5545b3bb90f37c47bd', - '491e8c4549b80de2de7366f75deb6fb7', - 'bf8ce548a070836411efc4ffab36f00d', - '5562ecf90c8ea05f8cff98099a16c6bd', - '451b5c9be02a42cb5cf6359355241f6a', - '3b39694a45d1c427dbf24229ad88f969', - 'd4527aec8dc183f1f61819a414fe3a52', - '95ea9db54a39dfc3d7eecbf120b93ee0', - '2ac0ee9854562c6274749fdcc1fb3609', - 'd1ef410112e3f3ed8a98e1dc7e64f653', - '5e05ca0cd3496beebe8f3a3c5dec2e3c', - '3e2febea1b3c111eed26c9a5a6b90ef3', - '969f85ffb945e52278b0b55b895f12a1', - 'd00132dd4a88b01e4071e8b1e1d6cf28', - '5d940c16b18065eb2579a48d12a9cdd0', - '144cbd4cd41f6bf3a3bee7b0776cff40', - '793cd15349782e52b009a5337301c2b9', - '676def9232cfb0ad832311cf6c29defb', - '7010c8c6d8124e35b1c9ad643f219ffd', - 'd0b705242470e18b6caf62dc1765e70f', - 'e0874bd58e0a72f341406fef23979bd0', - '4174d81f0fa117071a58abc5886cce45', - '6221a8463b3978352a1cc6f0b0945f0a', - '154c04f511463b7f73033559561ca88d', - '66fc47c7320a7af96716f17c80b0eb3f', + 'ba2bc300017587a47517a4572526b933', + '26ccc134a7a0dbca796c084da8a8f2ab', + '9353b5a4743d5846966982c617f8c6d3', + '38256f2a773b1d2e4bdc75ae08fc5aca', + '2e7889e3525851cb5f52917c1433f276', + '636c833769cbc78ebe6c50aa143bdb7c', + 'ff5af0c4a25ad97bea69046d90816795', + '6d0d5e14aeeb05df47ac0a609834a919', + '43d41135168d8ddeba8bd75a5ecdd23b', + '5a13ce6c9e3631caf83541d53490503e', + 'b2c53aa181d573f773c531d33a4ecaaa', + '75dcb30bbc0881082c336d94f04ba6cf', + 'c0d52057e60ec03f6e1e353c833cdb58', + '873ffa4c448ba9a4700c7287969265c5', + 'fd5d647936a2359641f005c1f63d6c9b', + 'd6c94a9cc87ceee6bdbddcf6b1a44430', + 'c317380eafe0d801d69ad41527817e4c', + '88e797f27103025280032ea58dfe3286', + '602a6129ed715ef7f0d64f1a3d06c79d', + '35b049dbbfc14eafe6eff9784fbc043c', + 'c7d2dcad8a49fb378c1156bc3e0eb076', + '099bd7788d3d1035a9ef0703bc8c5e3a', + 'b4127e80ac8ff38350c0561219bd4829', + '1e0c648381278c5f8a1e700117b68481', + 'f31b2395ece58f7ce0050401fbfc6ee3', + 'd7e0c607f6c273191935fe3c503f5edc', + 'c764f9a7d1fe73f7e25914785822228f', + '6631019d7da3f4895f73a8552b594ed7', + '3c6e6ae969948fdf2d5483c25cf4de9b', + '453c7605eb2530da9f73370d0b547b74', + '064065551068620fc01871981d7d78be', + '5fb0fef97089d96b73b2e36c472d3ea3', + '5d031c711a4c967d69230300884043b4', + '6766828a69d373a5cca7b8d6ab02de68', + 'e0b5b6179fa12fca7c6c485fff6c9604', + 'e96485164e8cd8cc67786a695aa1ef41', + '54b31167d328cef00adccaa1a58817a2', + '0220c1091cfbffd04c04b7a4c85042f1', + 'b28fa401faa29491a44196d26a97b207', + '361a44ba78a1d1c83a3ac69c54698427', + '1f1d1e5c34e55fc2befd1d9c8406c6e6', + '5a5b2e61f4bd2d6becf09794c076052c', + 'e876ee447141fcf3340fd2be9e0e7150', + 'f39056ec56716ac8126d028f5b173af3', + '9583a43d92f68823bf7ed48cee58a31f', + '55bad15339b118e2a5499d9c6e4d6712', + 'a13a80b07b2652e875ad2d6085c1d18b', + '32c7e1206e515c1d1e70ce377297d54b', + '6a184b55796ea1e881d770e738b7ab50', + 'f8447318c2425bb9b61867b3893c076e', + '3799d315dcd32cb4ef04f7c696864a97', + '03e5f35bbddb6eabb31d204956553929', + '38a184c0de890152e827818d91262a03', + '89712caccd036a44d57532af16b5edac', + '25262ba7da76224ac55b25fc2c0f72e7', + 'b9a88e9fd06e9f5d61f21ff2f2bbb7a1', + 'e13d2a99df2448b3c3dda18ed4e25d10', + 'ef0b2152ae957394bb790cfa253297ad', + '7d64c455ce832456b15c11d363fb78f5', + 'f8f697616faeb8a37c754cb5753b87a9', + 'ebb22b7ebe0e7ac29ce841cc237a941f', + 'b527639217b053dde60a34d7fb0d576b', + '1b5b1ef52b505d5858eb30d86ccd26a2', + 'fc4654d784f30ab97a72f089ad7e5684', ]); }); } diff --git a/pkgs/native_assets_cli/test/link_config_test.dart b/pkgs/native_assets_cli/test/link_config_test.dart index 44440d254..af6dd26a1 100644 --- a/pkgs/native_assets_cli/test/link_config_test.dart +++ b/pkgs/native_assets_cli/test/link_config_test.dart @@ -6,6 +6,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/src/config.dart' show latestVersion; import 'package:test/test.dart'; void main() async { @@ -83,7 +84,7 @@ void main() async { 'target_android_ndk_api': 30, 'target_architecture': 'arm64', 'target_os': 'android', - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), 'c_compiler.ar': fakeAr.toFilePath(), 'c_compiler.ld': fakeLd.toFilePath(), 'c_compiler.cc': fakeClang.toFilePath(), @@ -132,7 +133,7 @@ void main() async { (e) => e is FormatException && e.message.contains(version) && - e.message.contains(HookConfig.currentVersion.toString()), + e.message.contains(latestVersion.toString()), )), ); }); @@ -151,10 +152,10 @@ void main() async { 'target_android_ndk_api': 30, 'target_architecture': 'invalid_architecture', 'target_os': 'android', - 'version': HookOutput.latestVersion.toString(), + 'version': latestVersion.toString(), }; expect( - () => LinkConfig(config), + () => LinkConfig(config).codeConfig, throwsFormatException, ); }); @@ -170,7 +171,7 @@ void main() async { ); expect( () => LinkConfig({ - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), 'supported_asset_types': [CodeAsset.type], 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), @@ -189,7 +190,7 @@ void main() async { ); expect( () => LinkConfig({ - 'version': HookConfig.currentVersion.toString(), + 'version': latestVersion.toString(), 'supported_asset_types': [CodeAsset.type], 'out_dir': outDirUri.toFilePath(), 'out_dir_shared': outputDirectoryShared.toFilePath(), diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart index 9a92e3649..17adc1519 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart @@ -154,7 +154,7 @@ Future buildLib( supportedAssetTypes: [CodeAsset.type], packageName: name, packageRoot: tempUri, - targetOS: OS.iOS, + targetOS: OS.macOS, buildMode: BuildMode.release, ) ..setupBuildConfig( From 4bde8837ed5e1e1c778e0223cc20b816f535ed42 Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Mon, 14 Oct 2024 09:38:41 +0200 Subject: [PATCH 3/7] Many changes Amongst the changes: - require `configValidator` that can ensure the final hook configs are valid before using them to invoke hooks - update changelogs - add test wrappers - split out verification & config/output tests: move code/data asset specifics into their own tests - ... --- pkgs/native_assets_builder/CHANGELOG.md | 5 + .../lib/src/build_runner/build_runner.dart | 301 ++++++++++-------- .../build_runner/build_dependencies_test.dart | 1 + .../build_runner_asset_id_test.dart | 2 + .../build_runner_build_dry_run_test.dart | 1 + ...build_runner_build_output_format_test.dart | 1 + .../build_runner_caching_test.dart | 6 + .../build_runner/build_runner_cycle_test.dart | 1 + .../build_runner_failure_test.dart | 3 + .../build_runner_non_root_package_test.dart | 2 + .../build_runner_reusability_test.dart | 2 + .../build_runner_run_in_isolation_test.dart | 1 + .../test/build_runner/build_runner_test.dart | 2 + .../concurrency_shared_test_helper.dart | 8 +- .../build_runner/concurrency_test_helper.dart | 4 + .../build_runner/conflicting_dylib_test.dart | 3 + .../fail_on_os_sdk_version_test.dart | 8 + .../test/build_runner/helpers.dart | 10 +- .../test/build_runner/link_caching_test.dart | 2 + .../test/build_runner/link_test.dart | 9 + .../test/build_runner/metadata_test.dart | 1 + .../packaging_preference_test.dart | 4 + .../test/build_runner/resources_test.dart | 2 + .../test/build_runner/wrong_linker_test.dart | 1 + .../test_data/add_asset_link/hook/link.dart | 2 +- .../test_data/complex_link/hook/link.dart | 2 +- .../test_data/drop_dylib_link/hook/link.dart | 2 +- .../native_add_duplicate/hook/link.dart | 2 +- .../test_data/simple_link/hook/link.dart | 2 +- .../treeshaking_native_libs/hook/link.dart | 4 +- pkgs/native_assets_cli/CHANGELOG.md | 2 + .../build/local_asset/test/build_test.dart | 10 +- .../link/package_with_assets/hook/link.dart | 2 +- .../lib/native_assets_cli.dart | 13 +- .../lib/native_assets_cli_internal.dart | 21 +- .../lib/src/c_compiler_config.dart | 41 +-- .../lib/src/code_assets/code_asset.dart | 103 ------ .../src/code_assets/code_asset_bundling.dart | 77 ----- .../lib/src/code_assets/config.dart | 175 ++++++++++ .../lib/src/code_assets/testing.dart | 53 +++ .../lib/src/code_assets/validation.dart | 58 ++++ pkgs/native_assets_cli/lib/src/config.dart | 35 +- .../lib/src/data_assets/config.dart | 75 +++++ .../lib/src/data_assets/data_asset.dart | 45 --- .../src/data_assets/data_asset_bundling.dart | 20 -- .../lib/src/data_assets/validation.dart | 15 + .../native_assets_cli/lib/src/json_utils.dart | 27 +- .../native_assets_cli/lib/src/validation.dart | 32 ++ pkgs/native_assets_cli/lib/test.dart | 2 +- .../test/build_config_test.dart | 115 +------ .../test/build_output_test.dart | 37 +-- .../native_assets_cli/test/checksum_test.dart | 130 ++++---- .../test/code_assets/code_asset_test.dart | 28 ++ .../test/code_assets/config_test.dart | 222 +++++++++++++ .../validation_test.dart} | 234 ++++---------- .../test/data_assets/data_asset_test.dart | 23 ++ .../test/data_assets/validation_test.dart | 110 +++++++ .../test/link_config_test.dart | 74 +---- .../test/link_output_test.dart | 61 ++++ .../test/validation_test.dart | 123 +++++++ pkgs/native_toolchain_c/CHANGELOG.md | 6 +- 61 files changed, 1434 insertions(+), 929 deletions(-) delete mode 100644 pkgs/native_assets_cli/lib/src/code_assets/code_asset_bundling.dart create mode 100644 pkgs/native_assets_cli/lib/src/code_assets/config.dart create mode 100644 pkgs/native_assets_cli/lib/src/code_assets/testing.dart create mode 100644 pkgs/native_assets_cli/lib/src/data_assets/config.dart delete mode 100644 pkgs/native_assets_cli/lib/src/data_assets/data_asset_bundling.dart create mode 100644 pkgs/native_assets_cli/test/code_assets/code_asset_test.dart create mode 100644 pkgs/native_assets_cli/test/code_assets/config_test.dart rename pkgs/native_assets_cli/test/{validator/validator_test.dart => code_assets/validation_test.dart} (56%) create mode 100644 pkgs/native_assets_cli/test/data_assets/data_asset_test.dart create mode 100644 pkgs/native_assets_cli/test/data_assets/validation_test.dart create mode 100644 pkgs/native_assets_cli/test/link_output_test.dart create mode 100644 pkgs/native_assets_cli/test/validation_test.dart diff --git a/pkgs/native_assets_builder/CHANGELOG.md b/pkgs/native_assets_builder/CHANGELOG.md index f70d95e62..4395f99df 100644 --- a/pkgs/native_assets_builder/CHANGELOG.md +++ b/pkgs/native_assets_builder/CHANGELOG.md @@ -21,6 +21,11 @@ consistency of the sum of those parts. Effectively this means: Any asset that doesn't have an explicit linker will get a NOP linker that emits as outputs it's inputs. +- **Breaking change** Removes knowledge about code & data assets from + `package:native_assets_builder`. Users of this package can know hook into the + build/link hook configuration that is used and e.g. initialize code + configuration. Similarly users of this package now have to provide a callback + to verify the consistency of the used hook configuration. ## 0.8.3 diff --git a/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart b/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart index fce1a52ce..70506752f 100644 --- a/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart +++ b/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart @@ -33,6 +33,14 @@ typedef LinkConfigCreator = LinkConfigBuilder Function(); typedef _HookValidator = Future Function( HookConfig config, HookOutput output); +// A callback that validates the invariants of the [BuildConfig]. +typedef BuildConfigValidator = Future Function( + BuildConfig config); + +// A callback that validates the invariants of the [LinkConfig]. +typedef LinkConfigValidator = Future Function( + LinkConfig config); + // A callback that validates the output of a `hook/link.dart` invocation is // valid (it may valid asset-type specific information). typedef BuildValidator = Future Function( @@ -81,6 +89,7 @@ class NativeAssetsBuildRunner { /// https://github.com/dart-lang/native/issues/1319 Future build({ required BuildConfigCreator configCreator, + required BuildConfigValidator configValidator, required BuildValidator buildValidator, required ApplicationAssetValidator applicationAssetValidator, required OS targetOS, @@ -91,22 +100,89 @@ class NativeAssetsBuildRunner { String? runPackageName, required List supportedAssetTypes, required bool linkingEnabled, - }) async => - _run( - targetOS: targetOS, - buildMode: buildMode, - configCreator: configCreator, - validator: (HookConfig config, HookOutput output) => + }) async { + packageLayout ??= await PackageLayout.fromRootPackageRoot(workingDirectory); + + final (buildPlan, packageGraph, planSuccess) = await _makePlan( + hook: Hook.build, + packageLayout: packageLayout, + buildResult: null, + runPackageName: runPackageName, + ); + if (!planSuccess) return null; + + var hookResult = HookResult(); + final globalMetadata = {}; + for (final package in buildPlan) { + final metadata = {}; + _metadataForPackage( + packageGraph: packageGraph!, + packageName: package.name, + targetMetadata: globalMetadata, + )?.forEach((key, value) => metadata[key] = value); + + final configBuilder = configCreator() + ..setupHookConfig( + targetOS: targetOS, + supportedAssetTypes: supportedAssetTypes, + buildMode: buildMode, + packageName: package.name, + packageRoot: packageLayout.packageRoot(package.name), + ) + ..setupBuildConfig( + dryRun: false, + linkingEnabled: linkingEnabled, + metadata: metadata, + ); + + final (buildDirUri, outDirUri, outDirSharedUri) = await _setupDiretories( + Hook.build, packageLayout, configBuilder, package); + + configBuilder.setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outDirSharedUri, + ); + + final config = BuildConfig(configBuilder.json); + final errors = [ + ...await validateBuildConfig(config), + ...await configValidator(config), + ]; + if (errors.isNotEmpty) { + return _printErrors( + 'Build configuration for ${package.name} contains errors', errors); + } + + final hookOutput = await _runHookForPackageCached( + Hook.build, + config, + (config, output) => buildValidator(config as BuildConfig, output as BuildOutput), - applicationAssetValidator: applicationAssetValidator, - hook: Hook.build, - workingDirectory: workingDirectory, - includeParentEnvironment: includeParentEnvironment, - packageLayout: packageLayout, - runPackageName: runPackageName, - supportedAssetTypes: supportedAssetTypes, - linkingEnabled: linkingEnabled, + packageLayout.packageConfigUri, + workingDirectory, + includeParentEnvironment, + null, + packageLayout, ); + if (hookOutput == null) return null; + hookResult = hookResult.copyAdd(hookOutput); + globalMetadata[package.name] = (hookOutput as BuildOutput).metadata; + } + + // We only perform application wide validation in the final result of + // building all assets (i.e. in the build step if linking is not enabled or + // in the link step if linking is enableD). + if (linkingEnabled) return hookResult; + + final errors = await applicationAssetValidator(hookResult.encodedAssets); + if (errors.isEmpty) return hookResult; + + logger.severe('Application asset verification failed:'); + for (final error in errors) { + logger.severe('- $error'); + } + return null; + } /// [workingDirectory] is expected to contain `.dart_tool`. /// @@ -120,7 +196,8 @@ class NativeAssetsBuildRunner { /// [api.BuildConfig] and [api.LinkConfig]! For more info see: /// https://github.com/dart-lang/native/issues/1319 Future link({ - required ConfigCreator configCreator, + required LinkConfigCreator configCreator, + required LinkConfigValidator configValidator, required LinkValidator linkValidator, required OS targetOS, required BuildMode buildMode, @@ -132,128 +209,60 @@ class NativeAssetsBuildRunner { String? runPackageName, required List supportedAssetTypes, required BuildResult buildResult, - }) async => - _run( - configCreator: configCreator, - validator: (HookConfig config, HookOutput output) => - linkValidator(config as LinkConfig, output as LinkOutput), - applicationAssetValidator: applicationAssetValidator, - targetOS: targetOS, - buildMode: buildMode, - hook: Hook.link, - workingDirectory: workingDirectory, - includeParentEnvironment: includeParentEnvironment, - packageLayout: packageLayout, - runPackageName: runPackageName, - resourceIdentifiers: resourceIdentifiers, - supportedAssetTypes: supportedAssetTypes, - buildResult: buildResult, - ); - - /// The common method for running building or linking of assets. - Future _run({ - required ConfigCreator configCreator, - required _HookValidator validator, - required ApplicationAssetValidator applicationAssetValidator, - required OS targetOS, - required BuildMode buildMode, - required Hook hook, - required Uri workingDirectory, - required bool includeParentEnvironment, - PackageLayout? packageLayout, - String? runPackageName, - required List supportedAssetTypes, - bool? linkingEnabled, - BuildResult? buildResult, - Uri? resourceIdentifiers, }) async { - assert(hook == Hook.link || buildResult == null); - assert(hook == Hook.build || linkingEnabled == null); - packageLayout ??= await PackageLayout.fromRootPackageRoot(workingDirectory); + final (buildPlan, packageGraph, planSuccess) = await _makePlan( - hook: hook, + hook: Hook.link, packageLayout: packageLayout, buildResult: buildResult, runPackageName: runPackageName, ); - if (!planSuccess) { - return null; - } + if (!planSuccess) return null; - var hookResult = (hook == Hook.link) - ? HookResult(encodedAssets: buildResult!.encodedAssets) - : HookResult(); - final globalMetadata = {}; + var hookResult = HookResult(encodedAssets: buildResult.encodedAssets); for (final package in buildPlan) { - final configBuilder = configCreator(); - configBuilder.setupHookConfig( - targetOS: targetOS, - supportedAssetTypes: supportedAssetTypes, - buildMode: buildMode, - packageName: package.name, - packageRoot: packageLayout.packageRoot(package.name), - ); - if (hook == Hook.build) { - final metadata = {}; - _metadataForPackage( - packageGraph: packageGraph!, + final configBuilder = configCreator() + ..setupHookConfig( + targetOS: targetOS, + supportedAssetTypes: supportedAssetTypes, + buildMode: buildMode, packageName: package.name, - targetMetadata: globalMetadata, - )?.forEach((key, value) => metadata[key] = value); - (configBuilder as BuildConfigBuilder).setupBuildConfig( - dryRun: false, - linkingEnabled: linkingEnabled!, - metadata: metadata, - ); - } else { - (configBuilder as LinkConfigBuilder).setupLinkConfig( - assets: buildResult!.encodedAssetsForLinking[package.name] ?? []); - } - - final buildDirName = configBuilder.computeChecksum(); - final buildDirUri = - packageLayout.dartToolNativeAssetsBuilder.resolve('$buildDirName/'); - final outDirUri = buildDirUri.resolve('out/'); - final outDir = Directory.fromUri(outDirUri); - if (!await outDir.exists()) { - // TODO(https://dartbug.com/50565): Purge old or unused folders. - await outDir.create(recursive: true); - } - final outputDirectoryShared = packageLayout.dartToolNativeAssetsBuilder - .resolve('shared/${package.name}/$hook/'); - final outDirShared = Directory.fromUri(outputDirectoryShared); - if (!await outDirShared.exists()) { - // TODO(https://dartbug.com/50565): Purge old or unused folders. - await outDirShared.create(recursive: true); + packageRoot: packageLayout.packageRoot(package.name), + ) + ..setupLinkConfig( + assets: buildResult.encodedAssetsForLinking[package.name] ?? []); + + final (buildDirUri, outDirUri, outDirSharedUri) = await _setupDiretories( + Hook.build, packageLayout, configBuilder, package); + + File? resourcesFile; + if (resourceIdentifiers != null) { + resourcesFile = File.fromUri(buildDirUri.resolve('resources.json')); + await resourcesFile.create(); + await File.fromUri(resourceIdentifiers).copy(resourcesFile.path); } + configBuilder.setupLinkRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outDirSharedUri, + recordedUsesFile: resourcesFile?.uri, + ); - if (hook == Hook.link) { - File? resourcesFile; - if (resourceIdentifiers != null) { - resourcesFile = File.fromUri(buildDirUri.resolve('resources.json')); - await resourcesFile.create(); - await File.fromUri(resourceIdentifiers).copy(resourcesFile.path); - } - (configBuilder as LinkConfigBuilder).setupLinkRunConfig( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - recordedUsesFile: resourcesFile?.uri, - ); - } else { - (configBuilder as BuildConfigBuilder).setupBuildRunConfig( - outputDirectory: outDirUri, - outputDirectoryShared: outputDirectoryShared, - ); + final config = LinkConfig(configBuilder.json); + final errors = [ + ...await validateLinkConfig(config), + ...await configValidator(config), + ]; + if (errors.isNotEmpty) { + return _printErrors( + 'Link configuration for ${package.name} contains errors', errors); } - final config = hook == Hook.build - ? BuildConfig(configBuilder.json) - : LinkConfig(configBuilder.json); final hookOutput = await _runHookForPackageCached( - hook, + Hook.link, config, - validator, + (config, output) => + linkValidator(config as LinkConfig, output as LinkOutput), packageLayout.packageConfigUri, workingDirectory, includeParentEnvironment, @@ -262,25 +271,48 @@ class NativeAssetsBuildRunner { ); if (hookOutput == null) return null; hookResult = hookResult.copyAdd(hookOutput); - if (hook == Hook.build) { - globalMetadata[package.name] = (hookOutput as BuildOutput).metadata; - } } - // We only perform application wide validation in the final result of - // building all assets (i.e. in the build step if linking is not enabled or - // in the link step if linking is enableD). - if (hook == Hook.build && linkingEnabled!) return hookResult; final errors = await applicationAssetValidator(hookResult.encodedAssets); if (errors.isEmpty) return hookResult; - logger.severe('Application asset verification failed:'); + _printErrors('Application asset verification failed', errors); + return null; + } + + Null _printErrors(String message, ValidationErrors errors) { + assert(errors.isNotEmpty); + logger.severe(message); for (final error in errors) { logger.severe('- $error'); } return null; } + Future<(Uri, Uri, Uri)> _setupDiretories( + Hook hook, + PackageLayout packageLayout, + HookConfigBuilder configBuilder, + Package package) async { + final buildDirName = configBuilder.computeChecksum(); + final buildDirUri = + packageLayout.dartToolNativeAssetsBuilder.resolve('$buildDirName/'); + final outDirUri = buildDirUri.resolve('out/'); + final outDir = Directory.fromUri(outDirUri); + if (!await outDir.exists()) { + // TODO(https://dartbug.com/50565): Purge old or unused folders. + await outDir.create(recursive: true); + } + final outDirSharedUri = packageLayout.dartToolNativeAssetsBuilder + .resolve('shared/${package.name}/$hook/'); + final outDirShared = Directory.fromUri(outDirSharedUri); + if (!await outDirShared.exists()) { + // TODO(https://dartbug.com/50565): Purge old or unused folders. + await outDirShared.create(recursive: true); + } + return (buildDirUri, outDirUri, outDirSharedUri); + } + /// [workingDirectory] is expected to contain `.dart_tool`. /// /// This method is invoked by launchers such as dartdev (for `dart run`) and @@ -582,10 +614,9 @@ ${result.stdout} final errors = await _validate(config, output, packageLayout, validator); if (errors.isNotEmpty) { - logger.severe('package:${config.packageName}` has invalid output.'); - for (final error in errors) { - logger.severe('- $error'); - } + _printErrors( + '$hook hook of package:${config.packageName} has invalid output', + errors); deleteOutputIfExists = true; return null; } @@ -812,9 +843,9 @@ ${compileResult.stdout} // Link hooks are skipped if no assets for linking are provided. buildPlan = []; final skipped = []; - final encodedAssetsForLinking = buildResult?.encodedAssetsForLinking; + final encodedAssetsForLinking = buildResult!.encodedAssetsForLinking; for (final package in packagesWithHook) { - if (encodedAssetsForLinking![package.name]?.isNotEmpty ?? false) { + if (encodedAssetsForLinking[package.name]?.isNotEmpty ?? false) { buildPlan.add(package); } else { skipped.add(package.name); diff --git a/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart b/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart index 98eec9cf5..1a4e55b0d 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart @@ -32,6 +32,7 @@ void main() async { dartExecutable, capturedLogs: logMessages, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart index 59e606757..a35f650cb 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart @@ -28,6 +28,7 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ); @@ -63,6 +64,7 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart index 096f00bc9..b87296a64 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart @@ -36,6 +36,7 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart index b81987c16..9faefd081 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart @@ -34,6 +34,7 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [], + configValidator: (config) async => [], buildValidator: (config, output) async => [], applicationAssetValidator: validateCodeAssetsInApplication, ); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart index 9034149ee..e97f195d9 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart @@ -34,6 +34,7 @@ void main() async { dartExecutable, capturedLogs: logMessages, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -60,6 +61,7 @@ void main() async { dartExecutable, capturedLogs: logMessages, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -104,6 +106,7 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -123,6 +126,7 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -157,6 +161,7 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -184,6 +189,7 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_cycle_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_cycle_test.dart index 75321d0b5..198029f80 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_cycle_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_cycle_test.dart @@ -48,6 +48,7 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [], + configValidator: (config) async => [], buildValidator: (config, output) async => [], applicationAssetValidator: (_) async => [], ); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart index 198ba4252..b3b10d930 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart @@ -29,6 +29,7 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -56,6 +57,7 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ); @@ -83,6 +85,7 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart index 3799ed120..3c32e8447 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart @@ -31,6 +31,7 @@ void main() async { capturedLogs: logMessages, runPackageName: 'some_dev_dep', supportedAssetTypes: [CodeAsset.type], + configValidator: validateDataAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -47,6 +48,7 @@ void main() async { capturedLogs: logMessages, runPackageName: 'native_add', supportedAssetTypes: [CodeAsset.type], + configValidator: validateDataAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_reusability_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_reusability_test.dart index c1e091691..19e58520d 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_reusability_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_reusability_test.dart @@ -59,6 +59,7 @@ void main() async { includeParentEnvironment: true, linkingEnabled: false, supportedAssetTypes: [], + configValidator: (config) async => [], buildValidator: (config, output) async => [], applicationAssetValidator: (_) async => [], ); @@ -70,6 +71,7 @@ void main() async { includeParentEnvironment: true, linkingEnabled: false, supportedAssetTypes: [], + configValidator: (config) async => [], buildValidator: (config, output) async => [], applicationAssetValidator: (_) async => [], ); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart index 4443c2a31..752453e1a 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart @@ -61,6 +61,7 @@ void main() async { // Prevent any other environment variables. includeParentEnvironment: false, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart index aba3ba9ea..acc4f1d00 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart @@ -37,6 +37,7 @@ void main() async { logger, dartExecutable, capturedLogs: logMessages, + configValidator: validateCodeBuildConfig, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, @@ -64,6 +65,7 @@ void main() async { capturedLogs: logMessages, packageLayout: packageLayout, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/concurrency_shared_test_helper.dart b/pkgs/native_assets_builder/test/build_runner/concurrency_shared_test_helper.dart index 0f8f90ba1..cb69d2833 100644 --- a/pkgs/native_assets_builder/test/build_runner/concurrency_shared_test_helper.dart +++ b/pkgs/native_assets_builder/test/build_runner/concurrency_shared_test_helper.dart @@ -20,18 +20,14 @@ void main(List args) async { logger: logger, dartExecutable: dartExecutable, ).build( - configCreator: () => BuildConfigBuilder() - ..setupCodeConfig( - targetArchitecture: target.architecture, - linkModePreference: LinkModePreference.dynamic, - targetAndroidNdkApi: target.os == OS.android ? 30 : null, - ), + configCreator: BuildConfigBuilder.new, buildMode: BuildMode.release, targetOS: target.os, workingDirectory: packageUri, includeParentEnvironment: true, linkingEnabled: false, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetBuildConfig, buildValidator: (config, output) async => await validateDataAssetBuildOutput(config, output), applicationAssetValidator: (_) async => [], diff --git a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart index 8aa2746a5..f738f5494 100644 --- a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart +++ b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart @@ -37,6 +37,10 @@ void main(List args) async { includeParentEnvironment: true, linkingEnabled: false, supportedAssetTypes: [CodeAsset.type, DataAsset.type], + configValidator: (config) async => [ + ...await validateDataAssetBuildConfig(config), + ...await validateCodeBuildConfig(config), + ], buildValidator: (config, output) async => [ ...await validateCodeAssetBuildOutput(config, output), ...await validateDataAssetBuildOutput(config, output), diff --git a/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart b/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart index c0eecc0ec..e5d2d8cd4 100644 --- a/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart @@ -28,6 +28,7 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ); @@ -58,6 +59,7 @@ void main() async { linkingEnabled: true, dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -68,6 +70,7 @@ void main() async { dartExecutable, buildResult: buildResult, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeLinkConfig, linkValidator: validateCodeAssetLinkOutput, applicationAssetValidator: validateCodeAssetsInApplication, ); diff --git a/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart b/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart index b2c3b85b9..10e42ab75 100644 --- a/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart @@ -74,10 +74,18 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type, DataAsset.type], + buildConfigValidator: (config) async => [ + ...await validateDataAssetBuildConfig(config), + ...await validateCodeBuildConfig(config), + ], buildValidator: (config, output) async => [ ...await validateCodeAssetBuildOutput(config, output), ...await validateDataAssetBuildOutput(config, output), ], + linkConfigValidator: (config) async => [ + ...await validateDataAssetLinkConfig(config), + ...await validateCodeLinkConfig(config), + ], linkValidator: (config, output) async => [ ...await validateCodeAssetLinkOutput(config, output), ...await validateDataAssetLinkOutput(config, output), diff --git a/pkgs/native_assets_builder/test/build_runner/helpers.dart b/pkgs/native_assets_builder/test/build_runner/helpers.dart index 640d8add7..27b493c17 100644 --- a/pkgs/native_assets_builder/test/build_runner/helpers.dart +++ b/pkgs/native_assets_builder/test/build_runner/helpers.dart @@ -32,6 +32,7 @@ Future build( Uri packageUri, Logger logger, Uri dartExecutable, { + required BuildConfigValidator configValidator, required BuildValidator buildValidator, required ApplicationAssetValidator applicationAssetValidator, LinkModePreference linkModePreference = LinkModePreference.dynamic, @@ -63,6 +64,7 @@ Future build( targetMacOSVersion: targetMacOSVersion, targetAndroidNdkApi: targetAndroidNdkApi, ), + configValidator: configValidator, buildMode: BuildMode.release, targetOS: target?.os ?? OS.current, workingDirectory: packageUri, @@ -90,6 +92,7 @@ Future link( Uri packageUri, Logger logger, Uri dartExecutable, { + required LinkConfigValidator configValidator, required LinkValidator linkValidator, required ApplicationAssetValidator applicationAssetValidator, LinkModePreference linkModePreference = LinkModePreference.dynamic, @@ -121,6 +124,7 @@ Future link( targetMacOSVersion: targetMacOSVersion, targetAndroidNdkApi: targetAndroidNdkApi, ), + configValidator: configValidator, buildMode: BuildMode.release, targetOS: target?.os ?? OS.current, workingDirectory: packageUri, @@ -146,8 +150,10 @@ Future<(BuildResult?, LinkResult?)> buildAndLink( Uri dartExecutable, { LinkModePreference linkModePreference = LinkModePreference.dynamic, CCompilerConfig? cCompilerConfig, - required LinkValidator linkValidator, + required BuildConfigValidator buildConfigValidator, + required LinkConfigValidator linkConfigValidator, required BuildValidator buildValidator, + required LinkValidator linkValidator, required ApplicationAssetValidator applicationAssetValidator, bool includeParentEnvironment = true, List? capturedLogs, @@ -177,6 +183,7 @@ Future<(BuildResult?, LinkResult?)> buildAndLink( targetMacOSVersion: targetMacOSVersion, targetAndroidNdkApi: targetAndroidNdkApi, ), + configValidator: buildConfigValidator, buildMode: BuildMode.release, targetOS: target?.os ?? OS.current, workingDirectory: packageUri, @@ -210,6 +217,7 @@ Future<(BuildResult?, LinkResult?)> buildAndLink( targetMacOSVersion: targetMacOSVersion, targetAndroidNdkApi: targetAndroidNdkApi, ), + configValidator: linkConfigValidator, buildMode: BuildMode.release, targetOS: target?.os ?? OS.current, workingDirectory: packageUri, diff --git a/pkgs/native_assets_builder/test/build_runner/link_caching_test.dart b/pkgs/native_assets_builder/test/build_runner/link_caching_test.dart index 21f20657c..36e02c2cd 100644 --- a/pkgs/native_assets_builder/test/build_runner/link_caching_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/link_caching_test.dart @@ -40,6 +40,7 @@ void main() async { linkingEnabled: true, supportedAssetTypes: [DataAsset.type], capturedLogs: logMessages, + configValidator: validateDataAssetBuildConfig, buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], ))!; @@ -54,6 +55,7 @@ void main() async { buildResult: buildResult, supportedAssetTypes: [DataAsset.type], capturedLogs: logMessages, + configValidator: validateDataAssetLinkConfig, linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/link_test.dart b/pkgs/native_assets_builder/test/build_runner/link_test.dart index c5006bc31..09417a403 100644 --- a/pkgs/native_assets_builder/test/build_runner/link_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/link_test.dart @@ -32,6 +32,7 @@ void main() async { dartExecutable, linkingEnabled: true, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetBuildConfig, buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], ))!; @@ -43,6 +44,7 @@ void main() async { dartExecutable, buildResult: buildResult, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetLinkConfig, linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], ))!; @@ -54,6 +56,7 @@ void main() async { dartExecutable, linkingEnabled: false, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetBuildConfig, buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], ))!; @@ -99,6 +102,7 @@ void main() async { dartExecutable, linkingEnabled: true, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetBuildConfig, buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], ); @@ -116,6 +120,7 @@ void main() async { dartExecutable, buildResult: buildResult, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetLinkConfig, linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], ); @@ -144,6 +149,7 @@ void main() async { dartExecutable, linkingEnabled: true, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetBuildConfig, buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], ))!; @@ -158,6 +164,7 @@ void main() async { buildResult: buildResult, capturedLogs: logMessages, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetLinkConfig, linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], ))!; @@ -197,6 +204,7 @@ void main() async { dartExecutable, linkingEnabled: true, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -211,6 +219,7 @@ void main() async { buildResult: buildResult, capturedLogs: logMessages, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeLinkConfig, linkValidator: validateCodeAssetLinkOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/metadata_test.dart b/pkgs/native_assets_builder/test/build_runner/metadata_test.dart index 8fcb39afe..17aa2e5d0 100644 --- a/pkgs/native_assets_builder/test/build_runner/metadata_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/metadata_test.dart @@ -32,6 +32,7 @@ void main() async { dartExecutable, capturedLogs: logMessages, supportedAssetTypes: ['foo'], + configValidator: (config) async => [], buildValidator: (config, output) async => [], applicationAssetValidator: (_) async => [], ); diff --git a/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart b/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart index ae62b4295..15ec6f5ca 100644 --- a/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart @@ -27,6 +27,7 @@ void main() async { dartExecutable, linkModePreference: LinkModePreference.dynamic, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -37,6 +38,7 @@ void main() async { dartExecutable, linkModePreference: LinkModePreference.preferDynamic, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -47,6 +49,7 @@ void main() async { dartExecutable, linkModePreference: LinkModePreference.static, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; @@ -57,6 +60,7 @@ void main() async { dartExecutable, linkModePreference: LinkModePreference.preferStatic, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, ))!; diff --git a/pkgs/native_assets_builder/test/build_runner/resources_test.dart b/pkgs/native_assets_builder/test/build_runner/resources_test.dart index 3ae036471..936c3522c 100644 --- a/pkgs/native_assets_builder/test/build_runner/resources_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/resources_test.dart @@ -35,6 +35,7 @@ void main() async { dartExecutable, linkingEnabled: true, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetBuildConfig, buildValidator: validateDataAssetBuildOutput, applicationAssetValidator: (_) async => [], ))!; @@ -53,6 +54,7 @@ void main() async { buildResult: buildResult, resourceIdentifiers: resourcesUri, supportedAssetTypes: [DataAsset.type], + configValidator: validateDataAssetLinkConfig, linkValidator: validateDataAssetLinkOutput, applicationAssetValidator: (_) async => [], ); diff --git a/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart b/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart index 0f776dd47..1ff2f8ff2 100644 --- a/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart @@ -28,6 +28,7 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type], + configValidator: validateCodeBuildConfig, buildValidator: validateCodeAssetBuildOutput, applicationAssetValidator: validateCodeAssetsInApplication, linkingEnabled: true, diff --git a/pkgs/native_assets_builder/test_data/add_asset_link/hook/link.dart b/pkgs/native_assets_builder/test_data/add_asset_link/hook/link.dart index ccfbb9775..3f48615e0 100644 --- a/pkgs/native_assets_builder/test_data/add_asset_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/add_asset_link/hook/link.dart @@ -6,7 +6,7 @@ import 'package:native_assets_cli/native_assets_cli.dart'; void main(List arguments) async { await link(arguments, (config, output) async { - final builtDylib = config.codeAssets.all.first; + final builtDylib = config.codeAssets.first; output ..codeAssets.add( CodeAsset( diff --git a/pkgs/native_assets_builder/test_data/complex_link/hook/link.dart b/pkgs/native_assets_builder/test_data/complex_link/hook/link.dart index 113586781..335df7a08 100644 --- a/pkgs/native_assets_builder/test_data/complex_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/complex_link/hook/link.dart @@ -8,7 +8,7 @@ void main(List args) async { await link( args, (config, output) async => - output.dataAssets.addAll(treeshake(config.dataAssets.all)), + output.dataAssets.addAll(treeshake(config.dataAssets)), ); } diff --git a/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart b/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart index 3dfcb16c7..d531402a6 100644 --- a/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart @@ -6,7 +6,7 @@ import 'package:native_assets_cli/native_assets_cli.dart'; void main(List arguments) async { await link(arguments, (config, output) async { - for (final codeAsset in config.codeAssets.all) { + for (final codeAsset in config.codeAssets) { print('Got code asset: ${codeAsset.id}'); if (codeAsset.id.endsWith('add')) { output.codeAssets.add(codeAsset); diff --git a/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/link.dart b/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/link.dart index b69973d47..4ba7a02a7 100644 --- a/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/link.dart @@ -7,6 +7,6 @@ import 'package:native_assets_cli/native_assets_cli.dart'; void main(List args) async { await link(args, (config, output) async { // Simply output the dylib in the link hook. - output.codeAssets.addAll(config.codeAssets.all); + output.codeAssets.addAll(config.codeAssets); }); } diff --git a/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart b/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart index 3478258ab..31780a866 100644 --- a/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart @@ -6,7 +6,7 @@ import 'package:native_assets_cli/native_assets_cli.dart'; void main(List args) async { await link(args, (config, output) async { - shake(output, config.dataAssets.all); + shake(output, config.dataAssets); }); } diff --git a/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/link.dart b/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/link.dart index 07c868d95..3ee5acb56 100644 --- a/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/link.dart @@ -12,9 +12,9 @@ void main(List arguments) async { (config, output) async { final linker = CLinker.library( name: config.packageName, - assetName: config.codeAssets.all.single.id.split('/').skip(1).join('/'), + assetName: config.codeAssets.single.id.split('/').skip(1).join('/'), linkerOptions: LinkerOptions.treeshake(symbols: ['add']), - sources: [config.codeAssets.all.single.file!.toFilePath()], + sources: [config.codeAssets.single.file!.toFilePath()], ); await linker.run( config: config, diff --git a/pkgs/native_assets_cli/CHANGELOG.md b/pkgs/native_assets_cli/CHANGELOG.md index 71aff12e5..2f6955dc9 100644 --- a/pkgs/native_assets_cli/CHANGELOG.md +++ b/pkgs/native_assets_cli/CHANGELOG.md @@ -23,6 +23,8 @@ - **Breaking change** Removed `Asset` class, removed `{Build,Link}Output.assets*`. Hook writers should now use e.g. `output.dataAssets.add(DataAsset(...))` instead of `output.addAsset(DataAsset(...))`. +- **Breaking change** Introduce builder classes that construct hook configs and + hook outputs. ## 0.8.0 diff --git a/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart b/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart index c21063d6c..4e40c1fee 100644 --- a/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart +++ b/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart @@ -7,16 +7,10 @@ import 'package:test/test.dart'; import '../hook/build.dart' as build; -void main() { - testBuildHook( +void main() async { + await testCodeBuildHook( description: 'test my build hook', mainMethod: build.main, - extraConfigSetup: (config) { - config.setupCodeConfig( - linkModePreference: LinkModePreference.dynamic, - targetArchitecture: Architecture.current, - ); - }, check: (_, output) { expect(output.codeAssets, isNotEmpty); expect( diff --git a/pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart b/pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart index d77ea69bc..a00f548f8 100644 --- a/pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart +++ b/pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart @@ -20,7 +20,7 @@ void main(List args) async { final usedAssets = (usages.instancesOf(multiplyIdentifier) ?? []).map((e) => (e.instanceConstant.fields.values.first as StringConstant).value); - output.dataAssets.addAll(config.dataAssets.all + output.dataAssets.addAll(config.dataAssets .where((dataAsset) => usedAssets.contains(dataAsset.name))); }); } diff --git a/pkgs/native_assets_cli/lib/native_assets_cli.dart b/pkgs/native_assets_cli/lib/native_assets_cli.dart index 9cf2d1821..789ed234b 100644 --- a/pkgs/native_assets_cli/lib/native_assets_cli.dart +++ b/pkgs/native_assets_cli/lib/native_assets_cli.dart @@ -13,31 +13,28 @@ export 'src/api/linker.dart' show Linker; export 'src/architecture.dart' show Architecture; export 'src/build_mode.dart' show BuildMode; export 'src/c_compiler_config.dart' show CCompilerConfig; -export 'src/code_assets/code_asset.dart' +export 'src/code_assets/code_asset.dart' show CodeAsset, OSLibraryNaming; +export 'src/code_assets/config.dart' show BuildOutputCodeAssets, - CodeAsset, CodeAssetBuildConfig, CodeAssetsBuildOutput, CodeAssetsLinkConfig, CodeAssetsLinkOutput, CodeConfig, - LinkConfigCodeAssets, - LinkOutputCodeAssets, - OSLibraryNaming; + LinkOutputCodeAssets; export 'src/config.dart' show BuildConfig, BuildOutputBuilder; export 'src/config.dart' show BuildOutput, LinkOutput, LinkOutputBuilder; export 'src/config.dart' show HookConfig; export 'src/config.dart' show LinkConfig; -export 'src/data_assets/data_asset.dart' +export 'src/data_assets/config.dart' show BuildOutputDataAssets, - DataAsset, DataAssetsBuildOutput, DataAssetsLinkConfig, DataAssetsLinkOutput, - LinkConfigDataAssets, LinkOutputDataAssets; +export 'src/data_assets/data_asset.dart' show DataAsset; export 'src/encoded_asset.dart' show EncodedAsset; export 'src/ios_sdk.dart' show IOSSdk; export 'src/link_mode.dart' diff --git a/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart b/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart index 95d1f5ec7..92a4d40ee 100644 --- a/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart +++ b/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart @@ -17,20 +17,26 @@ library native_assets_cli_internal; export 'native_assets_cli.dart' hide build, link; -export 'src/code_assets/code_asset_bundling.dart' +export 'src/code_assets/config.dart' show CodeAssetBuildConfigBuilder, CodeAssetBuildOutput, CodeAssetLinkOutput; export 'src/code_assets/validation.dart' show validateCodeAssetBuildOutput, validateCodeAssetLinkOutput, - validateCodeAssetsInApplication; + validateCodeAssetsInApplication, + validateCodeBuildConfig, + validateCodeLinkConfig; export 'src/config.dart' show BuildConfigBuilder, LinkConfigBuilder; export 'src/config.dart' show BuildOutputBuilder, LinkOutputBuilder; export 'src/config.dart' show HookConfigBuilder, HookOutput; -export 'src/data_assets/data_asset_bundling.dart' +export 'src/data_assets/config.dart' show DataAssetBuildOutput, DataAssetLinkOutput; export 'src/data_assets/validation.dart' - show validateDataAssetBuildOutput, validateDataAssetLinkOutput; + show + validateDataAssetBuildConfig, + validateDataAssetBuildOutput, + validateDataAssetLinkConfig, + validateDataAssetLinkOutput; export 'src/encoded_asset.dart' show EncodedAsset; export 'src/model/dependencies.dart'; export 'src/model/hook.dart'; @@ -38,4 +44,9 @@ export 'src/model/metadata.dart'; export 'src/model/resource_identifiers.dart'; export 'src/model/target.dart' show Target; export 'src/validation.dart' - show ValidationErrors, validateBuildOutput, validateLinkOutput; + show + ValidationErrors, + validateBuildConfig, + validateBuildOutput, + validateLinkConfig, + validateLinkOutput; diff --git a/pkgs/native_assets_cli/lib/src/c_compiler_config.dart b/pkgs/native_assets_cli/lib/src/c_compiler_config.dart index b04cc7cbc..94f727b9c 100644 --- a/pkgs/native_assets_cli/lib/src/c_compiler_config.dart +++ b/pkgs/native_assets_cli/lib/src/c_compiler_config.dart @@ -38,16 +38,14 @@ final class CCompilerConfig { /// /// The json is expected to be valid encoding obtained via /// [CCompilerConfig.toJson]. - factory CCompilerConfig.fromJson(Map json) { - final compiler = _parseCompiler(json); - return CCompilerConfig( - archiver: _parseArchiver(json), - compiler: compiler, - envScript: _parseEnvScript(json, compiler), - envScriptArgs: _parseEnvScriptArgs(json), - linker: _parseLinker(json), - ); - } + factory CCompilerConfig.fromJson(Map json) => + CCompilerConfig( + archiver: json.optionalPath(_arConfigKey), + compiler: json.optionalPath(_ccConfigKey), + envScript: json.optionalPath(_envScriptConfigKey), + envScriptArgs: json.optionalStringList(_envScriptArgsConfigKey), + linker: json.optionalPath(_ldConfigKey), + ); /// The json representation of this [CCompilerConfig]. /// @@ -87,29 +85,6 @@ final class CCompilerConfig { ); } -Uri? _parseArchiver(Map config) => config.optionalPath( - _arConfigKey, - mustExist: true, - ); - -Uri? _parseCompiler(Map config) => config.optionalPath( - _ccConfigKey, - mustExist: true, - ); - -Uri? _parseLinker(Map config) => config.optionalPath( - _ldConfigKey, - mustExist: true, - ); - -Uri? _parseEnvScript(Map config, Uri? compiler) => - (compiler != null && compiler.toFilePath().endsWith('cl.exe')) - ? config.path(_envScriptConfigKey, mustExist: true) - : null; - -List? _parseEnvScriptArgs(Map config) => - config.optionalStringList(_envScriptArgsConfigKey); - const _arConfigKey = 'ar'; const _ccConfigKey = 'cc'; const _ldConfigKey = 'ld'; diff --git a/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart b/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart index 399175643..0b92b1735 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/code_asset.dart @@ -3,13 +3,10 @@ // BSD-style license that can be found in the LICENSE file. import '../architecture.dart'; -import '../c_compiler_config.dart'; import '../config.dart'; import '../encoded_asset.dart'; -import '../ios_sdk.dart'; import '../json_utils.dart'; import '../link_mode.dart'; -import '../link_mode_preference.dart'; import '../os.dart'; import '../utils/json.dart'; import '../utils/map.dart'; @@ -191,57 +188,6 @@ final class CodeAsset { static const String type = 'native_code'; } -/// Build config extension for code assets. -extension CodeAssetBuildConfig on BuildConfig { - CodeConfig get codeConfig => CodeConfig(this); -} - -/// Build output extension for code assets. -extension CodeAssetsBuildOutput on BuildOutputBuilder { - BuildOutputCodeAssets get codeAssets => BuildOutputCodeAssets(this); -} - -extension type BuildOutputCodeAssets(BuildOutputBuilder _output) { - void add(CodeAsset asset, {String? linkInPackage}) => - _output.addEncodedAsset(asset.encode(), linkInPackage: linkInPackage); - - void addAll(Iterable assets, {String? linkInPackage}) { - for (final asset in assets) { - add(asset, linkInPackage: linkInPackage); - } - } -} - -/// Link output extension for code assets. -extension CodeAssetsLinkConfig on LinkConfig { - CodeConfig get codeConfig => CodeConfig(this); - LinkConfigCodeAssets get codeAssets => LinkConfigCodeAssets(this); -} - -extension type LinkConfigCodeAssets(LinkConfig _config) { - // Returns the code assets that were sent to this linker. - // - // NOTE: If the linker implementation depends on the contents of the files the - // code assets refer (e.g. looks at static archives and links them) then the - // linker script has to add those files as dependencies via - // [LinkOutput.addDependency] to ensure the linker script will be re-run if - // the content of the files changes. - Iterable get all => _config.encodedAssets - .where((e) => e.type == CodeAsset.type) - .map(CodeAsset.fromEncoded); -} - -/// Link output extension for code assets. -extension CodeAssetsLinkOutput on LinkOutputBuilder { - LinkOutputCodeAssets get codeAssets => LinkOutputCodeAssets(this); -} - -extension type LinkOutputCodeAssets(LinkOutputBuilder _output) { - void add(CodeAsset asset) => _output.addEncodedAsset(asset.encode()); - - void addAll(Iterable assets) => assets.forEach(add); -} - extension OSLibraryNaming on OS { /// The default dynamic library file name on this os. String dylibFileName(String name) { @@ -274,55 +220,6 @@ extension OSLibraryNaming on OS { } } -class CodeConfig { - final Architecture? _targetArchitecture; - - final LinkModePreference linkModePreference; - final CCompilerConfig cCompiler; - final int? targetIOSVersion; - final int? targetMacOSVersion; - final int? targetAndroidNdkApi; - final IOSSdk? targetIOSSdk; - - CodeConfig(HookConfig config) - : linkModePreference = LinkModePreference.fromString( - config.json.string('link_mode_preference')), - _targetArchitecture = (config is BuildConfig && config.dryRun) - ? null - : Architecture.fromString(config.json.string('target_architecture', - validValues: Architecture.values.map((a) => a.name))), - cCompiler = (() { - final cCompiler = CCompilerConfig( - archiver: config.json.optionalPath('c_compiler.ar'), - compiler: config.json.optionalPath('c_compiler.cc'), - linker: config.json.optionalPath('c_compiler.ld'), - envScript: config.json.optionalPath('c_compiler.env_script'), - envScriptArgs: switch ( - config.json.optionalList('env_script_arguments')) { - final List l => [ - for (int i = 0; i < l.length; ++i) l.get(i) - ], - null => null, - }, - ); - return cCompiler; - })(), - targetIOSVersion = config.json.optionalInt('target_ios_version'), - targetMacOSVersion = config.json.optionalInt('target_macos_version'), - targetAndroidNdkApi = config.json.optionalInt('target_android_ndk_api'), - targetIOSSdk = switch (config.json.optionalString('target_ios_sdk')) { - final String value => IOSSdk.fromString(value), - null => null, - }; - - Architecture get targetArchitecture { - if (_targetArchitecture == null) { - throw StateError('Cannot access target architecture in dry runs'); - } - return _targetArchitecture; - } -} - /// The default name prefix for dynamic libraries per [OS]. const _dylibPrefix = { OS.android: 'lib', diff --git a/pkgs/native_assets_cli/lib/src/code_assets/code_asset_bundling.dart b/pkgs/native_assets_cli/lib/src/code_assets/code_asset_bundling.dart deleted file mode 100644 index ce8bc7e87..000000000 --- a/pkgs/native_assets_cli/lib/src/code_assets/code_asset_bundling.dart +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import '../architecture.dart'; -import '../c_compiler_config.dart'; -import '../config.dart'; -import '../ios_sdk.dart'; -import '../link_mode_preference.dart'; -import 'code_asset.dart'; - -// XXX TODO: Migrate to json decoding api. -extension CodeAssetBuildConfigBuilder on HookConfigBuilder { - void setupCodeConfig({ - required Architecture? targetArchitecture, - required LinkModePreference linkModePreference, - CCompilerConfig? cCompilerConfig, - int? targetIOSVersion, - int? targetMacOSVersion, - int? targetAndroidNdkApi, - IOSSdk? targetIOSSdk, - }) { - if (targetArchitecture != null) { - json['target_architecture'] = targetArchitecture.toString(); - } - json['link_mode_preference'] = linkModePreference.toString(); - if (cCompilerConfig != null) { - final ar = cCompilerConfig.archiver?.toFilePath(); - if (ar != null) { - json['c_compiler.ar'] = ar; - } - final cc = cCompilerConfig.compiler?.toFilePath(); - if (ar != null) { - json['c_compiler.cc'] = cc; - } - final ld = cCompilerConfig.linker?.toFilePath(); - if (ar != null) { - json['c_compiler.ld'] = ld; - } - final envScript = cCompilerConfig.envScript?.toFilePath(); - if (envScript != null) { - json['c_compiler.env_script'] = envScript; - } - final envScriptArgs = cCompilerConfig.envScriptArgs; - if (envScriptArgs != null && envScriptArgs.isNotEmpty) { - json['env_script_arguments'] = envScriptArgs; - } - } - - if (targetIOSVersion != null) { - json['target_ios_version'] = targetIOSVersion; - } - if (targetMacOSVersion != null) { - json['target_macos_version'] = targetMacOSVersion; - } - if (targetAndroidNdkApi != null) { - json['target_android_ndk_api'] = targetAndroidNdkApi; - } - if (targetIOSSdk != null) { - json['target_ios_sdk'] = targetIOSSdk.toString(); - } - } -} - -extension CodeAssetBuildOutput on BuildOutput { - List get codeAssets => encodedAssets - .where((asset) => asset.type == CodeAsset.type) - .map(CodeAsset.fromEncoded) - .toList(); -} - -extension CodeAssetLinkOutput on LinkOutput { - List get codeAssets => encodedAssets - .where((asset) => asset.type == CodeAsset.type) - .map(CodeAsset.fromEncoded) - .toList(); -} diff --git a/pkgs/native_assets_cli/lib/src/code_assets/config.dart b/pkgs/native_assets_cli/lib/src/code_assets/config.dart new file mode 100644 index 000000000..cea210f5f --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/code_assets/config.dart @@ -0,0 +1,175 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../architecture.dart'; +import '../c_compiler_config.dart'; +import '../config.dart'; +import '../ios_sdk.dart'; +import '../json_utils.dart'; +import '../link_mode_preference.dart'; + +import 'code_asset.dart'; + +/// Extension to the [BuildConfig] providing access to configuration specific to +/// code assets (only available if code assets are supported). +extension CodeAssetBuildConfig on BuildConfig { + /// Code asset specific configuration. + CodeConfig get codeConfig => CodeConfig(this); +} + +/// Extension to the [LinkConfig] providing access to configuration specific to +/// code assets as well as code asset inputs to the linker (only available if +/// code assets are supported). +extension CodeAssetsLinkConfig on LinkConfig { + /// Code asset specific configuration. + CodeConfig get codeConfig => CodeConfig(this); + + // Returns the code assets that were sent to this linker. + // + // NOTE: If the linker implementation depends on the contents of the files the + // code assets refer (e.g. looks at static archives and links them) then the + // linker script has to add those files as dependencies via + // [LinkOutput.addDependency] to ensure the linker script will be re-run if + // the content of the files changes. + Iterable get codeAssets => encodedAssets + .where((e) => e.type == CodeAsset.type) + .map(CodeAsset.fromEncoded); +} + +/// Configuration for hook writers if code assets are supported. +class CodeConfig { + final Architecture? _targetArchitecture; + + final LinkModePreference linkModePreference; + final CCompilerConfig cCompiler; + final int? targetIOSVersion; + final int? targetMacOSVersion; + final int? targetAndroidNdkApi; + final IOSSdk? targetIOSSdk; + + CodeConfig(HookConfig config) + : linkModePreference = LinkModePreference.fromString( + config.json.string(_linkModePreferenceKey)), + _targetArchitecture = (config is BuildConfig && config.dryRun) + ? null + : Architecture.fromString(config.json.string(_targetArchitectureKey, + validValues: Architecture.values.map((a) => a.name))), + cCompiler = switch (config.json.optionalMap(_compilerKey)) { + final Map map => CCompilerConfig.fromJson(map), + null => CCompilerConfig(), + }, + targetIOSVersion = config.json.optionalInt(_targetIOSVersionKey), + targetMacOSVersion = config.json.optionalInt(_targetMacOSVersionKey), + targetAndroidNdkApi = config.json.optionalInt(_targetAndroidNdkApiKey), + targetIOSSdk = switch (config.json.optionalString(_targetIOSSdkKey)) { + final String value => IOSSdk.fromString(value), + null => null, + }; + + Architecture get targetArchitecture { + if (_targetArchitecture == null) { + throw StateError('Cannot access target architecture in dry runs'); + } + return _targetArchitecture; + } +} + +/// Extension to the [BuildOutputBuilder] providing access to emitting code +/// assets (only available if code assets are supported). +extension CodeAssetsBuildOutput on BuildOutputBuilder { + /// Provides access to emitting code assets. + BuildOutputCodeAssets get codeAssets => BuildOutputCodeAssets._(this); +} + +/// Supports emitting code assets for build hooks. +extension type BuildOutputCodeAssets._(BuildOutputBuilder _output) { + /// Adds the given [asset] to the hook output (or send to [linkInPackage] + /// for linking if provided). + void add(CodeAsset asset, {String? linkInPackage}) => + _output.addEncodedAsset(asset.encode(), linkInPackage: linkInPackage); + + /// Adds the given [assets] to the hook output (or send to [linkInPackage] + /// for linking if provided). + void addAll(Iterable assets, {String? linkInPackage}) { + for (final asset in assets) { + add(asset, linkInPackage: linkInPackage); + } + } +} + +/// Extension to the [LinkOutputBuilder] providing access to emitting code +/// assets (only available if code assets are supported). +extension CodeAssetsLinkOutput on LinkOutputBuilder { + /// Provides access to emitting code assets. + LinkOutputCodeAssets get codeAssets => LinkOutputCodeAssets._(this); +} + +/// Extension on [LinkOutputBuilder] to emit code assets. +extension type LinkOutputCodeAssets._(LinkOutputBuilder _output) { + /// Adds the given [asset] to the link hook output. + void add(CodeAsset asset) => _output.addEncodedAsset(asset.encode()); + + /// Adds the given [assets] to the link hook output. + void addAll(Iterable assets) => assets.forEach(add); +} + +/// Extension to initialize code specific configuration on link/build configs. +extension CodeAssetBuildConfigBuilder on HookConfigBuilder { + void setupCodeConfig({ + required Architecture? targetArchitecture, + required LinkModePreference linkModePreference, + CCompilerConfig? cCompilerConfig, + int? targetIOSVersion, + int? targetMacOSVersion, + int? targetAndroidNdkApi, + IOSSdk? targetIOSSdk, + }) { + if (targetArchitecture != null) { + json[_targetArchitectureKey] = targetArchitecture.toString(); + } + json[_linkModePreferenceKey] = linkModePreference.toString(); + if (cCompilerConfig != null) { + json[_compilerKey] = cCompilerConfig.toJson(); + } + + if (targetIOSVersion != null) { + json[_targetIOSVersionKey] = targetIOSVersion; + } + if (targetMacOSVersion != null) { + json[_targetMacOSVersionKey] = targetMacOSVersion; + } + if (targetAndroidNdkApi != null) { + json[_targetAndroidNdkApiKey] = targetAndroidNdkApi; + } + if (targetIOSSdk != null) { + json[_targetIOSSdkKey] = targetIOSSdk.toString(); + } + } +} + +/// Provides access to [CodeAsset]s from a build hook output. +extension CodeAssetBuildOutput on BuildOutput { + /// The code assets emitted by the build hook. + List get codeAssets => encodedAssets + .where((asset) => asset.type == CodeAsset.type) + .map(CodeAsset.fromEncoded) + .toList(); +} + +/// Provides access to [CodeAsset]s from a link hook output. +extension CodeAssetLinkOutput on LinkOutput { + /// The code assets emitted by the link hook. + List get codeAssets => encodedAssets + .where((asset) => asset.type == CodeAsset.type) + .map(CodeAsset.fromEncoded) + .toList(); +} + +const String _compilerKey = 'c_compiler'; +const String _targetArchitectureKey = 'target_architecture'; +const String _targetIOSSdkKey = 'target_ios_sdk'; +const String _linkModePreferenceKey = 'link_mode_preference'; +const String _targetIOSVersionKey = 'target_ios_version'; +const String _targetMacOSVersionKey = 'target_macos_version'; +const String _targetAndroidNdkApiKey = 'target_android_ndk_api'; diff --git a/pkgs/native_assets_cli/lib/src/code_assets/testing.dart b/pkgs/native_assets_cli/lib/src/code_assets/testing.dart new file mode 100644 index 000000000..0b09166ed --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/code_assets/testing.dart @@ -0,0 +1,53 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:meta/meta.dart' show isTest; +import 'package:test/test.dart'; + +import '../../test.dart'; + +@isTest +Future testCodeBuildHook({ + required String description, + // ignore: inference_failure_on_function_return_type + required Function(List arguments) mainMethod, + required FutureOr Function(BuildConfig, BuildOutput) check, + BuildMode? buildMode, + Architecture? targetArchitecture, + OS? targetOS, + IOSSdk? targetIOSSdk, + int? targetIOSVersion, + int? targetMacOSVersion, + int? targetAndroidNdkApi, + CCompilerConfig? cCompiler, + LinkModePreference? linkModePreference, + required List supportedAssetTypes, + bool? linkingEnabled, +}) async { + await testBuildHook( + description: description, + mainMethod: mainMethod, + extraConfigSetup: (config) { + config.setupCodeConfig( + linkModePreference: linkModePreference ?? LinkModePreference.dynamic, + cCompilerConfig: cCompiler, + targetArchitecture: targetArchitecture ?? Architecture.current, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion, + targetAndroidNdkApi: targetAndroidNdkApi, + ); + }, + check: (config, output) async { + expect(await validateCodeAssetBuildOutput(config, output), isEmpty); + await check(config, output); + }, + buildMode: buildMode, + targetOS: targetOS, + supportedAssetTypes: supportedAssetTypes, + linkingEnabled: linkingEnabled, + ); +} diff --git a/pkgs/native_assets_cli/lib/src/code_assets/validation.dart b/pkgs/native_assets_cli/lib/src/code_assets/validation.dart index 8c333d361..381986ed8 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/validation.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/validation.dart @@ -7,6 +7,64 @@ import 'dart:io'; import '../../native_assets_cli_internal.dart'; import '../link_mode.dart'; +Future validateCodeBuildConfig(BuildConfig config) async => + _validateCodeConfig( + 'BuildConfig', config.targetOS, config.dryRun, config.codeConfig); + +Future validateCodeLinkConfig(LinkConfig config) async => + _validateCodeConfig( + 'LinkConfig', config.targetOS, false, config.codeConfig); + +ValidationErrors _validateCodeConfig( + String configName, OS targetOS, bool dryRun, CodeConfig codeConfig) { + // The dry run will be removed soon. + if (dryRun) return const []; + + final errors = []; + switch (targetOS) { + case OS.macOS: + if (codeConfig.targetMacOSVersion == null) { + errors.add('$configName.targetOS is OS.macOS but ' + '$configName.codeConfig.targetMacOSVersion was missing'); + } + break; + case OS.iOS: + if (codeConfig.targetIOSSdk == null) { + errors.add('$configName.targetOS is OS.iOS but ' + '$configName.codeConfig.targetIOSSdk was missing'); + } + if (codeConfig.targetIOSVersion == null) { + errors.add('$configName.targetOS is OS.iOS but ' + '$configName.codeConfig.targetIOSVersion was missing'); + } + break; + case OS.android: + if (codeConfig.targetAndroidNdkApi == null) { + errors.add('$configName.targetOS is OS.android but ' + '$configName.codeConfig.targetAndroidNdkApi was missing'); + } + break; + } + final compilerConfig = codeConfig.cCompiler; + final compiler = compilerConfig.compiler?.toFilePath(); + if (compiler != null && !File(compiler).existsSync()) { + errors.add('$configName.codeConfig.compiler ($compiler) does not exist.'); + } + final linker = compilerConfig.linker?.toFilePath(); + if (linker != null && !File(linker).existsSync()) { + errors.add('$configName.codeConfig.linker ($linker) does not exist.'); + } + final archiver = compilerConfig.archiver?.toFilePath(); + if (archiver != null && !File(archiver).existsSync()) { + errors.add('$configName.codeConfig.archiver ($archiver) does not exist.'); + } + final envScript = compilerConfig.envScript?.toFilePath(); + if (envScript != null && !File(envScript).existsSync()) { + errors.add('$configName.codeConfig.envScript ($envScript) does not exist.'); + } + return errors; +} + Future validateCodeAssetBuildOutput( BuildConfig config, BuildOutput output, diff --git a/pkgs/native_assets_cli/lib/src/config.dart b/pkgs/native_assets_cli/lib/src/config.dart index bb370c5ca..a25f6a3ee 100644 --- a/pkgs/native_assets_cli/lib/src/config.dart +++ b/pkgs/native_assets_cli/lib/src/config.dart @@ -151,22 +151,6 @@ sealed class HookConfigBuilder { .substring(0, 32); return hash; } - //String computeChecksum() { - //final savedOutDir = json.remove(_outDirConfigKey); - //final savedSharedOutDir = json.remove(_outDirSharedConfigKey); - //final hash = sha256 - //.convert(const JsonEncoder().fuse(const Utf8Encoder()).convert(json)) - //.toString() - //// 256 bit hashes lead to 64 hex character strings. - //// To avoid overflowing file paths limits, only use 32. - //// Using 16 hex characters would also be unlikely to have collisions. - //.substring(0, 32); - //if (savedOutDir != null) json[_outDirConfigKey] = savedOutDir; - //if (savedSharedOutDir != null) { - //json[_outDirSharedConfigKey] = savedSharedOutDir; - //} - //return hash; - //} } const _targetOSConfigKey = 'target_os'; @@ -206,15 +190,13 @@ final class BuildConfigBuilder extends HookConfigBuilder { void setupBuildConfig({ required bool dryRun, required bool linkingEnabled, - Map? metadata, + Map metadata = const {}, }) { json[_dryRunConfigKey] = dryRun; json[_linkingEnabledKey] = linkingEnabled; - if (metadata != null) { - json[_dependencyMetadataKey] = { - for (final key in metadata.keys) key: metadata[key]!.toJson(), - }; - } + json[_dependencyMetadataKey] = { + for (final key in metadata.keys) key: metadata[key]!.toJson(), + }; } void setupBuildRunConfig({ @@ -331,6 +313,7 @@ sealed class HookOutputBuilder { HookOutputBuilder() { json[_versionKey] = HookOutput.latestVersion.toString(); json[_timestampKey] = DateTime.now().roundDownToSeconds().toString(); + json[_dependenciesKey] = []; } /// Adds file used by this build. @@ -338,8 +321,7 @@ sealed class HookOutputBuilder { /// If any of the files are modified after [BuildOutput.timestamp], the // build will be re-run. void addDependency(Uri uri) { - var dependencies = json[_dependenciesKey] as List?; - dependencies ??= json[_dependenciesKey] = []; + final dependencies = json[_dependenciesKey] as List; dependencies.add(uri.toFilePath()); } @@ -348,8 +330,7 @@ sealed class HookOutputBuilder { /// If any of the files are modified after [BuildOutput.timestamp], the // build will be re-run. void addDependencies(Iterable uris) { - var dependencies = json[_dependenciesKey] as List?; - dependencies ??= json[_dependenciesKey] = []; + final dependencies = json[_dependenciesKey] as List; dependencies.addAll(uris.map((uri) => uri.toFilePath())); } } @@ -396,7 +377,7 @@ List _parseEncodedAssets(List? json) => json == null const _assetsForLinkingKey = 'assetsForLinking'; const _dependencyMetadataKey = 'dependency_metadata'; -// XXX TODO +/// Builder to initialize build hook specific configuration. class BuildOutputBuilder extends HookOutputBuilder { /// Adds metadata to be passed to build hook invocations of dependent /// packages. diff --git a/pkgs/native_assets_cli/lib/src/data_assets/config.dart b/pkgs/native_assets_cli/lib/src/data_assets/config.dart new file mode 100644 index 000000000..99dafc3cb --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/data_assets/config.dart @@ -0,0 +1,75 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../config.dart'; + +import 'data_asset.dart'; + +/// Link output extension for data assets. +extension DataAssetsLinkConfig on LinkConfig { + // Returns the data assets that were sent to this linker. + // + // NOTE: If the linker implementation depends on the contents of the files of + // the data assets (e.g. by transforming them, merging with other files, etc) + // then the linker script has to add those files as dependencies via + // [LinkOutput.addDependency] to ensure the linker script will be re-run if + // the content of the files changes. + Iterable get dataAssets => encodedAssets + .where((e) => e.type == DataAsset.type) + .map(DataAsset.fromEncoded); +} + +/// Build output extension for data assets. +extension DataAssetsBuildOutput on BuildOutputBuilder { + /// Provides access to emitting data assets. + BuildOutputDataAssets get dataAssets => BuildOutputDataAssets._(this); +} + +/// Supports emitting code assets for build hooks. +extension type BuildOutputDataAssets._(BuildOutputBuilder _output) { + /// Adds the given [asset] to the hook output (or send to [linkInPackage] + /// for linking if provided). + void add(DataAsset asset, {String? linkInPackage}) => + _output.addEncodedAsset(asset.encode(), linkInPackage: linkInPackage); + + /// Adds the given [assets] to the hook output (or send to [linkInPackage] + /// for linking if provided). + void addAll(Iterable assets, {String? linkInPackage}) { + for (final asset in assets) { + add(asset, linkInPackage: linkInPackage); + } + } +} + +/// Extension to the [LinkOutputBuilder] providing access to emitting data +/// assets (only available if data assets are supported). +extension DataAssetsLinkOutput on LinkOutputBuilder { + /// Provides access to emitting data assets. + LinkOutputDataAssets get dataAssets => LinkOutputDataAssets(this); +} + +/// Extension on [LinkOutputBuilder] to emit data assets. +extension type LinkOutputDataAssets(LinkOutputBuilder _output) { + /// Adds the given [asset] to the link hook output. + void add(DataAsset asset) => _output.addEncodedAsset(asset.encode()); + + /// Adds the given [assets] to the link hook output. + void addAll(Iterable assets) => assets.forEach(add); +} + +/// Provides access to [DataAsset]s from a build hook output. +extension DataAssetBuildOutput on BuildOutput { + List get dataAssets => encodedAssets + .where((asset) => asset.type == DataAsset.type) + .map(DataAsset.fromEncoded) + .toList(); +} + +/// Provides access to [DataAsset]s from a link hook output. +extension DataAssetLinkOutput on LinkOutput { + List get dataAssets => encodedAssets + .where((asset) => asset.type == DataAsset.type) + .map(DataAsset.fromEncoded) + .toList(); +} diff --git a/pkgs/native_assets_cli/lib/src/data_assets/data_asset.dart b/pkgs/native_assets_cli/lib/src/data_assets/data_asset.dart index 248e6715c..96d5193ca 100644 --- a/pkgs/native_assets_cli/lib/src/data_assets/data_asset.dart +++ b/pkgs/native_assets_cli/lib/src/data_assets/data_asset.dart @@ -90,51 +90,6 @@ final class DataAsset { static const String type = 'data'; } -/// Build output extension for data assets. -extension DataAssetsBuildOutput on BuildOutputBuilder { - BuildOutputDataAssets get dataAssets => BuildOutputDataAssets(this); -} - -extension type BuildOutputDataAssets(BuildOutputBuilder _output) { - void add(DataAsset asset, {String? linkInPackage}) => - _output.addEncodedAsset(asset.encode(), linkInPackage: linkInPackage); - - void addAll(Iterable assets, {String? linkInPackage}) { - for (final asset in assets) { - add(asset, linkInPackage: linkInPackage); - } - } -} - -/// Link output extension for data assets. -extension DataAssetsLinkConfig on LinkConfig { - LinkConfigDataAssets get dataAssets => LinkConfigDataAssets(this); -} - -extension type LinkConfigDataAssets(LinkConfig _config) { - // Returns the data assets that were sent to this linker. - // - // NOTE: If the linker implementation depends on the contents of the files of - // the data assets (e.g. by transforming them, merging with other files, etc) - // then the linker script has to add those files as dependencies via - // [LinkOutput.addDependency] to ensure the linker script will be re-run if - // the content of the files changes. - Iterable get all => _config.encodedAssets - .where((e) => e.type == DataAsset.type) - .map(DataAsset.fromEncoded); -} - -/// Link output extension for data assets. -extension DataAssetsLinkOutput on LinkOutputBuilder { - LinkOutputDataAssets get dataAssets => LinkOutputDataAssets(this); -} - -extension type LinkOutputDataAssets(LinkOutputBuilder _output) { - void add(DataAsset asset) => _output.addEncodedAsset(asset.encode()); - - void addAll(Iterable assets) => assets.forEach(add); -} - const _nameKey = 'name'; const _packageKey = 'package'; const _fileKey = 'file'; diff --git a/pkgs/native_assets_cli/lib/src/data_assets/data_asset_bundling.dart b/pkgs/native_assets_cli/lib/src/data_assets/data_asset_bundling.dart deleted file mode 100644 index 45a17b0fd..000000000 --- a/pkgs/native_assets_cli/lib/src/data_assets/data_asset_bundling.dart +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import '../config.dart'; -import 'data_asset.dart'; - -extension DataAssetBuildOutput on BuildOutput { - List get dataAssets => encodedAssets - .where((asset) => asset.type == DataAsset.type) - .map(DataAsset.fromEncoded) - .toList(); -} - -extension DataAssetLinkOutput on LinkOutput { - List get dataAssets => encodedAssets - .where((asset) => asset.type == DataAsset.type) - .map(DataAsset.fromEncoded) - .toList(); -} diff --git a/pkgs/native_assets_cli/lib/src/data_assets/validation.dart b/pkgs/native_assets_cli/lib/src/data_assets/validation.dart index 8504b11c9..20a98d04b 100644 --- a/pkgs/native_assets_cli/lib/src/data_assets/validation.dart +++ b/pkgs/native_assets_cli/lib/src/data_assets/validation.dart @@ -6,6 +6,21 @@ import 'dart:io'; import '../../native_assets_cli_internal.dart'; +Future validateDataAssetBuildConfig( + BuildConfig config) async => + const []; + +Future validateDataAssetLinkConfig(LinkConfig config) async { + final errors = []; + for (final asset in config.dataAssets) { + if (!File.fromUri(asset.file).existsSync()) { + errors.add('LinkConfig.dataAssets contained asset ${asset.id} with file ' + '(${asset.file}) which does not exist.'); + } + } + return errors; +} + Future validateDataAssetBuildOutput( BuildConfig config, BuildOutput output, diff --git a/pkgs/native_assets_cli/lib/src/json_utils.dart b/pkgs/native_assets_cli/lib/src/json_utils.dart index 08864113a..8c79c527d 100644 --- a/pkgs/native_assets_cli/lib/src/json_utils.dart +++ b/pkgs/native_assets_cli/lib/src/json_utils.dart @@ -22,17 +22,12 @@ extension MapJsonUtils on Map { core.int int(String key) => get(key); core.int? optionalInt(String key) => getOptional(key); - Uri path(String key, {bool mustExist = false}) => - _fileSystemPathToUri(get(key)); + Uri path(String key) => _fileSystemPathToUri(get(key)); - Uri? optionalPath(String key, {bool mustExist = false}) { + Uri? optionalPath(String key) { final value = getOptional(key); if (value == null) return null; - final uri = _fileSystemPathToUri(value); - if (mustExist) { - _throwIfNotExists(key, uri); - } - return uri; + return _fileSystemPathToUri(value); } List? optionalStringList(String key) { @@ -85,22 +80,6 @@ extension ListJsonUtils on List { Uri pathAt(int index) => _fileSystemPathToUri(get(index)); } -void _throwIfNotExists(String key, Uri value) { - final fileSystemEntity = value.fileSystemEntity; - if (!fileSystemEntity.existsSync()) { - throw FormatException("Path '$value' for key '$key' doesn't exist."); - } -} - -extension on Uri { - FileSystemEntity get fileSystemEntity { - if (path.endsWith(Platform.pathSeparator) || path.endsWith('/')) { - return Directory.fromUri(this); - } - return File.fromUri(this); - } -} - Uri _fileSystemPathToUri(String path) { if (path.endsWith(Platform.pathSeparator)) { return Uri.directory(path); diff --git a/pkgs/native_assets_cli/lib/src/validation.dart b/pkgs/native_assets_cli/lib/src/validation.dart index 5a17dc31f..739721a1a 100644 --- a/pkgs/native_assets_cli/lib/src/validation.dart +++ b/pkgs/native_assets_cli/lib/src/validation.dart @@ -2,10 +2,42 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:io'; import '../native_assets_cli_internal.dart'; typedef ValidationErrors = List; +Future validateBuildConfig(BuildConfig config) async => + _validateHookConfig(config); + +Future validateLinkConfig(LinkConfig config) async { + final errors = [ + ..._validateHookConfig(config), + ]; + final recordUses = config.recordedUsagesFile; + if (recordUses != null && !File.fromUri(recordUses).existsSync()) { + errors.add('Config.recordUses ($recordUses) does not exist.'); + } + return errors; +} + +ValidationErrors _validateHookConfig(HookConfig config) { + final errors = []; + if (!Directory.fromUri(config.packageRoot).existsSync()) { + errors.add('Config.packageRoot (${config.packageRoot}) ' + 'has to be an existing directory.'); + } + if (!Directory.fromUri(config.outputDirectory).existsSync()) { + errors.add('Config.outputDirectory (${config.outputDirectory}) ' + 'has to be an existing directory.'); + } + if (!Directory.fromUri(config.outputDirectoryShared).existsSync()) { + errors.add('Config.outputDirectoryShared (${config.outputDirectoryShared}) ' + 'has to be an existing directory'); + } + return errors; +} + /// Invoked by package:native_assets_builder Future validateBuildOutput( BuildConfig config, diff --git a/pkgs/native_assets_cli/lib/test.dart b/pkgs/native_assets_cli/lib/test.dart index ca2b329d2..a520166e7 100644 --- a/pkgs/native_assets_cli/lib/test.dart +++ b/pkgs/native_assets_cli/lib/test.dart @@ -13,7 +13,7 @@ import 'package:yaml/yaml.dart'; import 'native_assets_cli_internal.dart'; export 'native_assets_cli_internal.dart'; -export 'src/code_assets/code_asset_bundling.dart'; +export 'src/code_assets/testing.dart' show testCodeBuildHook; @isTest Future testBuildHook({ diff --git a/pkgs/native_assets_cli/test/build_config_test.dart b/pkgs/native_assets_cli/test/build_config_test.dart index 3011444b6..29d937d89 100644 --- a/pkgs/native_assets_cli/test/build_config_test.dart +++ b/pkgs/native_assets_cli/test/build_config_test.dart @@ -11,39 +11,11 @@ import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_assets_cli/src/config.dart' show latestVersion; import 'package:test/test.dart'; -//XXX TODO -//test('envScript', () { -//final buildConfig1 = BuildConfigImpl( -//outputDirectory: outDirUri, -//outputDirectoryShared: outputDirectoryShared, -//packageName: packageName, -//packageRoot: packageRootUri, -//targetArchitecture: Architecture.x64, -//targetOS: OS.windows, -//cCompiler: CCompilerConfig( -//compiler: fakeCl, -//envScript: fakeVcVars, -//envScriptArgs: ['x64'], -//), -//buildMode: BuildMode.release, -//linkModePreference: LinkModePreference.dynamic, -//linkingEnabled: false, -//supportedAssetTypes: [CodeAsset.type], -//); - -//final configFile = buildConfig1.toJson(); -//final fromConfig = BuildConfigImpl.fromJson(configFile); -//expect(fromConfig, equals(buildConfig1)); -//}); - void main() async { late Uri outDirUri; late Uri outputDirectoryShared; late String packageName; late Uri packageRootUri; - late Uri fakeClang; - late Uri fakeLd; - late Uri fakeAr; late Map metadata; setUp(() async { @@ -52,9 +24,6 @@ void main() async { outputDirectoryShared = tempUri.resolve('out_shared1/'); packageName = 'my_package'; packageRootUri = tempUri.resolve('$packageName/'); - fakeClang = tempUri.resolve('fake_clang'); - fakeLd = tempUri.resolve('fake_ld'); - fakeAr = tempUri.resolve('fake_ar'); metadata = { 'bar': const Metadata({ 'key': 'value', @@ -73,7 +42,7 @@ void main() async { packageRoot: packageRootUri, targetOS: OS.android, buildMode: BuildMode.release, - supportedAssetTypes: [CodeAsset.type], + supportedAssetTypes: ['my-asset-type'], ) ..setupBuildConfig( linkingEnabled: false, @@ -83,36 +52,20 @@ void main() async { ..setupBuildRunConfig( outputDirectory: outDirUri, outputDirectoryShared: outputDirectoryShared, - ) - ..setupCodeConfig( - targetArchitecture: Architecture.arm64, - targetAndroidNdkApi: 30, - linkModePreference: LinkModePreference.preferStatic, - cCompilerConfig: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - archiver: fakeAr, - ), ); final config = BuildConfig(configBuilder.json); final expectedConfigJson = { 'build_mode': 'release', - 'supported_asset_types': [CodeAsset.type], + 'supported_asset_types': ['my-asset-type'], 'dry_run': false, 'linking_enabled': false, - 'link_mode_preference': 'prefer-static', 'out_dir': outDirUri.toFilePath(), 'out_dir_shared': outputDirectoryShared.toFilePath(), 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'arm64', 'target_os': 'android', 'version': latestVersion.toString(), - 'c_compiler.ar': fakeAr.toFilePath(), - 'c_compiler.ld': fakeLd.toFilePath(), - 'c_compiler.cc': fakeClang.toFilePath(), 'dependency_metadata': { 'bar': { 'key': 'value', @@ -134,19 +87,11 @@ void main() async { expect(config.packageRoot, packageRootUri); expect(config.targetOS, OS.android); expect(config.buildMode, BuildMode.release); - expect(config.supportedAssetTypes, [CodeAsset.type]); + expect(config.supportedAssetTypes, ['my-asset-type']); expect(config.linkingEnabled, false); expect(config.dryRun, false); expect(config.metadata, metadata); - - final codeConfig = config.codeConfig; - expect(codeConfig.targetArchitecture, Architecture.arm64); - expect(codeConfig.targetAndroidNdkApi, 30); - expect(codeConfig.linkModePreference, LinkModePreference.preferStatic); - expect(codeConfig.cCompiler.compiler, fakeClang); - expect(codeConfig.cCompiler.linker, fakeLd); - expect(codeConfig.cCompiler.archiver, fakeAr); }); test('BuildConfig.dryRun', () { @@ -156,7 +101,7 @@ void main() async { packageRoot: packageRootUri, targetOS: OS.android, buildMode: null, // not available in dry run - supportedAssetTypes: [CodeAsset.type], + supportedAssetTypes: ['my-asset-type'], ) ..setupBuildConfig( linkingEnabled: true, @@ -165,24 +110,19 @@ void main() async { ..setupBuildRunConfig( outputDirectory: outDirUri, outputDirectoryShared: outputDirectoryShared, - ) - ..setupCodeConfig( - targetArchitecture: null, // not available in dry run - cCompilerConfig: null, // not available in dry run - linkModePreference: LinkModePreference.preferStatic, ); final config = BuildConfig(configBuilder.json); final expectedConfigJson = { 'dry_run': true, - 'supported_asset_types': [CodeAsset.type], + 'supported_asset_types': ['my-asset-type'], 'linking_enabled': true, - 'link_mode_preference': 'prefer-static', 'out_dir': outDirUri.toFilePath(), 'out_dir_shared': outputDirectoryShared.toFilePath(), 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), 'target_os': 'android', + 'dependency_metadata': {}, 'version': latestVersion.toString(), }; @@ -195,20 +135,12 @@ void main() async { expect(config.packageName, packageName); expect(config.packageRoot, packageRootUri); expect(config.targetOS, OS.android); - expect(config.supportedAssetTypes, [CodeAsset.type]); + expect(config.supportedAssetTypes, ['my-asset-type']); expect(() => config.buildMode, throwsStateError); expect(config.linkingEnabled, true); expect(config.dryRun, true); expect(config.metadata, {}); - - final codeConfig = config.codeConfig; - expect(() => codeConfig.targetArchitecture, throwsStateError); - expect(codeConfig.targetAndroidNdkApi, null); - expect(codeConfig.linkModePreference, LinkModePreference.preferStatic); - expect(codeConfig.cCompiler.compiler, null); - expect(codeConfig.cCompiler.linker, null); - expect(codeConfig.cCompiler.archiver, null); }); group('BuildConfig format issues', () { @@ -223,7 +155,7 @@ void main() async { 'target_os': 'linux', 'version': version, 'package_name': packageName, - 'supported_asset_types': [CodeAsset.type], + 'supported_asset_types': ['my-asset-type'], 'dry_run': true, 'linking_enabled': false, }; @@ -255,12 +187,9 @@ void main() async { 'version': latestVersion.toString(), 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', 'target_os': 'android', - 'target_android_ndk_api': 30, - 'link_mode_preference': 'prefer-static', 'linking_enabled': true, - 'supported_asset_types': [CodeAsset.type], + 'supported_asset_types': ['my-asset-type'], }), throwsA(predicate( (e) => @@ -277,13 +206,10 @@ void main() async { 'out_dir_shared': outputDirectoryShared.toFilePath(), 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', 'target_os': 'android', - 'target_android_ndk_api': 30, - 'link_mode_preference': 'prefer-static', 'linking_enabled': true, 'build_mode': BuildMode.release.name, - 'supported_asset_types': [CodeAsset.type], + 'supported_asset_types': ['my-asset-type'], 'dependency_metadata': { 'bar': {'key': 'value'}, 'foo': [], @@ -297,26 +223,5 @@ void main() async { )), ); }); - - test('invalid architecture', () { - final config = { - 'build_mode': 'release', - 'dry_run': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'invalid_architecture', - 'target_os': 'android', - 'supported_asset_types': [CodeAsset.type], - 'version': latestVersion.toString(), - }; - expect( - () => BuildConfig(config), - throwsFormatException, - ); - }); }); } diff --git a/pkgs/native_assets_cli/test/build_output_test.dart b/pkgs/native_assets_cli/test/build_output_test.dart index e1af613f4..28e6f02ba 100644 --- a/pkgs/native_assets_cli/test/build_output_test.dart +++ b/pkgs/native_assets_cli/test/build_output_test.dart @@ -4,8 +4,6 @@ // ignore_for_file: deprecated_member_use_from_same_package -import 'dart:convert'; - import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_assets_cli/src/utils/datetime.dart'; import 'package:test/test.dart'; @@ -13,9 +11,8 @@ import 'package:test/test.dart'; void main() { test('BuildOutputBuilder->JSON->BuildOutput', () { final assets = [ - for (int i = 0; i < 6; i++) - DataAsset(file: Uri(path: 'asset$i'), name: 'assetId$i', package: 'pkg') - .encode(), + for (int i = 0; i < 3; i++) + EncodedAsset('my-asset-type', {'a-$i': 'v-$i'}) ]; final uris = [ for (int i = 0; i < 3; ++i) Uri.file('path$i'), @@ -48,32 +45,28 @@ void main() { expect(config.timestamp, lessThanOrEqualTo(config.timestamp.roundDownToSeconds())); - print(const JsonEncoder.withIndent(' ').convert(config.json)); - - final expectedJson = { + // The JSON format of the build output. + { 'version': '1.5.0', - 'timestamp': config.timestamp.toString(), - 'dependencies': [ - ...uris.map((uri) => uri.toFilePath()), - ], + 'dependencies': ['path0', 'path1', 'path2'], 'metadata': { - ...metadata0, - ...metadata1, + 'meta-a': 'meta-b', + 'meta0': 'meta0-value', + 'meta1': 'meta1-value' }, 'assets': [ - assets.take(1).single.toJson(), - ...assets.skip(2).take(2).map((e) => e.toJson()), + {'a-0': 'v-0', 'type': 'my-asset-type'}, + {'a-2': 'v-2', 'type': 'my-asset-type'} ], 'assetsForLinking': { 'package:linker1': [ - assets.skip(1).first.toJson(), + {'a-1': 'v-1', 'type': 'my-asset-type'} ], - 'package:linker2': [ - ...assets.skip(4).map((e) => e.toJson()), - ] + 'package:linker2': [], } - }; - expect(config.json, equals(expectedJson)); + }.forEach((k, v) { + expect(config.json[k], equals(v)); + }); }); for (final version in ['9001.0.0', '0.0.1']) { diff --git a/pkgs/native_assets_cli/test/checksum_test.dart b/pkgs/native_assets_cli/test/checksum_test.dart index 680e6da2e..6a83b564d 100644 --- a/pkgs/native_assets_cli/test/checksum_test.dart +++ b/pkgs/native_assets_cli/test/checksum_test.dart @@ -37,71 +37,71 @@ void main() { // If format or algorithm for checksumming changes we'd like to know (by // needing to update this list). - expect(checksums, [ - 'ba2bc300017587a47517a4572526b933', - '26ccc134a7a0dbca796c084da8a8f2ab', - '9353b5a4743d5846966982c617f8c6d3', - '38256f2a773b1d2e4bdc75ae08fc5aca', - '2e7889e3525851cb5f52917c1433f276', - '636c833769cbc78ebe6c50aa143bdb7c', - 'ff5af0c4a25ad97bea69046d90816795', - '6d0d5e14aeeb05df47ac0a609834a919', - '43d41135168d8ddeba8bd75a5ecdd23b', - '5a13ce6c9e3631caf83541d53490503e', - 'b2c53aa181d573f773c531d33a4ecaaa', - '75dcb30bbc0881082c336d94f04ba6cf', - 'c0d52057e60ec03f6e1e353c833cdb58', - '873ffa4c448ba9a4700c7287969265c5', - 'fd5d647936a2359641f005c1f63d6c9b', - 'd6c94a9cc87ceee6bdbddcf6b1a44430', - 'c317380eafe0d801d69ad41527817e4c', - '88e797f27103025280032ea58dfe3286', - '602a6129ed715ef7f0d64f1a3d06c79d', - '35b049dbbfc14eafe6eff9784fbc043c', - 'c7d2dcad8a49fb378c1156bc3e0eb076', - '099bd7788d3d1035a9ef0703bc8c5e3a', - 'b4127e80ac8ff38350c0561219bd4829', - '1e0c648381278c5f8a1e700117b68481', - 'f31b2395ece58f7ce0050401fbfc6ee3', - 'd7e0c607f6c273191935fe3c503f5edc', - 'c764f9a7d1fe73f7e25914785822228f', - '6631019d7da3f4895f73a8552b594ed7', - '3c6e6ae969948fdf2d5483c25cf4de9b', - '453c7605eb2530da9f73370d0b547b74', - '064065551068620fc01871981d7d78be', - '5fb0fef97089d96b73b2e36c472d3ea3', - '5d031c711a4c967d69230300884043b4', - '6766828a69d373a5cca7b8d6ab02de68', - 'e0b5b6179fa12fca7c6c485fff6c9604', - 'e96485164e8cd8cc67786a695aa1ef41', - '54b31167d328cef00adccaa1a58817a2', - '0220c1091cfbffd04c04b7a4c85042f1', - 'b28fa401faa29491a44196d26a97b207', - '361a44ba78a1d1c83a3ac69c54698427', - '1f1d1e5c34e55fc2befd1d9c8406c6e6', - '5a5b2e61f4bd2d6becf09794c076052c', - 'e876ee447141fcf3340fd2be9e0e7150', - 'f39056ec56716ac8126d028f5b173af3', - '9583a43d92f68823bf7ed48cee58a31f', - '55bad15339b118e2a5499d9c6e4d6712', - 'a13a80b07b2652e875ad2d6085c1d18b', - '32c7e1206e515c1d1e70ce377297d54b', - '6a184b55796ea1e881d770e738b7ab50', - 'f8447318c2425bb9b61867b3893c076e', - '3799d315dcd32cb4ef04f7c696864a97', - '03e5f35bbddb6eabb31d204956553929', - '38a184c0de890152e827818d91262a03', - '89712caccd036a44d57532af16b5edac', - '25262ba7da76224ac55b25fc2c0f72e7', - 'b9a88e9fd06e9f5d61f21ff2f2bbb7a1', - 'e13d2a99df2448b3c3dda18ed4e25d10', - 'ef0b2152ae957394bb790cfa253297ad', - '7d64c455ce832456b15c11d363fb78f5', - 'f8f697616faeb8a37c754cb5753b87a9', - 'ebb22b7ebe0e7ac29ce841cc237a941f', - 'b527639217b053dde60a34d7fb0d576b', - '1b5b1ef52b505d5858eb30d86ccd26a2', - 'fc4654d784f30ab97a72f089ad7e5684', + expect(checksums, [ + '05cdbdf4976a68c33e75e6b57781c5f5', + 'c36ad7dc2f0846ed134029edaeb59195', + '7f90e825f08edafe99ac7314d02f46e0', + '82279ed0fb55f7e02b8e6cf857b5a7b9', + '8aa77a554828663ccfdb30d026caf729', + '6a69060c347c20000354bb9e7cca21f5', + 'c0a1cd20d08aa29044af633dec235b36', + '72a098e698316a60e6ca2b67c4de82b1', + '16dc68a85ea9cab4a9d35c77f9d8bc6c', + 'fbb47d28d4db2082f331a6710ae293f6', + 'c557d0bffbf479b85861a648ceda8912', + '7c23bce4887d70915a5d5824142cb75f', + '88d164985687d11445a1bba4c83b299e', + 'e6b3d1a31ea2ea2c37babbf8a52393de', + 'dfe63dab862fa7789f3bf4ad882c87c7', + 'b146d5dfbcb2bfdd295cdd548832d717', + '4267a4d5f5b7e1ae3278e590cab52e48', + '461e627475397d461da3c985e17466ba', + '2e5d01733c132b2801e3068bf008e023', + 'aee031592879b62e8512cc73a064c883', + '439222774886f776f2da9a5c0051310f', + 'a59d7e43b0a9562518863d6379fddd16', + '90a0e05df0f56c8d33b3bdbe7ff785b3', + 'e00db5df53778da8aaecace162d20325', + 'b4f8ef47ab0a43f0760c68d66297f1a8', + '17c758237c24c96e1d92a4681ba2b889', + 'dd6ee4832b2c11d31a2488f671d13e9a', + '7ac636c075bcc1423e80c635fed6de6c', + '427db33751df11daa8dc9809614b66e6', + 'c8d5918f01d365e0d6c2a1d610a47d1d', + '534fce1b658242d7942f3eb6e4ca987d', + '3dcea3a8a52eebea225eacd44ee370f1', + '55fe838d0d2a01e288b3faed2adc7a04', + '80727044903ebea814198f4001fdebf0', + '6198b46894c081193b9209f9ddb66b3d', + '856c0ffe90c97d9629e847ba1b3bbb67', + '3e3d7e551f1392f53d73fd3362693184', + '5244e64af596a46940892b28739737e2', + '8a875dc22c02d815e16f50386d03195d', + '50464749a3288f2d655ccef290835776', + '1982534a5ba2f13f8ed5b4ba38386d8c', + '012e03aad8221afab6200718f7e68fa6', + '9ddaa64eadc3b21ba48d77062a12bee7', + 'f2b802ce9d7c055f721e017db5582312', + 'abc578f0fe5c4a4c43b185a7940d0dd7', + '771cd5ab05e5838cccf4a75cc224f506', + 'd41f53ff6aca0cdd74bbea8b0c26b83e', + '24c8e4535afc18981f7470cbd05a5787', + 'fddca58e36cc89868114bb399bc6cec2', + 'fec6330fac0d3d9316f2f580602fc06a', + '092c7130962283f35d5de02604cc3852', + '130517517742ea571ab39d69f56c87a0', + 'e17135e1be677fb428a761b6c3b5f421', + '510c5b24f5bbd414917c96444ff41df3', + '75993da8d1508dc1e556096da0a7c00f', + 'aad9665f7c2a8e28e99c92a90d0f2168', + 'bab93955a78ab99e6157b1568e4b03d1', + 'f2ad0bb263fd38d9fba3ca9ed5c7c66b', + '7743132a908a48c183a75d8c25635de6', + '3b326f5a0ef295d3109bcf95a63b446e', + 'e0775404b93fadf74f5bce5410854346', + 'd1fd0e95194d8d4bc513666e2067548c', + '0541de11331a9ca647f7cbde69c1abf4', + 'c8c85515946c890e3056f379ca757cfe', ]); }); } diff --git a/pkgs/native_assets_cli/test/code_assets/code_asset_test.dart b/pkgs/native_assets_cli/test/code_assets/code_asset_test.dart new file mode 100644 index 000000000..7a20292b4 --- /dev/null +++ b/pkgs/native_assets_cli/test/code_assets/code_asset_test.dart @@ -0,0 +1,28 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. 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_internal.dart'; +import 'package:test/test.dart'; + +void main() async { + test('DataAsset', () { + expect( + CodeAsset( + package: 'my_package', + name: 'name', + linkMode: DynamicLoadingBundled(), + os: OS.android, + file: Uri.file('not there'), + architecture: Architecture.riscv64, + ).encode().toJson(), + { + 'architecture': 'riscv64', + 'file': 'not there', + 'id': 'package:my_package/name', + 'link_mode': {'type': 'dynamic_loading_bundle'}, + 'os': 'android', + 'type': 'native_code', + }); + }); +} diff --git a/pkgs/native_assets_cli/test/code_assets/config_test.dart b/pkgs/native_assets_cli/test/code_assets/config_test.dart new file mode 100644 index 000000000..3c4215aed --- /dev/null +++ b/pkgs/native_assets_cli/test/code_assets/config_test.dart @@ -0,0 +1,222 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/src/config.dart' show latestVersion; +import 'package:test/test.dart'; + +void main() async { + late Uri outDirUri; + late Uri outputDirectoryShared; + late String packageName; + late Uri packageRootUri; + late Uri fakeClang; + late Uri fakeLd; + late Uri fakeAr; + late List assets; + late Uri fakeVcVars; + + setUp(() async { + final tempUri = Directory.systemTemp.uri; + outDirUri = tempUri.resolve('out1/'); + outputDirectoryShared = tempUri.resolve('out_shared1/'); + packageName = 'my_package'; + packageRootUri = tempUri.resolve('$packageName/'); + fakeClang = tempUri.resolve('fake_clang'); + fakeLd = tempUri.resolve('fake_ld'); + fakeAr = tempUri.resolve('fake_ar'); + fakeVcVars = tempUri.resolve('vcvarsall.bat'); + + assets = [ + CodeAsset( + package: packageName, + name: 'name', + linkMode: DynamicLoadingBundled(), + os: OS.android, + file: Uri.file('not there'), + architecture: Architecture.riscv64, + ).encode(), + ]; + }); + + // Tests JSON encoding & accessors of code-asset configuration. + void expectCorrectCodeConfigDryRun( + Map json, CodeConfig codeConfig) { + { + 'supported_asset_types': [CodeAsset.type], + 'link_mode_preference': 'prefer-static', + }.forEach((k, v) { + expect(json[k], v); + }); + + expect(() => codeConfig.targetArchitecture, throwsStateError); + expect(codeConfig.targetAndroidNdkApi, null); + expect(codeConfig.linkModePreference, LinkModePreference.preferStatic); + expect(codeConfig.cCompiler.compiler, null); + expect(codeConfig.cCompiler.linker, null); + expect(codeConfig.cCompiler.archiver, null); + } + + void expectCorrectCodeConfig( + Map json, CodeConfig codeConfig) { + { + 'supported_asset_types': [CodeAsset.type], + 'link_mode_preference': 'prefer-static', + 'target_android_ndk_api': 30, + 'target_architecture': 'arm64', + 'c_compiler': { + 'ar': fakeAr.toFilePath(), + 'ld': fakeLd.toFilePath(), + 'cc': fakeClang.toFilePath(), + 'env_script': fakeVcVars.toFilePath(), + 'env_script_arguments': ['arg0', 'arg1'], + }, + }.forEach((k, v) { + expect(json[k], v); + }); + + expect(codeConfig.targetArchitecture, Architecture.arm64); + expect(codeConfig.targetAndroidNdkApi, 30); + expect(codeConfig.linkModePreference, LinkModePreference.preferStatic); + expect(codeConfig.cCompiler.compiler, fakeClang); + expect(codeConfig.cCompiler.linker, fakeLd); + expect(codeConfig.cCompiler.archiver, fakeAr); + } + + test('BuildConfig.codeConfig (dry-run)', () { + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: packageRootUri, + targetOS: OS.android, + buildMode: null, // not available in dry run + supportedAssetTypes: [CodeAsset.type], + ) + ..setupBuildConfig( + linkingEnabled: true, + dryRun: true, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + ) + ..setupCodeConfig( + targetArchitecture: null, // not available in dry run + cCompilerConfig: null, // not available in dry run + linkModePreference: LinkModePreference.preferStatic, + ); + final config = BuildConfig(configBuilder.json); + expectCorrectCodeConfigDryRun(config.json, config.codeConfig); + }); + + test('BuildConfig.codeConfig', () { + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: packageRootUri, + targetOS: OS.android, + buildMode: BuildMode.release, + supportedAssetTypes: [CodeAsset.type], + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + targetAndroidNdkApi: 30, + linkModePreference: LinkModePreference.preferStatic, + cCompilerConfig: CCompilerConfig( + compiler: fakeClang, + linker: fakeLd, + archiver: fakeAr, + envScript: fakeVcVars, + envScriptArgs: ['arg0', 'arg1'], + ), + ); + final config = BuildConfig(configBuilder.json); + expectCorrectCodeConfig(config.json, config.codeConfig); + }); + + test('LinkConfig.{codeConfig,codeAssets}', () { + final configBuilder = LinkConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: packageRootUri, + targetOS: OS.android, + buildMode: BuildMode.release, + supportedAssetTypes: [CodeAsset.type], + ) + ..setupLinkConfig(assets: assets) + ..setupLinkRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outputDirectoryShared, + recordedUsesFile: null, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + targetAndroidNdkApi: 30, + linkModePreference: LinkModePreference.preferStatic, + cCompilerConfig: CCompilerConfig( + compiler: fakeClang, + linker: fakeLd, + archiver: fakeAr, + envScript: fakeVcVars, + envScriptArgs: ['arg0', 'arg1'], + ), + ); + final config = LinkConfig(configBuilder.json); + expectCorrectCodeConfig(config.json, config.codeConfig); + expect(config.encodedAssets, assets); + }); + + test('BuildConfig.codeConfig: invalid architecture', () { + final config = { + 'build_mode': 'release', + 'dry_run': false, + 'linking_enabled': false, + 'link_mode_preference': 'prefer-static', + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_android_ndk_api': 30, + 'target_architecture': 'invalid_architecture', + 'target_os': 'android', + 'supported_asset_types': ['my-asset-type'], + 'version': latestVersion.toString(), + }; + expect( + () => BuildConfig(config).codeConfig, + throwsFormatException, + ); + }); + + test('LinkConfig.codeConfig: invalid architecture', () { + final config = { + 'supported_asset_types': [CodeAsset.type], + 'build_mode': 'release', + 'dry_run': false, + 'link_mode_preference': 'prefer-static', + 'out_dir': outDirUri.toFilePath(), + 'out_dir_shared': outputDirectoryShared.toFilePath(), + 'package_name': packageName, + 'package_root': packageRootUri.toFilePath(), + 'target_android_ndk_api': 30, + 'target_architecture': 'invalid_architecture', + 'target_os': 'android', + 'version': latestVersion.toString(), + }; + expect( + () => LinkConfig(config).codeConfig, + throwsFormatException, + ); + }); +} diff --git a/pkgs/native_assets_cli/test/validator/validator_test.dart b/pkgs/native_assets_cli/test/code_assets/validation_test.dart similarity index 56% rename from pkgs/native_assets_cli/test/validator/validator_test.dart rename to pkgs/native_assets_cli/test/code_assets/validation_test.dart index ba732ce20..e6fab9a4f 100644 --- a/pkgs/native_assets_cli/test/validator/validator_test.dart +++ b/pkgs/native_assets_cli/test/code_assets/validation_test.dart @@ -29,13 +29,12 @@ void main() { await Directory.fromUri(tempUri).delete(recursive: true); }); - BuildConfig makeCodeBuildConfig( - {LinkModePreference linkModePreference = LinkModePreference.dynamic}) { + BuildConfigBuilder makeBuildConfigBuilder({OS os = OS.iOS}) { final configBuilder = BuildConfigBuilder() ..setupHookConfig( packageName: packageName, packageRoot: tempUri, - targetOS: OS.iOS, + targetOS: os, buildMode: BuildMode.release, supportedAssetTypes: [CodeAsset.type], ) @@ -46,116 +45,21 @@ void main() { ..setupBuildRunConfig( outputDirectory: outDirUri, outputDirectoryShared: outDirSharedUri, - ) - ..setupCodeConfig( - targetArchitecture: Architecture.arm64, - targetIOSSdk: IOSSdk.iPhoneOS, - linkModePreference: linkModePreference, ); - return BuildConfig(configBuilder.json); + return configBuilder; } - LinkConfig makeCodeLinkConfig() { - final configBuilder = LinkConfigBuilder() - ..setupHookConfig( - packageName: packageName, - packageRoot: tempUri, - targetOS: OS.iOS, - buildMode: BuildMode.release, - supportedAssetTypes: [CodeAsset.type], - ) - ..setupLinkConfig(assets: []) - ..setupLinkRunConfig( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - recordedUsesFile: null, - ) + BuildConfig makeCodeBuildConfig( + {LinkModePreference linkModePreference = LinkModePreference.dynamic}) { + final builder = makeBuildConfigBuilder() ..setupCodeConfig( targetArchitecture: Architecture.arm64, targetIOSSdk: IOSSdk.iPhoneOS, - linkModePreference: LinkModePreference.dynamic, - ); - return LinkConfig(configBuilder.json); - } - - BuildConfig makeDataBuildConfig() { - final configBuilder = BuildConfigBuilder() - ..setupHookConfig( - packageName: packageName, - packageRoot: tempUri, - targetOS: OS.iOS, - buildMode: BuildMode.release, - supportedAssetTypes: [DataAsset.type]) - ..setupBuildConfig( - linkingEnabled: false, - dryRun: false, - ) - ..setupBuildRunConfig( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, + linkModePreference: linkModePreference, ); - return BuildConfig(configBuilder.json); + return BuildConfig(builder.json); } - test('linking not enabled', () async { - final config = makeCodeBuildConfig(); - final outputBuilder = BuildOutputBuilder(); - final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); - await assetFile.writeAsBytes([1, 2, 3]); - outputBuilder.codeAssets.add( - CodeAsset( - package: config.packageName, - name: 'foo.dart', - file: assetFile.uri, - linkMode: DynamicLoadingBundled(), - os: config.targetOS, - architecture: config.codeConfig.targetArchitecture, - ), - linkInPackage: 'bar', - ); - final errors = - await validateBuildOutput(config, BuildOutput(outputBuilder.json)); - expect( - errors, - contains(contains('linkingEnabled is false')), - ); - }); - - test('supported asset type', () async { - final config = makeCodeBuildConfig(); - final outputBuilder = BuildOutputBuilder(); - final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); - await assetFile.writeAsBytes([1, 2, 3]); - outputBuilder.dataAssets.add(DataAsset( - package: config.packageName, - name: 'foo.txt', - file: assetFile.uri, - )); - final errors = - await validateBuildOutput(config, BuildOutput(outputBuilder.json)); - expect( - errors, - contains(contains('"data" is not a supported asset type')), - ); - }); - - test('file exists', () async { - final config = makeCodeBuildConfig(); - final outputBuilder = BuildOutputBuilder(); - final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); - outputBuilder.dataAssets.add(DataAsset( - package: config.packageName, - name: 'foo.txt', - file: assetFile.uri, - )); - final errors = await validateDataAssetBuildOutput( - config, BuildOutput(outputBuilder.json)); - expect( - errors, - contains(contains('which does not exist')), - ); - }); - test('file not set', () async { final config = makeCodeBuildConfig(); final outputBuilder = BuildOutputBuilder(); @@ -279,67 +183,6 @@ void main() { ); }); - test('asset id in wrong package', () async { - final config = makeDataBuildConfig(); - final outputBuilder = BuildOutputBuilder(); - final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); - await assetFile.writeAsBytes([1, 2, 3]); - outputBuilder.dataAssets.add(DataAsset( - package: 'different_package', - name: 'foo.txt', - file: assetFile.uri, - )); - final errors = await validateDataAssetBuildOutput( - config, BuildOutput(outputBuilder.json)); - expect( - errors, - contains(contains('Data asset must have package name my_package')), - ); - }); - - test('duplicate asset id', () async { - final config = makeDataBuildConfig(); - final outputBuilder = BuildOutputBuilder(); - final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); - await assetFile.writeAsBytes([1, 2, 3]); - outputBuilder.dataAssets.addAll([ - DataAsset( - package: config.packageName, - name: 'foo.txt', - file: assetFile.uri, - ), - DataAsset( - package: config.packageName, - name: 'foo.txt', - file: assetFile.uri, - ), - ]); - final errors = await validateDataAssetBuildOutput( - config, BuildOutput(outputBuilder.json)); - expect( - errors, - contains(contains('More than one')), - ); - }); - - test('link hook validation', () async { - final config = makeCodeLinkConfig(); - final outputBuilder = LinkOutputBuilder(); - final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); - await assetFile.writeAsBytes([1, 2, 3]); - outputBuilder.dataAssets.add(DataAsset( - package: config.packageName, - name: 'foo.txt', - file: assetFile.uri, - )); - final errors = - await validateLinkOutput(config, LinkOutput(outputBuilder.json)); - expect( - errors, - contains(contains('"data" is not a supported asset type')), - ); - }); - test('duplicate dylib name', () async { final config = makeCodeBuildConfig(); final outputBuilder = BuildOutputBuilder(); @@ -371,4 +214,65 @@ void main() { contains(contains('Duplicate dynamic library file name')), ); }); + + group('BuildConfig.codeConfig validation', () { + test('Missing targetIOSVersion', () async { + final builder = makeBuildConfigBuilder(os: OS.iOS) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + linkModePreference: LinkModePreference.dynamic); + final errors = await validateCodeBuildConfig(BuildConfig(builder.json)); + expect( + errors, + contains( + contains('BuildConfig.codeConfig.targetIOSVersion was missing'))); + expect( + errors, + contains( + contains('BuildConfig.codeConfig.targetIOSSdk was missing'))); + }); + test('Missing targetAndroidNdkApi', () async { + final builder = makeBuildConfigBuilder(os: OS.android) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + linkModePreference: LinkModePreference.dynamic); + expect( + await validateCodeBuildConfig(BuildConfig(builder.json)), + contains(contains( + 'BuildConfig.codeConfig.targetAndroidNdkApi was missing'))); + }); + test('Missing targetMacOSVersion', () async { + final builder = makeBuildConfigBuilder(os: OS.macOS) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + linkModePreference: LinkModePreference.dynamic); + expect( + await validateCodeBuildConfig(BuildConfig(builder.json)), + contains(contains( + 'BuildConfig.codeConfig.targetMacOSVersion was missing'))); + }); + test('Nonexisting compiler/archiver/linker/envScript', () async { + final nonExistent = outDirUri.resolve('foo baz'); + final builder = makeBuildConfigBuilder(os: OS.linux) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + linkModePreference: LinkModePreference.dynamic, + cCompilerConfig: CCompilerConfig( + compiler: nonExistent, + linker: nonExistent, + archiver: nonExistent, + envScript: nonExistent, + )); + final errors = await validateCodeBuildConfig(BuildConfig(builder.json)); + + bool matches(String error, String field) => + RegExp('BuildConfig.codeConfig.$field (.*foo baz).* does not exist.') + .hasMatch(error); + + expect(errors.any((e) => matches(e, 'compiler')), true); + expect(errors.any((e) => matches(e, 'linker')), true); + expect(errors.any((e) => matches(e, 'archiver')), true); + expect(errors.any((e) => matches(e, 'envScript')), true); + }); + }); } diff --git a/pkgs/native_assets_cli/test/data_assets/data_asset_test.dart b/pkgs/native_assets_cli/test/data_assets/data_asset_test.dart new file mode 100644 index 000000000..b64205a81 --- /dev/null +++ b/pkgs/native_assets_cli/test/data_assets/data_asset_test.dart @@ -0,0 +1,23 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. 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_internal.dart'; +import 'package:test/test.dart'; + +void main() async { + test('DataAsset', () { + expect( + DataAsset( + package: 'my_package', + name: 'name', + file: Uri.file('not there'), + ).encode().toJson(), + { + 'file': 'not there', + 'package': 'my_package', + 'name': 'name', + 'type': 'data', + }); + }); +} diff --git a/pkgs/native_assets_cli/test/data_assets/validation_test.dart b/pkgs/native_assets_cli/test/data_assets/validation_test.dart new file mode 100644 index 000000000..21b9ed1c3 --- /dev/null +++ b/pkgs/native_assets_cli/test/data_assets/validation_test.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:test/test.dart'; + +void main() { + late Uri tempUri; + late Uri outDirUri; + late Uri outDirSharedUri; + late String packageName; + late Uri packageRootUri; + + setUp(() async { + tempUri = (await Directory.systemTemp.createTemp()).uri; + outDirUri = tempUri.resolve('out/'); + await Directory.fromUri(outDirUri).create(); + outDirSharedUri = tempUri.resolve('out_shared/'); + await Directory.fromUri(outDirSharedUri).create(); + packageName = 'my_package'; + packageRootUri = tempUri.resolve('$packageName/'); + await Directory.fromUri(packageRootUri).create(); + }); + + tearDown(() async { + await Directory.fromUri(tempUri).delete(recursive: true); + }); + + BuildConfig makeDataBuildConfig() { + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + supportedAssetTypes: [DataAsset.type]) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outDirSharedUri, + ); + return BuildConfig(configBuilder.json); + } + + test('file exists', () async { + final config = makeDataBuildConfig(); + final outputBuilder = BuildOutputBuilder(); + final assetFile = File.fromUri(outDirUri.resolve('foo.txt')); + outputBuilder.dataAssets.add(DataAsset( + package: config.packageName, + name: 'foo.txt', + file: assetFile.uri, + )); + final errors = await validateDataAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); + expect( + errors, + contains(contains('which does not exist')), + ); + }); + + test('asset id in wrong package', () async { + final config = makeDataBuildConfig(); + final outputBuilder = BuildOutputBuilder(); + final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); + await assetFile.writeAsBytes([1, 2, 3]); + outputBuilder.dataAssets.add(DataAsset( + package: 'different_package', + name: 'foo.txt', + file: assetFile.uri, + )); + final errors = await validateDataAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); + expect( + errors, + contains(contains('Data asset must have package name my_package')), + ); + }); + + test('duplicate asset id', () async { + final config = makeDataBuildConfig(); + final outputBuilder = BuildOutputBuilder(); + final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); + await assetFile.writeAsBytes([1, 2, 3]); + outputBuilder.dataAssets.addAll([ + DataAsset( + package: config.packageName, + name: 'foo.txt', + file: assetFile.uri, + ), + DataAsset( + package: config.packageName, + name: 'foo.txt', + file: assetFile.uri, + ), + ]); + final errors = await validateDataAssetBuildOutput( + config, BuildOutput(outputBuilder.json)); + expect( + errors, + contains(contains('More than one')), + ); + }); +} diff --git a/pkgs/native_assets_cli/test/link_config_test.dart b/pkgs/native_assets_cli/test/link_config_test.dart index af6dd26a1..93f8c14e2 100644 --- a/pkgs/native_assets_cli/test/link_config_test.dart +++ b/pkgs/native_assets_cli/test/link_config_test.dart @@ -14,9 +14,6 @@ void main() async { late Uri outputDirectoryShared; late String packageName; late Uri packageRootUri; - late Uri fakeClang; - late Uri fakeLd; - late Uri fakeAr; late List assets; setUp(() async { @@ -25,24 +22,9 @@ void main() async { outputDirectoryShared = tempUri.resolve('out_shared1/'); packageName = 'my_package'; packageRootUri = tempUri.resolve('$packageName/'); - fakeClang = tempUri.resolve('fake_clang'); - fakeLd = tempUri.resolve('fake_ld'); - fakeAr = tempUri.resolve('fake_ar'); - assets = [ - DataAsset( - package: packageName, - name: 'name', - file: Uri.file('nonexistent'), - ).encode(), - CodeAsset( - package: packageName, - name: 'name2', - linkMode: DynamicLoadingBundled(), - os: OS.android, - file: Uri.file('not there'), - architecture: Architecture.riscv64, - ).encode(), + for (int i = 0; i < 3; i++) + EncodedAsset('my-asset-type', {'a-$i': 'v-$i'}) ]; }); @@ -53,41 +35,25 @@ void main() async { packageRoot: packageRootUri, targetOS: OS.android, buildMode: BuildMode.release, - supportedAssetTypes: [CodeAsset.type], + supportedAssetTypes: ['asset-type-1', 'asset-type-2'], ) ..setupLinkConfig(assets: assets) ..setupLinkRunConfig( outputDirectory: outDirUri, outputDirectoryShared: outputDirectoryShared, recordedUsesFile: null, - ) - ..setupCodeConfig( - targetArchitecture: Architecture.arm64, - targetAndroidNdkApi: 30, - linkModePreference: LinkModePreference.preferStatic, - cCompilerConfig: CCompilerConfig( - compiler: fakeClang, - linker: fakeLd, - archiver: fakeAr, - ), ); final config = LinkConfig(configBuilder.json); final expectedConfigJson = { 'build_mode': 'release', - 'supported_asset_types': [CodeAsset.type], - 'link_mode_preference': 'prefer-static', + 'supported_asset_types': ['asset-type-1', 'asset-type-2'], 'out_dir': outDirUri.toFilePath(), 'out_dir_shared': outputDirectoryShared.toFilePath(), 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'arm64', 'target_os': 'android', 'version': latestVersion.toString(), - 'c_compiler.ar': fakeAr.toFilePath(), - 'c_compiler.ld': fakeLd.toFilePath(), - 'c_compiler.cc': fakeClang.toFilePath(), 'assets': [for (final asset in assets) asset.toJson()], }; expect(config.json, expectedConfigJson); @@ -100,16 +66,8 @@ void main() async { expect(config.packageRoot, packageRootUri); expect(config.targetOS, OS.android); expect(config.buildMode, BuildMode.release); - expect(config.supportedAssetTypes, [CodeAsset.type]); + expect(config.supportedAssetTypes, ['asset-type-1', 'asset-type-2']); expect(config.encodedAssets, assets); - - final codeConfig = config.codeConfig; - expect(codeConfig.targetArchitecture, Architecture.arm64); - expect(codeConfig.targetAndroidNdkApi, 30); - expect(codeConfig.linkModePreference, LinkModePreference.preferStatic); - expect(codeConfig.cCompiler.compiler, fakeClang); - expect(codeConfig.cCompiler.linker, fakeLd); - expect(codeConfig.cCompiler.archiver, fakeAr); }); group('LinkConfig FormatExceptions', () { @@ -138,28 +96,6 @@ void main() async { ); }); } - - test('invalid architecture', () { - final config = { - 'supported_asset_types': [CodeAsset.type], - 'build_mode': 'release', - 'dry_run': false, - 'link_mode_preference': 'prefer-static', - 'out_dir': outDirUri.toFilePath(), - 'out_dir_shared': outputDirectoryShared.toFilePath(), - 'package_name': packageName, - 'package_root': packageRootUri.toFilePath(), - 'target_android_ndk_api': 30, - 'target_architecture': 'invalid_architecture', - 'target_os': 'android', - 'version': latestVersion.toString(), - }; - expect( - () => LinkConfig(config).codeConfig, - throwsFormatException, - ); - }); - test('LinkConfig FormatExceptions', () { expect( () => LinkConfig({}), diff --git a/pkgs/native_assets_cli/test/link_output_test.dart b/pkgs/native_assets_cli/test/link_output_test.dart new file mode 100644 index 000000000..32e34d695 --- /dev/null +++ b/pkgs/native_assets_cli/test/link_output_test.dart @@ -0,0 +1,61 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. 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_internal.dart'; +import 'package:native_assets_cli/src/utils/datetime.dart'; +import 'package:test/test.dart'; + +void main() { + test('LinkOutputBuilder->JSON->LinkOutput', () { + final assets = [ + for (int i = 0; i < 3; i++) + EncodedAsset('my-asset-type', {'a-$i': 'v-$i'}) + ]; + final uris = [ + for (int i = 0; i < 3; ++i) Uri.file('path$i'), + ]; + final before = DateTime.now().roundDownToSeconds(); + final builder = LinkOutputBuilder(); + final after = DateTime.now().roundDownToSeconds(); + + builder.addDependency(uris.take(1).single); + builder.addDependencies(uris.skip(1).toList()); + + builder.addEncodedAsset(assets.take(1).single); + builder.addEncodedAssets(assets.skip(1).take(2).toList()); + + final config = BuildOutput(builder.json); + expect(config.timestamp, greaterThanOrEqualTo(before)); + expect(config.timestamp, lessThanOrEqualTo(after)); + expect(config.timestamp, + lessThanOrEqualTo(config.timestamp.roundDownToSeconds())); + + // The JSON format of the link output. + { + 'version': '1.5.0', + 'dependencies': ['path0', 'path1', 'path2'], + 'assets': [ + {'a-0': 'v-0', 'type': 'my-asset-type'}, + {'a-1': 'v-1', 'type': 'my-asset-type'}, + {'a-2': 'v-2', 'type': 'my-asset-type'} + ] + }.forEach((k, v) { + expect(config.json[k], equals(v)); + }); + }); + + for (final version in ['9001.0.0', '0.0.1']) { + test('LinkOutput version $version', () { + expect( + () => LinkOutput({'version': version}), + throwsA(predicate( + (e) => + e is FormatException && + e.message.contains(version) && + e.message.contains(HookOutput.latestVersion.toString()), + )), + ); + }); + } +} diff --git a/pkgs/native_assets_cli/test/validation_test.dart b/pkgs/native_assets_cli/test/validation_test.dart new file mode 100644 index 000000000..b8a509c36 --- /dev/null +++ b/pkgs/native_assets_cli/test/validation_test.dart @@ -0,0 +1,123 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:test/test.dart'; + +void main() { + late Uri tempUri; + late Uri outDirUri; + late Uri outDirSharedUri; + late String packageName; + late Uri packageRootUri; + + setUp(() async { + tempUri = (await Directory.systemTemp.createTemp()).uri; + outDirUri = tempUri.resolve('out/'); + await Directory.fromUri(outDirUri).create(); + outDirSharedUri = tempUri.resolve('out_shared/'); + await Directory.fromUri(outDirSharedUri).create(); + packageName = 'my_package'; + packageRootUri = tempUri.resolve('$packageName/'); + await Directory.fromUri(packageRootUri).create(); + }); + + tearDown(() async { + await Directory.fromUri(tempUri).delete(recursive: true); + }); + + BuildConfig makeBuildConfig() { + final configBuilder = BuildConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + supportedAssetTypes: ['my-asset-type'], + ) + ..setupBuildConfig( + linkingEnabled: false, + dryRun: false, + ) + ..setupBuildRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outDirSharedUri, + ); + return BuildConfig(configBuilder.json); + } + + LinkConfig makeCodeLinkConfig() { + final configBuilder = LinkConfigBuilder() + ..setupHookConfig( + packageName: packageName, + packageRoot: tempUri, + targetOS: OS.iOS, + buildMode: BuildMode.release, + supportedAssetTypes: [CodeAsset.type], + ) + ..setupLinkConfig(assets: []) + ..setupLinkRunConfig( + outputDirectory: outDirUri, + outputDirectoryShared: outDirSharedUri, + recordedUsesFile: null, + ) + ..setupCodeConfig( + targetArchitecture: Architecture.arm64, + targetIOSSdk: IOSSdk.iPhoneOS, + linkModePreference: LinkModePreference.dynamic, + ); + return LinkConfig(configBuilder.json); + } + + test('linking not enabled', () async { + final config = makeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); + final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); + await assetFile.writeAsBytes([1, 2, 3]); + outputBuilder.addEncodedAsset( + EncodedAsset('my-asset-type', {}), + linkInPackage: 'bar', + ); + final errors = + await validateBuildOutput(config, BuildOutput(outputBuilder.json)); + expect( + errors, + contains(contains('linkingEnabled is false')), + ); + }); + + test('supported asset type', () async { + final config = makeBuildConfig(); + final outputBuilder = BuildOutputBuilder(); + final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); + await assetFile.writeAsBytes([1, 2, 3]); + outputBuilder.addEncodedAsset(EncodedAsset('baz', {})); + final errors = + await validateBuildOutput(config, BuildOutput(outputBuilder.json)); + expect( + errors, + contains(contains('"baz" is not a supported asset type')), + ); + }); + + test('link hook validation', () async { + final config = makeCodeLinkConfig(); + final outputBuilder = LinkOutputBuilder(); + final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); + await assetFile.writeAsBytes([1, 2, 3]); + outputBuilder.dataAssets.add(DataAsset( + package: config.packageName, + name: 'foo.txt', + file: assetFile.uri, + )); + final errors = + await validateLinkOutput(config, LinkOutput(outputBuilder.json)); + expect( + errors, + contains(contains('"data" is not a supported asset type')), + ); + }); +} diff --git a/pkgs/native_toolchain_c/CHANGELOG.md b/pkgs/native_toolchain_c/CHANGELOG.md index 3715b49c8..703100a8e 100644 --- a/pkgs/native_toolchain_c/CHANGELOG.md +++ b/pkgs/native_toolchain_c/CHANGELOG.md @@ -1,7 +1,9 @@ -## 0.5.5-wip +## 0.6.0 - Address analyzer info diagnostic about multi-line if requiring a block body. -- Bump `package:native_assets_cli` to `0.9.0`. +- Bump `package:native_assets_cli` to `0.9.0`. This makes + `package:native_toolchain_c` now take `BuildOutputBuilder` & + `LinkOutputBuilder` objects. ## 0.5.4 From cee128cf674064d029f47c7202a0302c8f5046d8 Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Tue, 15 Oct 2024 09:46:59 +0200 Subject: [PATCH 4/7] Decouple asset types & base support in imports, ... --- .../lib/src/build_runner/build_runner.dart | 47 ++----------------- .../build_runner/build_dependencies_test.dart | 4 +- .../build_runner_asset_id_test.dart | 8 ++-- .../build_runner_build_dry_run_test.dart | 4 +- ...build_runner_build_output_format_test.dart | 2 +- .../build_runner_caching_test.dart | 24 +++++----- .../build_runner_failure_test.dart | 12 ++--- .../build_runner_non_root_package_test.dart | 4 +- .../build_runner_run_in_isolation_test.dart | 4 +- .../test/build_runner/build_runner_test.dart | 8 ++-- .../build_runner/concurrency_test_helper.dart | 4 +- .../build_runner/conflicting_dylib_test.dart | 12 ++--- .../fail_on_os_sdk_version_test.dart | 6 +-- .../test/build_runner/link_test.dart | 8 ++-- .../packaging_preference_test.dart | 16 +++---- .../test/build_runner/wrong_linker_test.dart | 4 +- pkgs/native_assets_builder/test/helpers.dart | 7 ++- .../test_data/add_asset_link/hook/build.dart | 2 +- .../test_data/add_asset_link/hook/link.dart | 2 +- .../test_data/complex_link/hook/build.dart | 2 +- .../test_data/complex_link/hook/link.dart | 2 +- .../complex_link_helper/hook/build.dart | 2 +- .../test_data/drop_dylib_link/hook/build.dart | 2 +- .../test_data/drop_dylib_link/hook/link.dart | 2 +- .../fail_on_os_sdk_version/hook/build.dart | 2 +- .../hook/build.dart | 2 +- .../hook/link.dart | 2 +- .../native_add_duplicate/hook/build.dart | 7 +-- .../native_add_duplicate/hook/link.dart | 2 +- .../no_asset_for_link/hook/link.dart | 6 ++- .../simple_data_asset/hook/build.dart | 2 +- .../test_data/simple_link/hook/build.dart | 2 +- .../test_data/simple_link/hook/link.dart | 2 +- .../test_data/transformer/hook/build.dart | 2 +- .../treeshaking_native_libs/hook/build.dart | 2 +- .../treeshaking_native_libs/hook/link.dart | 2 +- .../test_data/wrong_linker/hook/build.dart | 2 +- .../wrong_namespace_asset/hook/build.dart | 2 +- .../example/build/local_asset/hook/build.dart | 2 +- .../build/local_asset/test/build_test.dart | 2 +- .../link/package_with_assets/hook/build.dart | 2 +- .../link/package_with_assets/hook/link.dart | 2 +- pkgs/native_assets_cli/lib/code_assets.dart | 35 ++++++++++++++ .../lib/code_assets_builder.dart | 19 ++++++++ .../lib/code_assets_testing.dart | 6 +++ pkgs/native_assets_cli/lib/data_assets.dart | 20 ++++++++ .../lib/data_assets_builder.dart | 18 +++++++ .../lib/native_assets_cli.dart | 44 ++++------------- .../lib/native_assets_cli_builder.dart | 26 ++++++++++ .../lib/native_assets_cli_internal.dart | 47 ++----------------- .../lib/src/code_assets/config.dart | 16 ++++--- .../lib/src/code_assets/testing.dart | 1 + .../lib/src/code_assets/validation.dart | 8 ++-- pkgs/native_assets_cli/lib/src/config.dart | 41 ++++++++++++++-- .../lib/src/data_assets/config.dart | 16 ++++--- .../lib/src/data_assets/validation.dart | 2 +- .../lib/src/{model => }/metadata.dart | 4 +- .../native_assets_cli/lib/src/validation.dart | 2 +- pkgs/native_assets_cli/lib/test.dart | 6 +-- .../test/api/asset_test.dart | 3 +- .../test/api/build_test.dart | 5 +- .../test/api/target_test.dart | 2 +- .../test/build_config_test.dart | 2 +- .../test/build_output_test.dart | 2 +- .../native_assets_cli/test/checksum_test.dart | 3 +- .../test/code_assets/code_asset_test.dart | 2 +- .../test/code_assets/config_test.dart | 2 +- .../test/code_assets/validation_test.dart | 10 ++-- .../test/data_assets/data_asset_test.dart | 2 +- .../test/data_assets/validation_test.dart | 2 +- .../test/example/local_asset_test.dart | 2 +- .../test/example/native_add_library_test.dart | 2 +- .../example/native_dynamic_linking_test.dart | 2 +- pkgs/native_assets_cli/test/helpers.dart | 6 +-- .../test/link_config_test.dart | 13 ++--- .../test/link_output_test.dart | 2 +- .../test/model/asset_test.dart | 3 +- .../test/model/dependencies_test.dart | 2 +- .../test/model/link_mode_test.dart | 2 +- .../test/model/metadata_test.dart | 2 +- .../test/model/target_test.dart | 2 +- .../test/validation_test.dart | 43 +---------------- .../lib/src/cbuilder/cbuilder.dart | 2 +- .../lib/src/cbuilder/clinker.dart | 2 +- .../lib/src/cbuilder/compiler_resolver.dart | 2 +- .../lib/src/cbuilder/ctool.dart | 16 ++++--- .../lib/src/cbuilder/linkmode.dart | 2 +- .../lib/src/cbuilder/run_cbuilder.dart | 2 +- .../lib/src/native_toolchain/android_ndk.dart | 2 +- .../lib/src/native_toolchain/gcc.dart | 2 +- .../lib/src/native_toolchain/msvc.dart | 2 +- .../lib/src/native_toolchain/recognizer.dart | 2 +- .../lib/src/tool/tool_resolver.dart | 2 +- .../cbuilder/cbuilder_build_failure_test.dart | 1 - .../cbuilder/cbuilder_cross_android_test.dart | 1 - .../cbuilder/cbuilder_cross_ios_test.dart | 1 - .../cbuilder_cross_linux_host_test.dart | 1 - .../cbuilder_cross_macos_host_test.dart | 1 - .../cbuilder_cross_windows_host_test.dart | 1 - .../test/cbuilder/cbuilder_test.dart | 1 - .../test/cbuilder/compiler_resolver_test.dart | 1 - .../test/cbuilder/objective_c_test.dart | 1 - .../test/clinker/build_testfiles.dart | 1 - .../test/clinker/objects_test.dart | 1 - .../test/clinker/throws_test.dart | 1 - .../test/clinker/treeshake_cross_test.dart | 2 +- .../test/clinker/treeshake_helper.dart | 1 - .../test/clinker/treeshake_test.dart | 2 +- pkgs/native_toolchain_c/test/helpers.dart | 4 +- .../test/tool/tool_resolver_test.dart | 1 - 110 files changed, 366 insertions(+), 352 deletions(-) create mode 100644 pkgs/native_assets_cli/lib/code_assets.dart create mode 100644 pkgs/native_assets_cli/lib/code_assets_builder.dart create mode 100644 pkgs/native_assets_cli/lib/code_assets_testing.dart create mode 100644 pkgs/native_assets_cli/lib/data_assets.dart create mode 100644 pkgs/native_assets_cli/lib/data_assets_builder.dart create mode 100644 pkgs/native_assets_cli/lib/native_assets_cli_builder.dart rename pkgs/native_assets_cli/lib/src/{model => }/metadata.dart (93%) diff --git a/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart b/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart index 70506752f..e0b3d3949 100644 --- a/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart +++ b/pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart @@ -7,7 +7,6 @@ import 'dart:convert'; import 'dart:io'; import 'package:logging/logging.dart'; -import 'package:native_assets_cli/native_assets_cli.dart' as api; import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:package_config/package_config.dart'; @@ -63,7 +62,7 @@ typedef ApplicationAssetValidator = Future Function( /// and flutter_tools (for `flutter run` and `flutter build`). /// /// The native assets build runner does not support reentrancy for identical -/// [api.BuildConfig] and [api.LinkConfig]! For more info see: +/// [BuildConfig] and [LinkConfig]! For more info see: /// https://github.com/dart-lang/native/issues/1319 class NativeAssetsBuildRunner { final Logger logger; @@ -85,7 +84,7 @@ class NativeAssetsBuildRunner { /// [runPackageName] are built. /// /// The native assets build runner does not support reentrancy for identical - /// [api.BuildConfig] and [api.LinkConfig]! For more info see: + /// [BuildConfig] and [LinkConfig]! For more info see: /// https://github.com/dart-lang/native/issues/1319 Future build({ required BuildConfigCreator configCreator, @@ -193,7 +192,7 @@ class NativeAssetsBuildRunner { /// [runPackageName] are linked. /// /// The native assets build runner does not support reentrancy for identical - /// [api.BuildConfig] and [api.LinkConfig]! For more info see: + /// [BuildConfig] and [LinkConfig]! For more info see: /// https://github.com/dart-lang/native/issues/1319 Future link({ required LinkConfigCreator configCreator, @@ -872,43 +871,3 @@ extension on DateTime { extension on Uri { Uri get parent => File(toFilePath()).parent.uri; } - -extension OSArchitectures on OS { - Set get architectures => _osTargets[this]!; -} - -const _osTargets = { - OS.android: { - Architecture.arm, - Architecture.arm64, - Architecture.ia32, - Architecture.x64, - Architecture.riscv64, - }, - OS.fuchsia: { - Architecture.arm64, - Architecture.x64, - }, - OS.iOS: { - Architecture.arm, - Architecture.arm64, - Architecture.x64, - }, - OS.linux: { - Architecture.arm, - Architecture.arm64, - Architecture.ia32, - Architecture.riscv32, - Architecture.riscv64, - Architecture.x64, - }, - OS.macOS: { - Architecture.arm64, - Architecture.x64, - }, - OS.windows: { - Architecture.arm64, - Architecture.ia32, - Architecture.x64, - }, -}; diff --git a/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart b/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart index 1a4e55b0d..fd248d658 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_dependencies_test.dart @@ -32,9 +32,9 @@ void main() async { dartExecutable, capturedLogs: logMessages, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect( logMessages.join('\n'), diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart index a35f650cb..b31dd3c4a 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_asset_id_test.dart @@ -28,9 +28,9 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ); final fullLog = logMessages.join('\n'); expect(result, isNull); @@ -64,9 +64,9 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ); expect(result, isNotNull); } diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart index b87296a64..6fe8f68a6 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_build_dry_run_test.dart @@ -36,9 +36,9 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect(dryRunResult.encodedAssets.length, 1); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart index 9faefd081..68ddeba44 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_build_output_format_test.dart @@ -36,7 +36,7 @@ void main() async { supportedAssetTypes: [], configValidator: (config) async => [], buildValidator: (config, output) async => [], - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ); final fullLog = logMessages.join('\n'); expect(result, isNull); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart index e97f195d9..e83948421 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_caching_test.dart @@ -34,9 +34,9 @@ void main() async { dartExecutable, capturedLogs: logMessages, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect( logMessages.join('\n'), @@ -61,9 +61,9 @@ void main() async { dartExecutable, capturedLogs: logMessages, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect( logMessages.join('\n'), @@ -106,9 +106,9 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; await expectSymbols( asset: CodeAsset.fromEncoded(result.encodedAssets.single), @@ -126,9 +126,9 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; await expectSymbols( asset: CodeAsset.fromEncoded(result.encodedAssets.single), @@ -161,9 +161,9 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; { final compiledHook = logMessages @@ -189,9 +189,9 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; { final compiledHook = logMessages diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart index b3b10d930..ce1130ba5 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_failure_test.dart @@ -29,9 +29,9 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect(result.encodedAssets.length, 1); await expectSymbols( @@ -57,9 +57,9 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ); final fullLog = logMessages.join('\n'); expect(result, isNull); @@ -85,9 +85,9 @@ void main() async { logger, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect(result.encodedAssets.length, 1); await expectSymbols( diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart index 3c32e8447..825bbe66a 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_non_root_package_test.dart @@ -33,7 +33,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], configValidator: validateDataAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect(result.encodedAssets, isEmpty); expect(result.dependencies, isEmpty); @@ -50,7 +50,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type], configValidator: validateDataAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect(result.encodedAssets, isNotEmpty); expect( diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart index 752453e1a..45f6bbc17 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_run_in_isolation_test.dart @@ -61,9 +61,9 @@ void main() async { // Prevent any other environment variables. includeParentEnvironment: false, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect(result.encodedAssets.length, 1); }); diff --git a/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart b/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart index acc4f1d00..51a5d68f2 100644 --- a/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/build_runner_test.dart @@ -37,10 +37,10 @@ void main() async { logger, dartExecutable, capturedLogs: logMessages, - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, supportedAssetTypes: [CodeAsset.type], buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect( logMessages.join('\n'), @@ -65,9 +65,9 @@ void main() async { capturedLogs: logMessages, packageLayout: packageLayout, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect( false, diff --git a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart index f738f5494..163a2f40c 100644 --- a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart +++ b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart @@ -39,13 +39,13 @@ void main(List args) async { supportedAssetTypes: [CodeAsset.type, DataAsset.type], configValidator: (config) async => [ ...await validateDataAssetBuildConfig(config), - ...await validateCodeBuildConfig(config), + ...await validateCodeAssetBuildConfig(config), ], buildValidator: (config, output) async => [ ...await validateCodeAssetBuildOutput(config, output), ...await validateDataAssetBuildOutput(config, output), ], - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ); if (result == null) { throw Error(); diff --git a/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart b/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart index e5d2d8cd4..ee0f53b55 100644 --- a/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/conflicting_dylib_test.dart @@ -28,9 +28,9 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ); final fullLog = logMessages.join('\n'); expect(result, isNull); @@ -59,9 +59,9 @@ void main() async { linkingEnabled: true, dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; final linkResult = await link( @@ -70,9 +70,9 @@ void main() async { dartExecutable, buildResult: buildResult, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeLinkConfig, + configValidator: validateCodeAssetLinkConfig, linkValidator: validateCodeAssetLinkOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ); // Application validation error due to conflicting dylib name. expect(linkResult, isNull); diff --git a/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart b/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart index 10e42ab75..f56edf833 100644 --- a/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/fail_on_os_sdk_version_test.dart @@ -76,7 +76,7 @@ void main() async { supportedAssetTypes: [CodeAsset.type, DataAsset.type], buildConfigValidator: (config) async => [ ...await validateDataAssetBuildConfig(config), - ...await validateCodeBuildConfig(config), + ...await validateCodeAssetBuildConfig(config), ], buildValidator: (config, output) async => [ ...await validateCodeAssetBuildOutput(config, output), @@ -84,13 +84,13 @@ void main() async { ], linkConfigValidator: (config) async => [ ...await validateDataAssetLinkConfig(config), - ...await validateCodeLinkConfig(config), + ...await validateCodeAssetLinkConfig(config), ], linkValidator: (config, output) async => [ ...await validateCodeAssetLinkOutput(config, output), ...await validateDataAssetLinkOutput(config, output), ], - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ); final fullLog = logMessages.join('\n'); if (hook == 'build') { diff --git a/pkgs/native_assets_builder/test/build_runner/link_test.dart b/pkgs/native_assets_builder/test/build_runner/link_test.dart index 09417a403..87967cb49 100644 --- a/pkgs/native_assets_builder/test/build_runner/link_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/link_test.dart @@ -204,9 +204,9 @@ void main() async { dartExecutable, linkingEnabled: true, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect(buildResult.encodedAssets.length, 0); expect(buildResult.encodedAssetsForLinking.length, 1); @@ -219,9 +219,9 @@ void main() async { buildResult: buildResult, capturedLogs: logMessages, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeLinkConfig, + configValidator: validateCodeAssetLinkConfig, linkValidator: validateCodeAssetLinkOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; expect(linkResult.encodedAssets.length, 1); expect(linkResult.encodedAssets.first.type, CodeAsset.type); diff --git a/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart b/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart index 15ec6f5ca..140d7954f 100644 --- a/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/packaging_preference_test.dart @@ -27,9 +27,9 @@ void main() async { dartExecutable, linkModePreference: LinkModePreference.dynamic, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; final resultPreferDynamic = (await build( @@ -38,9 +38,9 @@ void main() async { dartExecutable, linkModePreference: LinkModePreference.preferDynamic, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; final resultStatic = (await build( @@ -49,9 +49,9 @@ void main() async { dartExecutable, linkModePreference: LinkModePreference.static, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; final resultPreferStatic = (await build( @@ -60,9 +60,9 @@ void main() async { dartExecutable, linkModePreference: LinkModePreference.preferStatic, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, ))!; // This package honors preferences. diff --git a/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart b/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart index 1ff2f8ff2..e004fe581 100644 --- a/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart +++ b/pkgs/native_assets_builder/test/build_runner/wrong_linker_test.dart @@ -28,9 +28,9 @@ void main() async { createCapturingLogger(logMessages, level: Level.SEVERE), dartExecutable, supportedAssetTypes: [CodeAsset.type], - configValidator: validateCodeBuildConfig, + configValidator: validateCodeAssetBuildConfig, buildValidator: validateCodeAssetBuildOutput, - applicationAssetValidator: validateCodeAssetsInApplication, + applicationAssetValidator: validateCodeAssetInApplication, linkingEnabled: true, ); final fullLog = logMessages.join('\n'); diff --git a/pkgs/native_assets_builder/test/helpers.dart b/pkgs/native_assets_builder/test/helpers.dart index 85759c73b..3bb4c710a 100644 --- a/pkgs/native_assets_builder/test/helpers.dart +++ b/pkgs/native_assets_builder/test/helpers.dart @@ -8,11 +8,14 @@ import 'dart:io'; import 'package:logging/logging.dart'; import 'package:native_assets_builder/src/utils/run_process.dart' as run_process; +import 'package:native_assets_cli/code_assets.dart'; +import 'package:native_assets_cli/data_assets.dart'; import 'package:native_assets_cli/native_assets_cli.dart'; -import 'package:native_assets_cli/native_assets_cli_internal.dart' as internal; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; +export 'package:native_assets_cli/code_assets_builder.dart'; +export 'package:native_assets_cli/data_assets_builder.dart'; export 'package:native_assets_cli/native_assets_cli_internal.dart'; extension UriExtension on Uri { @@ -160,7 +163,7 @@ final List? _envScriptArgs = Platform /// Configuration for the native toolchain. /// /// Provided on Dart CI. -final cCompiler = internal.CCompilerConfig( +final cCompiler = CCompilerConfig( compiler: _cc, archiver: _ar, linker: _ld, diff --git a/pkgs/native_assets_builder/test_data/add_asset_link/hook/build.dart b/pkgs/native_assets_builder/test_data/add_asset_link/hook/build.dart index c08c9dbd1..10a1d4575 100644 --- a/pkgs/native_assets_builder/test_data/add_asset_link/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/add_asset_link/hook/build.dart @@ -3,7 +3,7 @@ // 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_assets_cli/code_assets.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; void main(List arguments) async { diff --git a/pkgs/native_assets_builder/test_data/add_asset_link/hook/link.dart b/pkgs/native_assets_builder/test_data/add_asset_link/hook/link.dart index 3f48615e0..67ff71cfb 100644 --- a/pkgs/native_assets_builder/test_data/add_asset_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/add_asset_link/hook/link.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; void main(List arguments) async { await link(arguments, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/complex_link/hook/build.dart b/pkgs/native_assets_builder/test_data/complex_link/hook/build.dart index 0ac49c85c..5a508c4c0 100644 --- a/pkgs/native_assets_builder/test_data/complex_link/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/complex_link/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/data_assets.dart'; void main(List args) async { await build(args, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/complex_link/hook/link.dart b/pkgs/native_assets_builder/test_data/complex_link/hook/link.dart index 335df7a08..735c78502 100644 --- a/pkgs/native_assets_builder/test_data/complex_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/complex_link/hook/link.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/data_assets.dart'; void main(List args) async { await link( diff --git a/pkgs/native_assets_builder/test_data/complex_link_helper/hook/build.dart b/pkgs/native_assets_builder/test_data/complex_link_helper/hook/build.dart index 79ff0dfdf..fe2829fd5 100644 --- a/pkgs/native_assets_builder/test_data/complex_link_helper/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/complex_link_helper/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/data_assets.dart'; void main(List args) async { await build(args, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/build.dart b/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/build.dart index 41030887e..a924a9ee8 100644 --- a/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/build.dart @@ -3,7 +3,7 @@ // 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_assets_cli/code_assets.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; void main(List arguments) async { diff --git a/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart b/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart index d531402a6..9e5f01743 100644 --- a/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/drop_dylib_link/hook/link.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; void main(List arguments) async { await link(arguments, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version/hook/build.dart b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version/hook/build.dart index 1f9200207..177b2d794 100644 --- a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version/hook/build.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; // Simulate needing some version of the API. // diff --git a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_link/hook/build.dart b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_link/hook/build.dart index 5ac16fef7..3d96b622e 100644 --- a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_link/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_link/hook/build.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/data_assets.dart'; void main(List arguments) async { await build(arguments, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_linker/hook/link.dart b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_linker/hook/link.dart index ae888ae8e..27aec5e37 100644 --- a/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_linker/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/fail_on_os_sdk_version_linker/hook/link.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; // Simulate needing some version of the API. // diff --git a/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart b/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart index 30fa8ef31..faeeab1c6 100644 --- a/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/build.dart @@ -3,7 +3,8 @@ // 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_assets_cli/code_assets.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; void main(List arguments) async { @@ -29,8 +30,8 @@ void main(List arguments) async { }), ); final tempBuildOutput = BuildOutput(outputBuilder.json); - output.addEncodedAsset( - tempBuildOutput.encodedAssets.single, + output.codeAssets.add( + tempBuildOutput.codeAssets.single, // Send dylib to linking if linking is enabled. linkInPackage: config.linkingEnabled ? packageName : null, ); diff --git a/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/link.dart b/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/link.dart index 4ba7a02a7..c2ca7d027 100644 --- a/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/native_add_duplicate/hook/link.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; void main(List args) async { await link(args, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/no_asset_for_link/hook/link.dart b/pkgs/native_assets_builder/test_data/no_asset_for_link/hook/link.dart index 6909bb089..150300fea 100644 --- a/pkgs/native_assets_builder/test_data/no_asset_for_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/no_asset_for_link/hook/link.dart @@ -2,10 +2,12 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; +import 'package:native_assets_cli/data_assets.dart'; void main(List arguments) async { await link(arguments, (config, output) async { - output.addEncodedAssets(config.encodedAssets); + output.codeAssets.addAll(config.codeAssets); + output.dataAssets.addAll(config.dataAssets); }); } diff --git a/pkgs/native_assets_builder/test_data/simple_data_asset/hook/build.dart b/pkgs/native_assets_builder/test_data/simple_data_asset/hook/build.dart index e7aed2a3c..db164a614 100644 --- a/pkgs/native_assets_builder/test_data/simple_data_asset/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/simple_data_asset/hook/build.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/data_assets.dart'; void main(List args) async { await build( diff --git a/pkgs/native_assets_builder/test_data/simple_link/hook/build.dart b/pkgs/native_assets_builder/test_data/simple_link/hook/build.dart index 0ac49c85c..5a508c4c0 100644 --- a/pkgs/native_assets_builder/test_data/simple_link/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/simple_link/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/data_assets.dart'; void main(List args) async { await build(args, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart b/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart index 31780a866..413dbd6f6 100644 --- a/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/simple_link/hook/link.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/data_assets.dart'; void main(List args) async { await link(args, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/transformer/hook/build.dart b/pkgs/native_assets_builder/test_data/transformer/hook/build.dart index 9f5956bed..6cacae904 100644 --- a/pkgs/native_assets_builder/test_data/transformer/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/transformer/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/data_assets.dart'; import 'package:transformer/src/transform.dart'; void main(List arguments) async { diff --git a/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/build.dart b/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/build.dart index 46f6b1e23..e24b38a3a 100644 --- a/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/build.dart @@ -3,7 +3,7 @@ // 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_assets_cli/code_assets.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; void main(List arguments) async { diff --git a/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/link.dart b/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/link.dart index 3ee5acb56..a3c4c9095 100644 --- a/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/link.dart +++ b/pkgs/native_assets_builder/test_data/treeshaking_native_libs/hook/link.dart @@ -3,7 +3,7 @@ // 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_assets_cli/code_assets.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; void main(List arguments) async { diff --git a/pkgs/native_assets_builder/test_data/wrong_linker/hook/build.dart b/pkgs/native_assets_builder/test_data/wrong_linker/hook/build.dart index 4e06197eb..6da96e5f7 100644 --- a/pkgs/native_assets_builder/test_data/wrong_linker/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/wrong_linker/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; void main(List arguments) async { await build(arguments, (config, output) async { diff --git a/pkgs/native_assets_builder/test_data/wrong_namespace_asset/hook/build.dart b/pkgs/native_assets_builder/test_data/wrong_namespace_asset/hook/build.dart index b923086ce..ed5e053d2 100644 --- a/pkgs/native_assets_builder/test_data/wrong_namespace_asset/hook/build.dart +++ b/pkgs/native_assets_builder/test_data/wrong_namespace_asset/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; void main(List arguments) async { await build(arguments, (config, output) async { diff --git a/pkgs/native_assets_cli/example/build/local_asset/hook/build.dart b/pkgs/native_assets_cli/example/build/local_asset/hook/build.dart index 54540905c..cb4a237d8 100644 --- a/pkgs/native_assets_cli/example/build/local_asset/hook/build.dart +++ b/pkgs/native_assets_cli/example/build/local_asset/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; const assetName = 'asset.txt'; final packageAssetPath = Uri.file('assets/$assetName'); diff --git a/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart b/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart index 4e40c1fee..a178ff606 100644 --- a/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart +++ b/pkgs/native_assets_cli/example/build/local_asset/test/build_test.dart @@ -2,7 +2,7 @@ // for details. 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/test.dart'; +import 'package:native_assets_cli/code_assets_testing.dart'; import 'package:test/test.dart'; import '../hook/build.dart' as build; diff --git a/pkgs/native_assets_cli/example/link/package_with_assets/hook/build.dart b/pkgs/native_assets_cli/example/link/package_with_assets/hook/build.dart index 0ac49c85c..5a508c4c0 100644 --- a/pkgs/native_assets_cli/example/link/package_with_assets/hook/build.dart +++ b/pkgs/native_assets_cli/example/link/package_with_assets/hook/build.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/data_assets.dart'; void main(List args) async { await build(args, (config, output) async { diff --git a/pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart b/pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart index a00f548f8..403d0f15b 100644 --- a/pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart +++ b/pkgs/native_assets_cli/example/link/package_with_assets/hook/link.dart @@ -5,7 +5,7 @@ import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/data_assets.dart'; import 'package:record_use/record_use.dart'; const multiplyIdentifier = Identifier( diff --git a/pkgs/native_assets_cli/lib/code_assets.dart b/pkgs/native_assets_cli/lib/code_assets.dart new file mode 100644 index 000000000..402e5774d --- /dev/null +++ b/pkgs/native_assets_cli/lib/code_assets.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Code asset support for hook authors. +library; + +export 'native_assets_cli.dart' + hide + EncodedAsset, + EncodedAssetBuildOutputBuilder, + EncodedAssetLinkOutputBuilder; +export 'src/architecture.dart' show Architecture; +export 'src/build_mode.dart' show BuildMode; +export 'src/c_compiler_config.dart' show CCompilerConfig; +export 'src/code_assets/code_asset.dart' show CodeAsset, OSLibraryNaming; +export 'src/code_assets/config.dart' + show + CodeAssetBuildConfig, + CodeAssetBuildOutputBuilder, + CodeAssetBuildOutputBuilderAdd, + CodeAssetLinkConfig, + CodeAssetLinkOutputBuilder, + CodeAssetLinkOutputBuilderAdd, + CodeConfig; +export 'src/ios_sdk.dart' show IOSSdk; +export 'src/link_mode.dart' + show + DynamicLoadingBundled, + DynamicLoadingSystem, + LinkMode, + LookupInExecutable, + LookupInProcess, + StaticLinking; +export 'src/link_mode_preference.dart' show LinkModePreference; diff --git a/pkgs/native_assets_cli/lib/code_assets_builder.dart b/pkgs/native_assets_cli/lib/code_assets_builder.dart new file mode 100644 index 000000000..950e0769a --- /dev/null +++ b/pkgs/native_assets_cli/lib/code_assets_builder.dart @@ -0,0 +1,19 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Code asset support for hook invokers (e.g. building / bundling tools). +library; + +export 'code_assets.dart' hide build, link; +export 'native_assets_cli_builder.dart' + hide EncodedAssetBuildOutputBuilder, EncodedAssetLinkOutputBuilder; +export 'src/code_assets/config.dart' + show CodeAssetBuildConfigBuilder, CodeAssetBuildOutput, CodeAssetLinkOutput; +export 'src/code_assets/validation.dart' + show + validateCodeAssetBuildOutput, + validateCodeAssetInApplication, + validateCodeAssetLinkConfig, + validateCodeAssetLinkOutput, + validateCodeAssetBuildConfig; diff --git a/pkgs/native_assets_cli/lib/code_assets_testing.dart b/pkgs/native_assets_cli/lib/code_assets_testing.dart new file mode 100644 index 000000000..148e875d2 --- /dev/null +++ b/pkgs/native_assets_cli/lib/code_assets_testing.dart @@ -0,0 +1,6 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +export 'code_assets_builder.dart'; +export 'src/code_assets/testing.dart' show testCodeBuildHook; diff --git a/pkgs/native_assets_cli/lib/data_assets.dart b/pkgs/native_assets_cli/lib/data_assets.dart new file mode 100644 index 000000000..a2abce48b --- /dev/null +++ b/pkgs/native_assets_cli/lib/data_assets.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Data asset support for hook authors. +library; + +export 'native_assets_cli.dart' + hide + EncodedAsset, + EncodedAssetBuildOutputBuilder, + EncodedAssetLinkOutputBuilder; +export 'src/data_assets/config.dart' + show + DataAssetBuildOutputBuilder, + DataAssetBuildOutputBuilderAdd, + DataAssetLinkConfig, + DataAssetLinkOutputBuilder, + DataAssetLinkOutputBuilderAdd; +export 'src/data_assets/data_asset.dart' show DataAsset; diff --git a/pkgs/native_assets_cli/lib/data_assets_builder.dart b/pkgs/native_assets_cli/lib/data_assets_builder.dart new file mode 100644 index 000000000..fe9d43a79 --- /dev/null +++ b/pkgs/native_assets_cli/lib/data_assets_builder.dart @@ -0,0 +1,18 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Data asset support for hook invokers (e.g. building / bundling tools). +library; + +export 'data_assets.dart' hide build, link; +export 'native_assets_cli_builder.dart' + hide EncodedAssetBuildOutputBuilder, EncodedAssetLinkOutputBuilder; +export 'src/data_assets/config.dart' + show DataAssetBuildOutput, DataAssetLinkOutput; +export 'src/data_assets/validation.dart' + show + validateDataAssetBuildConfig, + validateDataAssetBuildOutput, + validateDataAssetLinkConfig, + validateDataAssetLinkOutput; diff --git a/pkgs/native_assets_cli/lib/native_assets_cli.dart b/pkgs/native_assets_cli/lib/native_assets_cli.dart index 789ed234b..f1ef16f3d 100644 --- a/pkgs/native_assets_cli/lib/native_assets_cli.dart +++ b/pkgs/native_assets_cli/lib/native_assets_cli.dart @@ -4,46 +4,22 @@ /// A library that contains the argument and file formats for implementing a /// build hook (`hook/build.dart`). -library native_assets_cli; +library; export 'src/api/build.dart' show build; export 'src/api/builder.dart' show Builder; export 'src/api/link.dart' show link; export 'src/api/linker.dart' show Linker; -export 'src/architecture.dart' show Architecture; export 'src/build_mode.dart' show BuildMode; -export 'src/c_compiler_config.dart' show CCompilerConfig; -export 'src/code_assets/code_asset.dart' show CodeAsset, OSLibraryNaming; -export 'src/code_assets/config.dart' +export 'src/config.dart' show - BuildOutputCodeAssets, - CodeAssetBuildConfig, - CodeAssetsBuildOutput, - CodeAssetsLinkConfig, - CodeAssetsLinkOutput, - CodeConfig, - LinkOutputCodeAssets; -export 'src/config.dart' show BuildConfig, BuildOutputBuilder; -export 'src/config.dart' show BuildOutput, LinkOutput, LinkOutputBuilder; -export 'src/config.dart' show HookConfig; -export 'src/config.dart' show LinkConfig; -export 'src/data_assets/config.dart' - show - BuildOutputDataAssets, - DataAssetsBuildOutput, - DataAssetsLinkConfig, - DataAssetsLinkOutput, - LinkOutputDataAssets; -export 'src/data_assets/data_asset.dart' show DataAsset; + BuildConfig, + BuildOutputBuilder, + EncodedAssetBuildOutputBuilder, + EncodedAssetLinkOutputBuilder, + HookConfig, + LinkConfig, + LinkOutputBuilder; export 'src/encoded_asset.dart' show EncodedAsset; -export 'src/ios_sdk.dart' show IOSSdk; -export 'src/link_mode.dart' - show - DynamicLoadingBundled, - DynamicLoadingSystem, - LinkMode, - LookupInExecutable, - LookupInProcess, - StaticLinking; -export 'src/link_mode_preference.dart' show LinkModePreference; +export 'src/metadata.dart'; export 'src/os.dart' show OS; diff --git a/pkgs/native_assets_cli/lib/native_assets_cli_builder.dart b/pkgs/native_assets_cli/lib/native_assets_cli_builder.dart new file mode 100644 index 000000000..6b753433e --- /dev/null +++ b/pkgs/native_assets_cli/lib/native_assets_cli_builder.dart @@ -0,0 +1,26 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Support for hook invokers (e.g. building / bundling tools). +library; + +export 'native_assets_cli.dart' hide build, link; +export 'src/config.dart' + show + BuildConfigBuilder, + BuildOutput, + HookConfigBuilder, + HookOutput, + LinkConfigBuilder, + LinkOutput; +export 'src/model/dependencies.dart'; +export 'src/model/resource_identifiers.dart'; +export 'src/model/target.dart' show Target; +export 'src/validation.dart' + show + ValidationErrors, + validateBuildConfig, + validateBuildOutput, + validateLinkConfig, + validateLinkOutput; diff --git a/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart b/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart index 92a4d40ee..d8bab884b 100644 --- a/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart +++ b/pkgs/native_assets_cli/lib/native_assets_cli_internal.dart @@ -2,51 +2,12 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -/// Internal API for invoking build hooks. -/// -/// This library is intended for use by: -/// * `package:native_assets_builder`, -/// * `dartdev` (in the Dart SDK), and, -/// * `flutter_tools` (in the Flutter SDK). -/// -/// > [!CAUTION] -/// > Unless you are building a custom SDK that embeds Dart you should -/// > not be importing this library! -/// -/// @nodoc -library native_assets_cli_internal; +/// Support for hook invokers (e.g. building / bundling tools). +library; + +export 'native_assets_cli_builder.dart'; -export 'native_assets_cli.dart' hide build, link; -export 'src/code_assets/config.dart' - show CodeAssetBuildConfigBuilder, CodeAssetBuildOutput, CodeAssetLinkOutput; -export 'src/code_assets/validation.dart' - show - validateCodeAssetBuildOutput, - validateCodeAssetLinkOutput, - validateCodeAssetsInApplication, - validateCodeBuildConfig, - validateCodeLinkConfig; -export 'src/config.dart' show BuildConfigBuilder, LinkConfigBuilder; -export 'src/config.dart' show BuildOutputBuilder, LinkOutputBuilder; -export 'src/config.dart' show HookConfigBuilder, HookOutput; -export 'src/data_assets/config.dart' - show DataAssetBuildOutput, DataAssetLinkOutput; -export 'src/data_assets/validation.dart' - show - validateDataAssetBuildConfig, - validateDataAssetBuildOutput, - validateDataAssetLinkConfig, - validateDataAssetLinkOutput; -export 'src/encoded_asset.dart' show EncodedAsset; export 'src/model/dependencies.dart'; export 'src/model/hook.dart'; -export 'src/model/metadata.dart'; export 'src/model/resource_identifiers.dart'; export 'src/model/target.dart' show Target; -export 'src/validation.dart' - show - ValidationErrors, - validateBuildConfig, - validateBuildOutput, - validateLinkConfig, - validateLinkOutput; diff --git a/pkgs/native_assets_cli/lib/src/code_assets/config.dart b/pkgs/native_assets_cli/lib/src/code_assets/config.dart index cea210f5f..509338c38 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/config.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/config.dart @@ -21,7 +21,7 @@ extension CodeAssetBuildConfig on BuildConfig { /// Extension to the [LinkConfig] providing access to configuration specific to /// code assets as well as code asset inputs to the linker (only available if /// code assets are supported). -extension CodeAssetsLinkConfig on LinkConfig { +extension CodeAssetLinkConfig on LinkConfig { /// Code asset specific configuration. CodeConfig get codeConfig => CodeConfig(this); @@ -77,13 +77,14 @@ class CodeConfig { /// Extension to the [BuildOutputBuilder] providing access to emitting code /// assets (only available if code assets are supported). -extension CodeAssetsBuildOutput on BuildOutputBuilder { +extension CodeAssetBuildOutputBuilder on BuildOutputBuilder { /// Provides access to emitting code assets. - BuildOutputCodeAssets get codeAssets => BuildOutputCodeAssets._(this); + CodeAssetBuildOutputBuilderAdd get codeAssets => + CodeAssetBuildOutputBuilderAdd._(this); } /// Supports emitting code assets for build hooks. -extension type BuildOutputCodeAssets._(BuildOutputBuilder _output) { +extension type CodeAssetBuildOutputBuilderAdd._(BuildOutputBuilder _output) { /// Adds the given [asset] to the hook output (or send to [linkInPackage] /// for linking if provided). void add(CodeAsset asset, {String? linkInPackage}) => @@ -100,13 +101,14 @@ extension type BuildOutputCodeAssets._(BuildOutputBuilder _output) { /// Extension to the [LinkOutputBuilder] providing access to emitting code /// assets (only available if code assets are supported). -extension CodeAssetsLinkOutput on LinkOutputBuilder { +extension CodeAssetLinkOutputBuilder on LinkOutputBuilder { /// Provides access to emitting code assets. - LinkOutputCodeAssets get codeAssets => LinkOutputCodeAssets._(this); + CodeAssetLinkOutputBuilderAdd get codeAssets => + CodeAssetLinkOutputBuilderAdd._(this); } /// Extension on [LinkOutputBuilder] to emit code assets. -extension type LinkOutputCodeAssets._(LinkOutputBuilder _output) { +extension type CodeAssetLinkOutputBuilderAdd._(LinkOutputBuilder _output) { /// Adds the given [asset] to the link hook output. void add(CodeAsset asset) => _output.addEncodedAsset(asset.encode()); diff --git a/pkgs/native_assets_cli/lib/src/code_assets/testing.dart b/pkgs/native_assets_cli/lib/src/code_assets/testing.dart index 0b09166ed..21f2ad672 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/testing.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/testing.dart @@ -7,6 +7,7 @@ import 'dart:async'; import 'package:meta/meta.dart' show isTest; import 'package:test/test.dart'; +import '../../code_assets_builder.dart'; import '../../test.dart'; @isTest diff --git a/pkgs/native_assets_cli/lib/src/code_assets/validation.dart b/pkgs/native_assets_cli/lib/src/code_assets/validation.dart index 381986ed8..ba0008cbd 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/validation.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/validation.dart @@ -4,14 +4,14 @@ import 'dart:io'; -import '../../native_assets_cli_internal.dart'; +import '../../code_assets_builder.dart'; import '../link_mode.dart'; -Future validateCodeBuildConfig(BuildConfig config) async => +Future validateCodeAssetBuildConfig(BuildConfig config) async => _validateCodeConfig( 'BuildConfig', config.targetOS, config.dryRun, config.codeConfig); -Future validateCodeLinkConfig(LinkConfig config) async => +Future validateCodeAssetLinkConfig(LinkConfig config) async => _validateCodeConfig( 'LinkConfig', config.targetOS, false, config.codeConfig); @@ -84,7 +84,7 @@ Future validateCodeAssetLinkOutput( /// Some restrictions - e.g. unique shared library names - have to be validated /// on the entire application build and not on individual `hook/build.dart` /// invocations. -Future validateCodeAssetsInApplication( +Future validateCodeAssetInApplication( List assets) async { final fileNameToEncodedAssetId = >{}; for (final asset in assets) { diff --git a/pkgs/native_assets_cli/lib/src/config.dart b/pkgs/native_assets_cli/lib/src/config.dart index a25f6a3ee..d33f4ce3a 100644 --- a/pkgs/native_assets_cli/lib/src/config.dart +++ b/pkgs/native_assets_cli/lib/src/config.dart @@ -13,7 +13,7 @@ import 'architecture.dart'; import 'build_mode.dart'; import 'encoded_asset.dart'; import 'json_utils.dart'; -import 'model/metadata.dart'; +import 'metadata.dart'; import 'os.dart'; import 'utils/datetime.dart'; import 'utils/json.dart'; @@ -377,7 +377,20 @@ List _parseEncodedAssets(List? json) => json == null const _assetsForLinkingKey = 'assetsForLinking'; const _dependencyMetadataKey = 'dependency_metadata'; -/// Builder to initialize build hook specific configuration. +/// Builder to produce the output of a build hook. +/// +/// There are various Dart extensions on this [BuildOutputBuilder] that allow +/// adding specific asset types - which should be used by normal hook authors. +/// For example +/// +/// ```dart +/// main(List arguments) async { +/// await build((config, output) { +/// output.codeAssets.add(CodeAsset(...)); +/// output.dataAssets.add(DataAsset(...)); +/// }); +/// } +/// ``` class BuildOutputBuilder extends HookOutputBuilder { /// Adds metadata to be passed to build hook invocations of dependent /// packages. @@ -396,7 +409,11 @@ class BuildOutputBuilder extends HookOutputBuilder { map ??= json[_metadataConfigKey] = {}; map.addAll(metadata); } +} +/// Extension for the lower-level API to add [EncodedAsset]s to +/// [BuildOutputBuilder]. +extension EncodedAssetBuildOutputBuilder on BuildOutputBuilder { /// Adds [EncodedAsset]s produced by this build or dry run. /// /// If the [linkInPackage] argument is specified, the asset will not be @@ -473,7 +490,25 @@ class LinkOutput extends HookOutput { : encodedAssets = _parseEncodedAssets(json.optionalList(_assetsKey)); } -class LinkOutputBuilder extends HookOutputBuilder { +/// Builder to produce the output of a link hook. +/// +/// There are various Dart extensions on this [LinkOutputBuilder] that allow +/// adding specific asset types - which should be used by normal hook authors. +/// For example +/// +/// ```dart +/// main(List arguments) async { +/// await build((config, output) { +/// output.codeAssets.add(CodeAsset(...)); +/// output.dataAssets.add(DataAsset(...)); +/// }); +/// } +/// ``` +class LinkOutputBuilder extends HookOutputBuilder {} + +/// Extension for the lower-level API to add [EncodedAsset]s to +/// [BuildOutputBuilder]. +extension EncodedAssetLinkOutputBuilder on LinkOutputBuilder { /// Adds [EncodedAsset]s produced by this build. /// /// Note to hook writers. Prefer using the `.add` method on the extension for diff --git a/pkgs/native_assets_cli/lib/src/data_assets/config.dart b/pkgs/native_assets_cli/lib/src/data_assets/config.dart index 99dafc3cb..5c5433810 100644 --- a/pkgs/native_assets_cli/lib/src/data_assets/config.dart +++ b/pkgs/native_assets_cli/lib/src/data_assets/config.dart @@ -7,7 +7,7 @@ import '../config.dart'; import 'data_asset.dart'; /// Link output extension for data assets. -extension DataAssetsLinkConfig on LinkConfig { +extension DataAssetLinkConfig on LinkConfig { // Returns the data assets that were sent to this linker. // // NOTE: If the linker implementation depends on the contents of the files of @@ -21,13 +21,14 @@ extension DataAssetsLinkConfig on LinkConfig { } /// Build output extension for data assets. -extension DataAssetsBuildOutput on BuildOutputBuilder { +extension DataAssetBuildOutputBuilder on BuildOutputBuilder { /// Provides access to emitting data assets. - BuildOutputDataAssets get dataAssets => BuildOutputDataAssets._(this); + DataAssetBuildOutputBuilderAdd get dataAssets => + DataAssetBuildOutputBuilderAdd._(this); } /// Supports emitting code assets for build hooks. -extension type BuildOutputDataAssets._(BuildOutputBuilder _output) { +extension type DataAssetBuildOutputBuilderAdd._(BuildOutputBuilder _output) { /// Adds the given [asset] to the hook output (or send to [linkInPackage] /// for linking if provided). void add(DataAsset asset, {String? linkInPackage}) => @@ -44,13 +45,14 @@ extension type BuildOutputDataAssets._(BuildOutputBuilder _output) { /// Extension to the [LinkOutputBuilder] providing access to emitting data /// assets (only available if data assets are supported). -extension DataAssetsLinkOutput on LinkOutputBuilder { +extension DataAssetLinkOutputBuilder on LinkOutputBuilder { /// Provides access to emitting data assets. - LinkOutputDataAssets get dataAssets => LinkOutputDataAssets(this); + DataAssetLinkOutputBuilderAdd get dataAssets => + DataAssetLinkOutputBuilderAdd(this); } /// Extension on [LinkOutputBuilder] to emit data assets. -extension type LinkOutputDataAssets(LinkOutputBuilder _output) { +extension type DataAssetLinkOutputBuilderAdd(LinkOutputBuilder _output) { /// Adds the given [asset] to the link hook output. void add(DataAsset asset) => _output.addEncodedAsset(asset.encode()); diff --git a/pkgs/native_assets_cli/lib/src/data_assets/validation.dart b/pkgs/native_assets_cli/lib/src/data_assets/validation.dart index 20a98d04b..2c4165551 100644 --- a/pkgs/native_assets_cli/lib/src/data_assets/validation.dart +++ b/pkgs/native_assets_cli/lib/src/data_assets/validation.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import '../../native_assets_cli_internal.dart'; +import '../../data_assets_builder.dart'; Future validateDataAssetBuildConfig( BuildConfig config) async => diff --git a/pkgs/native_assets_cli/lib/src/model/metadata.dart b/pkgs/native_assets_cli/lib/src/metadata.dart similarity index 93% rename from pkgs/native_assets_cli/lib/src/model/metadata.dart rename to pkgs/native_assets_cli/lib/src/metadata.dart index 0a492b98f..e9dc00128 100644 --- a/pkgs/native_assets_cli/lib/src/model/metadata.dart +++ b/pkgs/native_assets_cli/lib/src/metadata.dart @@ -4,8 +4,8 @@ import 'package:collection/collection.dart'; -import '../utils/json.dart'; -import '../utils/map.dart'; +import 'utils/json.dart'; +import 'utils/map.dart'; class Metadata { final Map metadata; diff --git a/pkgs/native_assets_cli/lib/src/validation.dart b/pkgs/native_assets_cli/lib/src/validation.dart index 739721a1a..66b314434 100644 --- a/pkgs/native_assets_cli/lib/src/validation.dart +++ b/pkgs/native_assets_cli/lib/src/validation.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:io'; -import '../native_assets_cli_internal.dart'; +import '../native_assets_cli_builder.dart'; typedef ValidationErrors = List; diff --git a/pkgs/native_assets_cli/lib/test.dart b/pkgs/native_assets_cli/lib/test.dart index a520166e7..26c0ab27b 100644 --- a/pkgs/native_assets_cli/lib/test.dart +++ b/pkgs/native_assets_cli/lib/test.dart @@ -10,10 +10,10 @@ import 'package:meta/meta.dart' show isTest; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; -import 'native_assets_cli_internal.dart'; +import 'native_assets_cli_builder.dart'; +import 'native_assets_cli_internal.dart' show Hook; -export 'native_assets_cli_internal.dart'; -export 'src/code_assets/testing.dart' show testCodeBuildHook; +export 'native_assets_cli_builder.dart'; @isTest Future testBuildHook({ diff --git a/pkgs/native_assets_cli/test/api/asset_test.dart b/pkgs/native_assets_cli/test/api/asset_test.dart index 8c260e281..9e580aed9 100644 --- a/pkgs/native_assets_cli/test/api/asset_test.dart +++ b/pkgs/native_assets_cli/test/api/asset_test.dart @@ -2,7 +2,8 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; +import 'package:native_assets_cli/data_assets.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/api/build_test.dart b/pkgs/native_assets_cli/test/api/build_test.dart index 1e9e73fb0..0504151f4 100644 --- a/pkgs/native_assets_cli/test/api/build_test.dart +++ b/pkgs/native_assets_cli/test/api/build_test.dart @@ -7,7 +7,8 @@ import 'dart:io'; import 'package:file_testing/file_testing.dart'; import 'package:native_assets_cli/native_assets_cli.dart' show build; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli_builder.dart'; +import 'package:native_assets_cli/native_assets_cli_internal.dart' show Hook; import 'package:test/test.dart'; void main() async { @@ -34,7 +35,7 @@ void main() async { packageRoot: tempUri, packageName: packageName, targetOS: OS.iOS, - supportedAssetTypes: [CodeAsset.type], + supportedAssetTypes: ['foo'], buildMode: BuildMode.release, ) ..setupBuildConfig( diff --git a/pkgs/native_assets_cli/test/api/target_test.dart b/pkgs/native_assets_cli/test/api/target_test.dart index 4d44547d1..155734e7c 100644 --- a/pkgs/native_assets_cli/test/api/target_test.dart +++ b/pkgs/native_assets_cli/test/api/target_test.dart @@ -4,7 +4,7 @@ import 'dart:ffi'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/build_config_test.dart b/pkgs/native_assets_cli/test/build_config_test.dart index 29d937d89..6c4b334df 100644 --- a/pkgs/native_assets_cli/test/build_config_test.dart +++ b/pkgs/native_assets_cli/test/build_config_test.dart @@ -7,7 +7,7 @@ import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli_builder.dart'; import 'package:native_assets_cli/src/config.dart' show latestVersion; import 'package:test/test.dart'; diff --git a/pkgs/native_assets_cli/test/build_output_test.dart b/pkgs/native_assets_cli/test/build_output_test.dart index 28e6f02ba..7eb7b30da 100644 --- a/pkgs/native_assets_cli/test/build_output_test.dart +++ b/pkgs/native_assets_cli/test/build_output_test.dart @@ -4,7 +4,7 @@ // ignore_for_file: deprecated_member_use_from_same_package -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli_builder.dart'; import 'package:native_assets_cli/src/utils/datetime.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_assets_cli/test/checksum_test.dart b/pkgs/native_assets_cli/test/checksum_test.dart index 6a83b564d..214eb67ec 100644 --- a/pkgs/native_assets_cli/test/checksum_test.dart +++ b/pkgs/native_assets_cli/test/checksum_test.dart @@ -2,7 +2,8 @@ // for details. 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_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; +import 'package:native_assets_cli/data_assets_builder.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/code_assets/code_asset_test.dart b/pkgs/native_assets_cli/test/code_assets/code_asset_test.dart index 7a20292b4..1ffe89bbf 100644 --- a/pkgs/native_assets_cli/test/code_assets/code_asset_test.dart +++ b/pkgs/native_assets_cli/test/code_assets/code_asset_test.dart @@ -2,7 +2,7 @@ // for details. 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_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:test/test.dart'; void main() async { diff --git a/pkgs/native_assets_cli/test/code_assets/config_test.dart b/pkgs/native_assets_cli/test/code_assets/config_test.dart index 3c4215aed..35618b1f9 100644 --- a/pkgs/native_assets_cli/test/code_assets/config_test.dart +++ b/pkgs/native_assets_cli/test/code_assets/config_test.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:native_assets_cli/src/config.dart' show latestVersion; import 'package:test/test.dart'; diff --git a/pkgs/native_assets_cli/test/code_assets/validation_test.dart b/pkgs/native_assets_cli/test/code_assets/validation_test.dart index e6fab9a4f..52415eb9c 100644 --- a/pkgs/native_assets_cli/test/code_assets/validation_test.dart +++ b/pkgs/native_assets_cli/test/code_assets/validation_test.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:test/test.dart'; void main() { @@ -221,7 +221,7 @@ void main() { ..setupCodeConfig( targetArchitecture: Architecture.arm64, linkModePreference: LinkModePreference.dynamic); - final errors = await validateCodeBuildConfig(BuildConfig(builder.json)); + final errors = await validateCodeAssetBuildConfig(BuildConfig(builder.json)); expect( errors, contains( @@ -237,7 +237,7 @@ void main() { targetArchitecture: Architecture.arm64, linkModePreference: LinkModePreference.dynamic); expect( - await validateCodeBuildConfig(BuildConfig(builder.json)), + await validateCodeAssetBuildConfig(BuildConfig(builder.json)), contains(contains( 'BuildConfig.codeConfig.targetAndroidNdkApi was missing'))); }); @@ -247,7 +247,7 @@ void main() { targetArchitecture: Architecture.arm64, linkModePreference: LinkModePreference.dynamic); expect( - await validateCodeBuildConfig(BuildConfig(builder.json)), + await validateCodeAssetBuildConfig(BuildConfig(builder.json)), contains(contains( 'BuildConfig.codeConfig.targetMacOSVersion was missing'))); }); @@ -263,7 +263,7 @@ void main() { archiver: nonExistent, envScript: nonExistent, )); - final errors = await validateCodeBuildConfig(BuildConfig(builder.json)); + final errors = await validateCodeAssetBuildConfig(BuildConfig(builder.json)); bool matches(String error, String field) => RegExp('BuildConfig.codeConfig.$field (.*foo baz).* does not exist.') diff --git a/pkgs/native_assets_cli/test/data_assets/data_asset_test.dart b/pkgs/native_assets_cli/test/data_assets/data_asset_test.dart index b64205a81..3649b9b8b 100644 --- a/pkgs/native_assets_cli/test/data_assets/data_asset_test.dart +++ b/pkgs/native_assets_cli/test/data_assets/data_asset_test.dart @@ -2,7 +2,7 @@ // for details. 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_internal.dart'; +import 'package:native_assets_cli/data_assets_builder.dart'; import 'package:test/test.dart'; void main() async { diff --git a/pkgs/native_assets_cli/test/data_assets/validation_test.dart b/pkgs/native_assets_cli/test/data_assets/validation_test.dart index 21b9ed1c3..c3f5fcd01 100644 --- a/pkgs/native_assets_cli/test/data_assets/validation_test.dart +++ b/pkgs/native_assets_cli/test/data_assets/validation_test.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/data_assets_builder.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/example/local_asset_test.dart b/pkgs/native_assets_cli/test/example/local_asset_test.dart index 629aa3c4c..591d6a3e3 100644 --- a/pkgs/native_assets_cli/test/example/local_asset_test.dart +++ b/pkgs/native_assets_cli/test/example/local_asset_test.dart @@ -11,7 +11,7 @@ library; import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:test/test.dart'; import '../helpers.dart'; diff --git a/pkgs/native_assets_cli/test/example/native_add_library_test.dart b/pkgs/native_assets_cli/test/example/native_add_library_test.dart index 3d0d2f9c7..3e85e84db 100644 --- a/pkgs/native_assets_cli/test/example/native_add_library_test.dart +++ b/pkgs/native_assets_cli/test/example/native_add_library_test.dart @@ -11,7 +11,7 @@ library; import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:test/test.dart'; import '../helpers.dart'; diff --git a/pkgs/native_assets_cli/test/example/native_dynamic_linking_test.dart b/pkgs/native_assets_cli/test/example/native_dynamic_linking_test.dart index dada26501..a20306a4f 100644 --- a/pkgs/native_assets_cli/test/example/native_dynamic_linking_test.dart +++ b/pkgs/native_assets_cli/test/example/native_dynamic_linking_test.dart @@ -14,7 +14,7 @@ library; import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:test/test.dart'; import '../helpers.dart'; diff --git a/pkgs/native_assets_cli/test/helpers.dart b/pkgs/native_assets_cli/test/helpers.dart index 6f02de316..6fbc01635 100644 --- a/pkgs/native_assets_cli/test/helpers.dart +++ b/pkgs/native_assets_cli/test/helpers.dart @@ -5,8 +5,8 @@ import 'dart:io'; import 'package:logging/logging.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; -import 'package:native_assets_cli/native_assets_cli_internal.dart' as internal; +import 'package:native_assets_cli/code_assets_builder.dart'; +import 'package:native_assets_cli/data_assets_builder.dart'; import 'package:test/test.dart'; const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES'; @@ -115,7 +115,7 @@ final List? _envScriptArgs = Platform /// Configuration for the native toolchain. /// /// Provided on Dart CI. -final cCompiler = internal.CCompilerConfig( +final cCompiler = CCompilerConfig( compiler: _cc, archiver: _ar, linker: _ld, diff --git a/pkgs/native_assets_cli/test/link_config_test.dart b/pkgs/native_assets_cli/test/link_config_test.dart index 93f8c14e2..16d394d32 100644 --- a/pkgs/native_assets_cli/test/link_config_test.dart +++ b/pkgs/native_assets_cli/test/link_config_test.dart @@ -5,7 +5,7 @@ import 'dart:convert'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli_builder.dart'; import 'package:native_assets_cli/src/config.dart' show latestVersion; import 'package:test/test.dart'; @@ -82,7 +82,7 @@ void main() async { 'target_os': 'linux', 'version': version, 'package_name': packageName, - 'supported_asset_types': [CodeAsset.type], + 'supported_asset_types': ['my-asset-type'], 'dry_run': true, }; expect( @@ -108,12 +108,10 @@ void main() async { expect( () => LinkConfig({ 'version': latestVersion.toString(), - 'supported_asset_types': [CodeAsset.type], + 'supported_asset_types': ['my-asset-type'], 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', 'target_os': 'android', - 'target_android_ndk_api': 30, 'assets': [], }), throwsA(predicate( @@ -127,17 +125,14 @@ void main() async { expect( () => LinkConfig({ 'version': latestVersion.toString(), - 'supported_asset_types': [CodeAsset.type], + 'supported_asset_types': ['my-asset-type'], 'out_dir': outDirUri.toFilePath(), 'out_dir_shared': outputDirectoryShared.toFilePath(), 'package_name': packageName, 'package_root': packageRootUri.toFilePath(), - 'target_architecture': 'arm64', 'target_os': 'android', - 'target_android_ndk_api': 30, 'build_mode': BuildMode.release.name, 'assets': 'astring', - 'link_mode_preference': LinkModePreference.preferStatic.name, }), throwsA(predicate( (e) => diff --git a/pkgs/native_assets_cli/test/link_output_test.dart b/pkgs/native_assets_cli/test/link_output_test.dart index 32e34d695..a79d81a18 100644 --- a/pkgs/native_assets_cli/test/link_output_test.dart +++ b/pkgs/native_assets_cli/test/link_output_test.dart @@ -2,7 +2,7 @@ // for details. 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_internal.dart'; +import 'package:native_assets_cli/native_assets_cli_builder.dart'; import 'package:native_assets_cli/src/utils/datetime.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_assets_cli/test/model/asset_test.dart b/pkgs/native_assets_cli/test/model/asset_test.dart index e6d268812..af23ffaf3 100644 --- a/pkgs/native_assets_cli/test/model/asset_test.dart +++ b/pkgs/native_assets_cli/test/model/asset_test.dart @@ -3,7 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'package:collection/collection.dart'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; +import 'package:native_assets_cli/data_assets.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/model/dependencies_test.dart b/pkgs/native_assets_cli/test/model/dependencies_test.dart index e11aeb954..549431160 100644 --- a/pkgs/native_assets_cli/test/model/dependencies_test.dart +++ b/pkgs/native_assets_cli/test/model/dependencies_test.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli_builder.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/model/link_mode_test.dart b/pkgs/native_assets_cli/test/model/link_mode_test.dart index d27fdc129..52a2d0276 100644 --- a/pkgs/native_assets_cli/test/model/link_mode_test.dart +++ b/pkgs/native_assets_cli/test/model/link_mode_test.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/model/metadata_test.dart b/pkgs/native_assets_cli/test/model/metadata_test.dart index e1e2dfa68..4f5ed0442 100644 --- a/pkgs/native_assets_cli/test/model/metadata_test.dart +++ b/pkgs/native_assets_cli/test/model/metadata_test.dart @@ -2,7 +2,7 @@ // for details. 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_internal.dart'; +import 'package:native_assets_cli/native_assets_cli.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/model/target_test.dart b/pkgs/native_assets_cli/test/model/target_test.dart index f63f16856..96e49337f 100644 --- a/pkgs/native_assets_cli/test/model/target_test.dart +++ b/pkgs/native_assets_cli/test/model/target_test.dart @@ -5,7 +5,7 @@ import 'dart:ffi'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:test/test.dart'; void main() { diff --git a/pkgs/native_assets_cli/test/validation_test.dart b/pkgs/native_assets_cli/test/validation_test.dart index b8a509c36..aa291d020 100644 --- a/pkgs/native_assets_cli/test/validation_test.dart +++ b/pkgs/native_assets_cli/test/validation_test.dart @@ -4,7 +4,7 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; +import 'package:native_assets_cli/native_assets_cli_builder.dart'; import 'package:test/test.dart'; void main() { @@ -49,29 +49,6 @@ void main() { return BuildConfig(configBuilder.json); } - LinkConfig makeCodeLinkConfig() { - final configBuilder = LinkConfigBuilder() - ..setupHookConfig( - packageName: packageName, - packageRoot: tempUri, - targetOS: OS.iOS, - buildMode: BuildMode.release, - supportedAssetTypes: [CodeAsset.type], - ) - ..setupLinkConfig(assets: []) - ..setupLinkRunConfig( - outputDirectory: outDirUri, - outputDirectoryShared: outDirSharedUri, - recordedUsesFile: null, - ) - ..setupCodeConfig( - targetArchitecture: Architecture.arm64, - targetIOSSdk: IOSSdk.iPhoneOS, - linkModePreference: LinkModePreference.dynamic, - ); - return LinkConfig(configBuilder.json); - } - test('linking not enabled', () async { final config = makeBuildConfig(); final outputBuilder = BuildOutputBuilder(); @@ -102,22 +79,4 @@ void main() { contains(contains('"baz" is not a supported asset type')), ); }); - - test('link hook validation', () async { - final config = makeCodeLinkConfig(); - final outputBuilder = LinkOutputBuilder(); - final assetFile = File.fromUri(outDirUri.resolve('foo.dylib')); - await assetFile.writeAsBytes([1, 2, 3]); - outputBuilder.dataAssets.add(DataAsset( - package: config.packageName, - name: 'foo.txt', - file: assetFile.uri, - )); - final errors = - await validateLinkOutput(config, LinkOutput(outputBuilder.json)); - expect( - errors, - contains(contains('"data" is not a supported asset type')), - ); - }); } diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart index 2468589cd..d8994f315 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/cbuilder.dart @@ -6,7 +6,7 @@ import 'dart:io'; import 'package:logging/logging.dart'; import 'package:meta/meta.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'ctool.dart'; import 'language.dart'; diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart index 55c5ef997..5283603d9 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/clinker.dart @@ -6,7 +6,7 @@ import 'dart:io'; import 'package:logging/logging.dart'; import 'package:meta/meta.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import 'ctool.dart'; import 'language.dart'; diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart index 392d6324f..149b64df2 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/compiler_resolver.dart @@ -5,7 +5,7 @@ import 'dart:io'; import 'package:logging/logging.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import '../native_toolchain/android_ndk.dart'; import '../native_toolchain/apple_clang.dart'; diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart index 3902ea6d0..47e8c7456 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/ctool.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:meta/meta.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import 'cbuilder.dart'; import 'language.dart'; @@ -33,14 +33,14 @@ abstract class CTool { /// /// Resolved against [LinkConfig.packageRoot]. /// - /// Used to output the [LinkOutput.dependencies]. + /// The sources will be reported as dependencies of the hook. final List sources; /// Include directories to pass to the linker. /// /// Resolved against [LinkConfig.packageRoot]. /// - /// Used to output the [LinkOutput.dependencies]. + /// The sources will be reported as dependencies of the hook. final List includes; /// Frameworks to link. @@ -49,10 +49,12 @@ abstract class CTool { /// /// Defaults to `['Foundation']`. /// - /// Not used to output the [LinkOutput.dependencies], frameworks can be - /// mentioned by name if they are available on the system, so the file path - /// is not known. If you're depending on your own frameworks add them to - /// [LinkOutput.dependencies] manually. + /// Framworks will not be automatically reported as dependencies of the hook. + /// Frameworks can be mentioned by name if they are available on the system, + /// so the file path is not known. If you're depending on your own frameworks + /// report them as dependencies of the hook by calling + /// [BuildOutputBuilder.addDependency] / [LinkOutputBuilder.addDependency] + /// manually. final List frameworks; static const List defaultFrameworks = ['Foundation']; diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/linkmode.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/linkmode.dart index d5d08c5be..da7154e28 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/linkmode.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/linkmode.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; LinkMode getLinkMode(LinkModePreference preference) { if (preference == LinkModePreference.dynamic || diff --git a/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart b/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart index 4cf0c99d3..4bbbe69a3 100644 --- a/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart +++ b/pkgs/native_toolchain_c/lib/src/cbuilder/run_cbuilder.dart @@ -5,7 +5,7 @@ import 'dart:math'; import 'package:logging/logging.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import '../native_toolchain/msvc.dart'; import '../native_toolchain/tool_likeness.dart'; diff --git a/pkgs/native_toolchain_c/lib/src/native_toolchain/android_ndk.dart b/pkgs/native_toolchain_c/lib/src/native_toolchain/android_ndk.dart index 964a97a35..9d4547e71 100644 --- a/pkgs/native_toolchain_c/lib/src/native_toolchain/android_ndk.dart +++ b/pkgs/native_toolchain_c/lib/src/native_toolchain/android_ndk.dart @@ -5,7 +5,7 @@ import 'dart:io'; import 'package:logging/logging.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import '../tool/tool.dart'; import '../tool/tool_instance.dart'; diff --git a/pkgs/native_toolchain_c/lib/src/native_toolchain/gcc.dart b/pkgs/native_toolchain_c/lib/src/native_toolchain/gcc.dart index c7bf2cd4b..b6d280fcf 100644 --- a/pkgs/native_toolchain_c/lib/src/native_toolchain/gcc.dart +++ b/pkgs/native_toolchain_c/lib/src/native_toolchain/gcc.dart @@ -2,7 +2,7 @@ // for details. 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'; +import 'package:native_assets_cli/code_assets.dart'; import '../tool/tool.dart'; import '../tool/tool_resolver.dart'; diff --git a/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart b/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart index e8aef12ed..a9463b4e7 100644 --- a/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart +++ b/pkgs/native_toolchain_c/lib/src/native_toolchain/msvc.dart @@ -6,7 +6,7 @@ import 'dart:io'; import 'package:glob/glob.dart'; import 'package:logging/logging.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import '../tool/tool.dart'; import '../tool/tool_instance.dart'; diff --git a/pkgs/native_toolchain_c/lib/src/native_toolchain/recognizer.dart b/pkgs/native_toolchain_c/lib/src/native_toolchain/recognizer.dart index 6c8b430e9..a1cfbbe65 100644 --- a/pkgs/native_toolchain_c/lib/src/native_toolchain/recognizer.dart +++ b/pkgs/native_toolchain_c/lib/src/native_toolchain/recognizer.dart @@ -3,7 +3,7 @@ // 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_assets_cli/code_assets.dart'; import '../tool/tool.dart'; import '../tool/tool_instance.dart'; diff --git a/pkgs/native_toolchain_c/lib/src/tool/tool_resolver.dart b/pkgs/native_toolchain_c/lib/src/tool/tool_resolver.dart index 18f5f075c..f665a7d92 100644 --- a/pkgs/native_toolchain_c/lib/src/tool/tool_resolver.dart +++ b/pkgs/native_toolchain_c/lib/src/tool/tool_resolver.dart @@ -8,7 +8,7 @@ import 'dart:io'; import 'package:glob/glob.dart'; import 'package:glob/list_local_fs.dart'; import 'package:logging/logging.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import 'package:pub_semver/pub_semver.dart'; import '../utils/run_process.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_build_failure_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_build_failure_test.dart index ea920c0f7..778471a6e 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_build_failure_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_build_failure_test.dart @@ -10,7 +10,6 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_android_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_android_test.dart index dcbd0e236..2225a8bd9 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_android_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_android_test.dart @@ -4,7 +4,6 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_ios_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_ios_test.dart index 06577cdd3..006f5c262 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_ios_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_ios_test.dart @@ -10,7 +10,6 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_linux_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_linux_host_test.dart index 63e3aaeec..48a08286a 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_linux_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_linux_host_test.dart @@ -7,7 +7,6 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart index 17adc1519..4c66cbacc 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_macos_host_test.dart @@ -10,7 +10,6 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart index 5cba2fba3..60b509844 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_cross_windows_host_test.dart @@ -10,7 +10,6 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/native_toolchain/msvc.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart index 3482144d8..1b5630650 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/cbuilder_test.dart @@ -11,7 +11,6 @@ library; import 'dart:ffi'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/compiler_resolver_test.dart b/pkgs/native_toolchain_c/test/cbuilder/compiler_resolver_test.dart index 6c13c5257..bac97bd79 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/compiler_resolver_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/compiler_resolver_test.dart @@ -9,7 +9,6 @@ library; import 'package:collection/collection.dart'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/src/cbuilder/compiler_resolver.dart'; import 'package:native_toolchain_c/src/native_toolchain/apple_clang.dart'; import 'package:native_toolchain_c/src/native_toolchain/clang.dart'; diff --git a/pkgs/native_toolchain_c/test/cbuilder/objective_c_test.dart b/pkgs/native_toolchain_c/test/cbuilder/objective_c_test.dart index 737a3e941..c6ebc852e 100644 --- a/pkgs/native_toolchain_c/test/cbuilder/objective_c_test.dart +++ b/pkgs/native_toolchain_c/test/cbuilder/objective_c_test.dart @@ -11,7 +11,6 @@ library; import 'dart:ffi'; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/clinker/build_testfiles.dart b/pkgs/native_toolchain_c/test/clinker/build_testfiles.dart index 39c22e4fe..c9eb1ee86 100644 --- a/pkgs/native_toolchain_c/test/clinker/build_testfiles.dart +++ b/pkgs/native_toolchain_c/test/clinker/build_testfiles.dart @@ -4,7 +4,6 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import '../helpers.dart'; diff --git a/pkgs/native_toolchain_c/test/clinker/objects_test.dart b/pkgs/native_toolchain_c/test/clinker/objects_test.dart index 3e5300e86..ff98f7009 100644 --- a/pkgs/native_toolchain_c/test/clinker/objects_test.dart +++ b/pkgs/native_toolchain_c/test/clinker/objects_test.dart @@ -9,7 +9,6 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/clinker/throws_test.dart b/pkgs/native_toolchain_c/test/clinker/throws_test.dart index fc88a5d39..e6aa79d0f 100644 --- a/pkgs/native_toolchain_c/test/clinker/throws_test.dart +++ b/pkgs/native_toolchain_c/test/clinker/throws_test.dart @@ -4,7 +4,6 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/clinker/treeshake_cross_test.dart b/pkgs/native_toolchain_c/test/clinker/treeshake_cross_test.dart index 9ca276f64..b3672ea47 100644 --- a/pkgs/native_toolchain_c/test/clinker/treeshake_cross_test.dart +++ b/pkgs/native_toolchain_c/test/clinker/treeshake_cross_test.dart @@ -9,7 +9,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import 'package:test/test.dart'; import 'treeshake_helper.dart'; diff --git a/pkgs/native_toolchain_c/test/clinker/treeshake_helper.dart b/pkgs/native_toolchain_c/test/clinker/treeshake_helper.dart index 8a746e516..945940166 100644 --- a/pkgs/native_toolchain_c/test/clinker/treeshake_helper.dart +++ b/pkgs/native_toolchain_c/test/clinker/treeshake_helper.dart @@ -9,7 +9,6 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli_internal.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:test/test.dart'; diff --git a/pkgs/native_toolchain_c/test/clinker/treeshake_test.dart b/pkgs/native_toolchain_c/test/clinker/treeshake_test.dart index e67136319..9ac7a3957 100644 --- a/pkgs/native_toolchain_c/test/clinker/treeshake_test.dart +++ b/pkgs/native_toolchain_c/test/clinker/treeshake_test.dart @@ -9,7 +9,7 @@ library; import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets.dart'; import 'package:test/test.dart'; import 'treeshake_helper.dart'; diff --git a/pkgs/native_toolchain_c/test/helpers.dart b/pkgs/native_toolchain_c/test/helpers.dart index c1575920a..60b758e6f 100644 --- a/pkgs/native_toolchain_c/test/helpers.dart +++ b/pkgs/native_toolchain_c/test/helpers.dart @@ -7,11 +7,13 @@ import 'dart:ffi'; import 'dart:io'; import 'package:logging/logging.dart'; -import 'package:native_assets_cli/native_assets_cli.dart'; +import 'package:native_assets_cli/code_assets_builder.dart'; import 'package:native_toolchain_c/src/native_toolchain/apple_clang.dart'; import 'package:native_toolchain_c/src/utils/run_process.dart'; import 'package:test/test.dart'; +export 'package:native_assets_cli/code_assets_builder.dart'; + /// Returns a suffix for a test that is parameterized. /// /// [tags] represent the current configuration of the test. Each element diff --git a/pkgs/native_toolchain_c/test/tool/tool_resolver_test.dart b/pkgs/native_toolchain_c/test/tool/tool_resolver_test.dart index 85abb1996..1bf295aec 100644 --- a/pkgs/native_toolchain_c/test/tool/tool_resolver_test.dart +++ b/pkgs/native_toolchain_c/test/tool/tool_resolver_test.dart @@ -4,7 +4,6 @@ import 'dart:io'; -import 'package:native_assets_cli/native_assets_cli.dart'; import 'package:native_toolchain_c/src/native_toolchain/apple_clang.dart'; import 'package:native_toolchain_c/src/native_toolchain/clang.dart'; import 'package:native_toolchain_c/src/native_toolchain/msvc.dart'; From e4b93cba865df52eab671285d953e395cb42d54f Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Tue, 15 Oct 2024 12:42:59 +0200 Subject: [PATCH 5/7] run formater, sort imports --- pkgs/native_assets_cli/lib/code_assets_builder.dart | 4 ++-- pkgs/native_assets_cli/lib/src/code_assets/validation.dart | 3 ++- .../native_assets_cli/test/code_assets/validation_test.dart | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pkgs/native_assets_cli/lib/code_assets_builder.dart b/pkgs/native_assets_cli/lib/code_assets_builder.dart index 950e0769a..38c5fe668 100644 --- a/pkgs/native_assets_cli/lib/code_assets_builder.dart +++ b/pkgs/native_assets_cli/lib/code_assets_builder.dart @@ -12,8 +12,8 @@ export 'src/code_assets/config.dart' show CodeAssetBuildConfigBuilder, CodeAssetBuildOutput, CodeAssetLinkOutput; export 'src/code_assets/validation.dart' show + validateCodeAssetBuildConfig, validateCodeAssetBuildOutput, validateCodeAssetInApplication, validateCodeAssetLinkConfig, - validateCodeAssetLinkOutput, - validateCodeAssetBuildConfig; + validateCodeAssetLinkOutput; diff --git a/pkgs/native_assets_cli/lib/src/code_assets/validation.dart b/pkgs/native_assets_cli/lib/src/code_assets/validation.dart index ba0008cbd..b13637179 100644 --- a/pkgs/native_assets_cli/lib/src/code_assets/validation.dart +++ b/pkgs/native_assets_cli/lib/src/code_assets/validation.dart @@ -7,7 +7,8 @@ import 'dart:io'; import '../../code_assets_builder.dart'; import '../link_mode.dart'; -Future validateCodeAssetBuildConfig(BuildConfig config) async => +Future validateCodeAssetBuildConfig( + BuildConfig config) async => _validateCodeConfig( 'BuildConfig', config.targetOS, config.dryRun, config.codeConfig); diff --git a/pkgs/native_assets_cli/test/code_assets/validation_test.dart b/pkgs/native_assets_cli/test/code_assets/validation_test.dart index 52415eb9c..f2ad1c173 100644 --- a/pkgs/native_assets_cli/test/code_assets/validation_test.dart +++ b/pkgs/native_assets_cli/test/code_assets/validation_test.dart @@ -221,7 +221,8 @@ void main() { ..setupCodeConfig( targetArchitecture: Architecture.arm64, linkModePreference: LinkModePreference.dynamic); - final errors = await validateCodeAssetBuildConfig(BuildConfig(builder.json)); + final errors = + await validateCodeAssetBuildConfig(BuildConfig(builder.json)); expect( errors, contains( @@ -263,7 +264,8 @@ void main() { archiver: nonExistent, envScript: nonExistent, )); - final errors = await validateCodeAssetBuildConfig(BuildConfig(builder.json)); + final errors = + await validateCodeAssetBuildConfig(BuildConfig(builder.json)); bool matches(String error, String field) => RegExp('BuildConfig.codeConfig.$field (.*foo baz).* does not exist.') From 5b32ae879fa4fda657b7538239ce8f8b58e93ca4 Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Tue, 15 Oct 2024 13:00:27 +0200 Subject: [PATCH 6/7] Set targetMacOSVersion if OS==MacOS in test helpers --- .../test/build_runner/helpers.dart | 146 +++++++++--------- 1 file changed, 77 insertions(+), 69 deletions(-) diff --git a/pkgs/native_assets_builder/test/build_runner/helpers.dart b/pkgs/native_assets_builder/test/build_runner/helpers.dart index 27b493c17..e8b13f574 100644 --- a/pkgs/native_assets_builder/test/build_runner/helpers.dart +++ b/pkgs/native_assets_builder/test/build_runner/helpers.dart @@ -48,45 +48,48 @@ Future build( Target? target, bool linkingEnabled = false, required List supportedAssetTypes, -}) async => - await runWithLog(capturedLogs, () async { - final result = await NativeAssetsBuildRunner( - logger: logger, - dartExecutable: dartExecutable, - ).build( - configCreator: () => BuildConfigBuilder() - ..setupCodeConfig( - targetArchitecture: target?.architecture ?? Architecture.current, - linkModePreference: linkModePreference, - cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, - ), - configValidator: configValidator, - buildMode: BuildMode.release, - targetOS: target?.os ?? OS.current, - workingDirectory: packageUri, - includeParentEnvironment: includeParentEnvironment, - packageLayout: packageLayout, - runPackageName: runPackageName, - linkingEnabled: linkingEnabled, - supportedAssetTypes: supportedAssetTypes, - buildValidator: buildValidator, - applicationAssetValidator: applicationAssetValidator, - ); +}) async { + final targetOS = target?.os ?? OS.current; + return await runWithLog(capturedLogs, () async { + final result = await NativeAssetsBuildRunner( + logger: logger, + dartExecutable: dartExecutable, + ).build( + configCreator: () => BuildConfigBuilder() + ..setupCodeConfig( + targetArchitecture: target?.architecture ?? Architecture.current, + linkModePreference: linkModePreference, + cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion ?? + (targetOS == OS.macOS ? _defaultMacOSVersion : null), + targetAndroidNdkApi: targetAndroidNdkApi, + ), + configValidator: configValidator, + buildMode: BuildMode.release, + targetOS: targetOS, + workingDirectory: packageUri, + includeParentEnvironment: includeParentEnvironment, + packageLayout: packageLayout, + runPackageName: runPackageName, + linkingEnabled: linkingEnabled, + supportedAssetTypes: supportedAssetTypes, + buildValidator: buildValidator, + applicationAssetValidator: applicationAssetValidator, + ); - if (result != null) { - expect(await result.encodedAssets.allExist(), true); - for (final encodedAssetsForLinking - in result.encodedAssetsForLinking.values) { - expect(await encodedAssetsForLinking.allExist(), true); - } + if (result != null) { + expect(await result.encodedAssets.allExist(), true); + for (final encodedAssetsForLinking + in result.encodedAssetsForLinking.values) { + expect(await encodedAssetsForLinking.allExist(), true); } + } - return result; - }); + return result; + }); +} Future link( Uri packageUri, @@ -108,41 +111,44 @@ Future link( int? targetAndroidNdkApi, Target? target, required List supportedAssetTypes, -}) async => - await runWithLog(capturedLogs, () async { - final result = await NativeAssetsBuildRunner( - logger: logger, - dartExecutable: dartExecutable, - ).link( - configCreator: () => LinkConfigBuilder() - ..setupCodeConfig( - targetArchitecture: target?.architecture ?? Architecture.current, - linkModePreference: linkModePreference, - cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion, - targetAndroidNdkApi: targetAndroidNdkApi, - ), - configValidator: configValidator, - buildMode: BuildMode.release, - targetOS: target?.os ?? OS.current, - workingDirectory: packageUri, - includeParentEnvironment: includeParentEnvironment, - packageLayout: packageLayout, - buildResult: buildResult, - resourceIdentifiers: resourceIdentifiers, - supportedAssetTypes: supportedAssetTypes, - linkValidator: linkValidator, - applicationAssetValidator: applicationAssetValidator, - ); +}) async { + final targetOS = target?.os ?? OS.current; + return await runWithLog(capturedLogs, () async { + final result = await NativeAssetsBuildRunner( + logger: logger, + dartExecutable: dartExecutable, + ).link( + configCreator: () => LinkConfigBuilder() + ..setupCodeConfig( + targetArchitecture: target?.architecture ?? Architecture.current, + linkModePreference: linkModePreference, + cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion ?? + (targetOS == OS.macOS ? _defaultMacOSVersion : null), + targetAndroidNdkApi: targetAndroidNdkApi, + ), + configValidator: configValidator, + buildMode: BuildMode.release, + targetOS: target?.os ?? OS.current, + workingDirectory: packageUri, + includeParentEnvironment: includeParentEnvironment, + packageLayout: packageLayout, + buildResult: buildResult, + resourceIdentifiers: resourceIdentifiers, + supportedAssetTypes: supportedAssetTypes, + linkValidator: linkValidator, + applicationAssetValidator: applicationAssetValidator, + ); - if (result != null) { - expect(await result.encodedAssets.allExist(), true); - } + if (result != null) { + expect(await result.encodedAssets.allExist(), true); + } - return result; - }); + return result; + }); +} Future<(BuildResult?, LinkResult?)> buildAndLink( Uri packageUri, @@ -343,3 +349,5 @@ final CCompilerConfig? dartCICompilerConfig = (() { } return null; })(); + +int _defaultMacOSVersion = 13; From 2ade85bc5ed9c122283debaf402650add56640cb Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Tue, 15 Oct 2024 14:34:12 +0200 Subject: [PATCH 7/7] More test updates regarding `targetMacOSVersion must be set iff targetOS==MacOS` requirement --- .../build_runner/concurrency_test_helper.dart | 1 + .../test/build_runner/helpers.dart | 56 +++++++++++-------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart index 163a2f40c..bebf171a7 100644 --- a/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart +++ b/pkgs/native_assets_builder/test/build_runner/concurrency_test_helper.dart @@ -30,6 +30,7 @@ void main(List args) async { targetArchitecture: Architecture.current, linkModePreference: LinkModePreference.dynamic, cCompilerConfig: dartCICompilerConfig, + targetMacOSVersion: OS.current == OS.macOS ? defaultMacOSVersion : null, ), buildMode: BuildMode.release, targetOS: OS.current, diff --git a/pkgs/native_assets_builder/test/build_runner/helpers.dart b/pkgs/native_assets_builder/test/build_runner/helpers.dart index e8b13f574..c80f3f798 100644 --- a/pkgs/native_assets_builder/test/build_runner/helpers.dart +++ b/pkgs/native_assets_builder/test/build_runner/helpers.dart @@ -55,17 +55,22 @@ Future build( logger: logger, dartExecutable: dartExecutable, ).build( - configCreator: () => BuildConfigBuilder() - ..setupCodeConfig( - targetArchitecture: target?.architecture ?? Architecture.current, - linkModePreference: linkModePreference, - cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion ?? - (targetOS == OS.macOS ? _defaultMacOSVersion : null), - targetAndroidNdkApi: targetAndroidNdkApi, - ), + configCreator: () { + final configBuilder = BuildConfigBuilder(); + if (supportedAssetTypes.contains(CodeAsset.type)) { + configBuilder.setupCodeConfig( + targetArchitecture: target?.architecture ?? Architecture.current, + linkModePreference: linkModePreference, + cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion ?? + (targetOS == OS.macOS ? defaultMacOSVersion : null), + targetAndroidNdkApi: targetAndroidNdkApi, + ); + } + return configBuilder; + }, configValidator: configValidator, buildMode: BuildMode.release, targetOS: targetOS, @@ -118,17 +123,22 @@ Future link( logger: logger, dartExecutable: dartExecutable, ).link( - configCreator: () => LinkConfigBuilder() - ..setupCodeConfig( - targetArchitecture: target?.architecture ?? Architecture.current, - linkModePreference: linkModePreference, - cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, - targetIOSSdk: targetIOSSdk, - targetIOSVersion: targetIOSVersion, - targetMacOSVersion: targetMacOSVersion ?? - (targetOS == OS.macOS ? _defaultMacOSVersion : null), - targetAndroidNdkApi: targetAndroidNdkApi, - ), + configCreator: () { + final configBuilder = LinkConfigBuilder(); + if (supportedAssetTypes.contains(CodeAsset.type)) { + configBuilder.setupCodeConfig( + targetArchitecture: target?.architecture ?? Architecture.current, + linkModePreference: linkModePreference, + cCompilerConfig: cCompilerConfig ?? dartCICompilerConfig, + targetIOSSdk: targetIOSSdk, + targetIOSVersion: targetIOSVersion, + targetMacOSVersion: targetMacOSVersion ?? + (targetOS == OS.macOS ? defaultMacOSVersion : null), + targetAndroidNdkApi: targetAndroidNdkApi, + ); + } + return configBuilder; + }, configValidator: configValidator, buildMode: BuildMode.release, targetOS: target?.os ?? OS.current, @@ -350,4 +360,4 @@ final CCompilerConfig? dartCICompilerConfig = (() { return null; })(); -int _defaultMacOSVersion = 13; +int defaultMacOSVersion = 13;