diff --git a/pkgs/native_assets_cli/CHANGELOG.md b/pkgs/native_assets_cli/CHANGELOG.md index 679abc4cb..b39a0dfe4 100644 --- a/pkgs/native_assets_cli/CHANGELOG.md +++ b/pkgs/native_assets_cli/CHANGELOG.md @@ -8,6 +8,10 @@ - Remove v1.0 / v1.1 related serialization - Update SDK constraint to 3.5.0+ - Remove (deprecated) support for accepting yaml as config +- Remove usage of `package:cli_config` and `package:args`: it minimizes + dependencies and it simplifies logic any hook has to do (as it no longer has + to look into environment variables, arguments and json file, determine which + has presence over other, etc) ## 0.8.0 diff --git a/pkgs/native_assets_cli/lib/src/api/build_config.dart b/pkgs/native_assets_cli/lib/src/api/build_config.dart index 9b256eaae..ff0401eb6 100644 --- a/pkgs/native_assets_cli/lib/src/api/build_config.dart +++ b/pkgs/native_assets_cli/lib/src/api/build_config.dart @@ -2,12 +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 'dart:convert'; import 'dart:io'; -import 'package:cli_config/cli_config.dart'; import 'package:collection/collection.dart'; import 'package:pub_semver/pub_semver.dart'; +import '../args_parser.dart'; +import '../json_utils.dart'; import '../model/hook.dart'; import '../model/metadata.dart'; import '../utils/json.dart'; diff --git a/pkgs/native_assets_cli/lib/src/api/hook_config.dart b/pkgs/native_assets_cli/lib/src/api/hook_config.dart index 8171f005e..f05b8d748 100644 --- a/pkgs/native_assets_cli/lib/src/api/hook_config.dart +++ b/pkgs/native_assets_cli/lib/src/api/hook_config.dart @@ -5,11 +5,11 @@ import 'dart:convert'; import 'dart:io'; -import 'package:cli_config/cli_config.dart'; import 'package:collection/collection.dart'; import 'package:crypto/crypto.dart'; import 'package:pub_semver/pub_semver.dart'; +import '../json_utils.dart'; import '../model/hook.dart'; import '../model/metadata.dart'; import '../model/target.dart'; @@ -22,7 +22,6 @@ import 'ios_sdk.dart'; import 'link_config.dart'; import 'link_mode_preference.dart'; import 'os.dart'; - part '../model/hook_config.dart'; /// The shared properties of a [LinkConfig] and a [BuildConfig]. diff --git a/pkgs/native_assets_cli/lib/src/api/link_config.dart b/pkgs/native_assets_cli/lib/src/api/link_config.dart index d5e4b71e8..e3897bd01 100644 --- a/pkgs/native_assets_cli/lib/src/api/link_config.dart +++ b/pkgs/native_assets_cli/lib/src/api/link_config.dart @@ -4,12 +4,12 @@ import 'dart:convert'; import 'dart:io'; -import 'package:args/args.dart'; -import 'package:cli_config/cli_config.dart'; import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; import 'package:pub_semver/pub_semver.dart'; +import '../args_parser.dart'; +import '../json_utils.dart'; import '../model/hook.dart'; import '../utils/map.dart'; import 'architecture.dart'; diff --git a/pkgs/native_assets_cli/lib/src/args_parser.dart b/pkgs/native_assets_cli/lib/src/args_parser.dart new file mode 100644 index 000000000..942b3a6d4 --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/args_parser.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. + +String getConfigArgument(List arguments) { + for (var i = 0; i < arguments.length; ++i) { + final argument = arguments[i]; + if (argument.startsWith('--config=')) { + return argument.substring('--config='.length); + } + if (argument == '--config') { + if ((i + 1) < arguments.length) { + return arguments[i + 1]; + } + } + } + throw StateError('No --config argument given.'); +} diff --git a/pkgs/native_assets_cli/lib/src/json_utils.dart b/pkgs/native_assets_cli/lib/src/json_utils.dart new file mode 100644 index 000000000..88ec59ca3 --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/json_utils.dart @@ -0,0 +1,106 @@ +// 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:core'; +import 'dart:core' as core; +import 'dart:io'; + +extension JsonUtils on Map { + String string(String key, {Iterable? validValues}) { + final value = get(key); + if (validValues != null && !validValues.contains(value)) { + throw FormatException('Json "$key" had value $value but expected one of ' + '${validValues.join(',')}'); + } + return value; + } + + String? optionalString(String key) => getOptional(key); + + bool? optionalBool(String key) => getOptional(key); + core.int int(String key) => get(key); + core.int? optionalInt(String key) => getOptional(key); + + Uri path(String key, + {required Uri baseUri, + bool resolveUri = true, + bool mustExist = false}) => + _pathToUri(get(key), baseUri: baseUri, resolveUri: resolveUri); + + Uri? optionalPath(String key, + {required Uri baseUri, bool resolveUri = true, bool mustExist = false}) { + final value = getOptional(key); + if (value == null) return null; + final uri = _pathToUri(value, baseUri: baseUri, resolveUri: resolveUri); + if (mustExist) { + _throwIfNotExists(key, uri); + } + return uri; + } + + List? optionalStringList(String key) { + final value = getOptional>(key); + if (value == null) return null; + return value.cast(); + } + + List list(String key) => get>(key); + List? optionalList(String key) => getOptional>(key); + Map? optionalMap(String key) => + getOptional>(key); + + T get(String key) { + final value = this[key]; + if (value == null) { + throw FormatException('No value was provided for required key: $key'); + } + if (value is T) return value; + throw FormatException( + 'Unexpected value \'$value\' for key \'.$key\' in config file. ' + 'Expected a $T.'); + } + + T? getOptional(String key) { + final value = this[key]; + if (value is T?) return value; + throw FormatException( + 'Unexpected value \'$value\' for key \'.$key\' in config file. ' + 'Expected a $T?.'); + } +} + +Uri _pathToUri( + String path, { + required core.bool resolveUri, + required Uri? baseUri, +}) { + final uri = _fileSystemPathToUri(path); + if (resolveUri && baseUri != null) { + return baseUri.resolveUri(uri); + } + return uri; +} + +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); + } + return Uri.file(path); +} diff --git a/pkgs/native_assets_cli/lib/src/model/build_config.dart b/pkgs/native_assets_cli/lib/src/model/build_config.dart index 4b6dabd0d..b7d0d5e45 100644 --- a/pkgs/native_assets_cli/lib/src/model/build_config.dart +++ b/pkgs/native_assets_cli/lib/src/model/build_config.dart @@ -97,37 +97,32 @@ final class BuildConfigImpl extends HookConfigImpl implements BuildConfig { _supportedAssetTypesBackwardsCompatibility(supportedAssetTypes), ); - factory BuildConfigImpl._fromConfig(Config config) => - _readFieldsFromConfig(config); - static BuildConfigImpl fromArguments( - List args, { + List arguments, { Map? environment, Uri? workingDirectory, }) { - // TODO(https://github.com/dart-lang/native/issues/1000): At some point, - // migrate away from package:cli_config, to get rid of package:yaml - // dependency. - final config = Config.fromArgumentsSync( - arguments: args, - environment: environment, - workingDirectory: workingDirectory, - ); - return BuildConfigImpl._fromConfig(config); + final configPath = getConfigArgument(arguments); + final bytes = File(configPath).readAsBytesSync(); + final linkConfigJson = const Utf8Decoder() + .fuse(const JsonDecoder()) + .convert(bytes) as Map; + return fromJson(linkConfigJson, baseUri: Uri.parse(configPath)); } static const dependencyMetadataConfigKey = 'dependency_metadata'; static const linkingEnabledKey = 'linking_enabled'; - static BuildConfigImpl _readFieldsFromConfig(Config config) { + static BuildConfigImpl fromJson(Map config, {Uri? baseUri}) { + baseUri ??= Uri.base; final dryRun = HookConfigImpl.parseDryRun(config) ?? false; final targetOS = HookConfigImpl.parseTargetOS(config); return BuildConfigImpl( - outputDirectory: HookConfigImpl.parseOutDir(config), - outputDirectoryShared: HookConfigImpl.parseOutDirShared(config), + outputDirectory: HookConfigImpl.parseOutDir(baseUri, config), + outputDirectoryShared: HookConfigImpl.parseOutDirShared(baseUri, config), packageName: HookConfigImpl.parsePackageName(config), - packageRoot: HookConfigImpl.parsePackageRoot(config), + packageRoot: HookConfigImpl.parsePackageRoot(baseUri, config), buildMode: HookConfigImpl.parseBuildMode(config, dryRun), targetOS: targetOS, targetArchitecture: @@ -136,7 +131,7 @@ final class BuildConfigImpl extends HookConfigImpl implements BuildConfig { dependencyMetadata: parseDependencyMetadata(config), linkingEnabled: parseHasLinkPhase(config), version: HookConfigImpl.parseVersion(config), - cCompiler: HookConfigImpl.parseCCompiler(config, dryRun), + cCompiler: HookConfigImpl.parseCCompiler(baseUri, config, dryRun), supportedAssetTypes: HookConfigImpl.parseSupportedAssetTypes(config), targetAndroidNdkApi: HookConfigImpl.parseTargetAndroidNdkApi(config, dryRun, targetOS), @@ -149,9 +144,9 @@ final class BuildConfigImpl extends HookConfigImpl implements BuildConfig { ); } - static Map? parseDependencyMetadata(Config config) { - final fileValue = - config.valueOf?>(dependencyMetadataConfigKey); + static Map? parseDependencyMetadata( + Map config) { + final fileValue = config.optionalMap(dependencyMetadataConfigKey); if (fileValue == null) { return null; } @@ -174,12 +169,9 @@ final class BuildConfigImpl extends HookConfigImpl implements BuildConfig { ).sortOnKey(); } - static bool? parseHasLinkPhase(Config config) => + static bool? parseHasLinkPhase(Map config) => config.optionalBool(linkingEnabledKey); - static BuildConfigImpl fromJson(Map buildConfigJson) => - BuildConfigImpl._fromConfig(Config(fileParsed: buildConfigJson)); - @override Map toJson() => { ...hookToJson(), diff --git a/pkgs/native_assets_cli/lib/src/model/hook_config.dart b/pkgs/native_assets_cli/lib/src/model/hook_config.dart index 3057212bf..ded300194 100644 --- a/pkgs/native_assets_cli/lib/src/model/hook_config.dart +++ b/pkgs/native_assets_cli/lib/src/model/hook_config.dart @@ -204,7 +204,7 @@ abstract class HookConfigImpl implements HookConfig { }.sortOnKey(); } - static Version parseVersion(Config config) { + static Version parseVersion(Map config) { final version = Version.parse(config.string('version')); if (version.major > latestVersion.major) { throw FormatException( @@ -223,34 +223,35 @@ abstract class HookConfigImpl implements HookConfig { return version; } - static bool? parseDryRun(Config config) => + static bool? parseDryRun(Map config) => config.optionalBool(dryRunConfigKey); - static Uri parseOutDir(Config config) => - config.path(outDirConfigKey, mustExist: true); + static Uri parseOutDir(Uri baseUri, Map config) => + config.path(outDirConfigKey, baseUri: baseUri, mustExist: true); - static Uri parseOutDirShared(Config config) { - final configResult = - config.optionalPath(outDirSharedConfigKey, mustExist: true); + static Uri parseOutDirShared(Uri baseUri, Map config) { + final configResult = config.optionalPath(outDirSharedConfigKey, + baseUri: baseUri, 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 outDir = config.path(outDirConfigKey, baseUri: baseUri); final outDirShared = outDir.resolve('../out_shared/'); Directory.fromUri(outDirShared).createSync(); return outDirShared; } - static String parsePackageName(Config config) => + static String parsePackageName(Map config) => config.string(packageNameConfigKey); - static Uri parsePackageRoot(Config config) => - config.path(packageRootConfigKey, mustExist: true); + static Uri parsePackageRoot(Uri baseUri, Map config) => + config.path(packageRootConfigKey, baseUri: baseUri, mustExist: true); - static BuildModeImpl? parseBuildMode(Config config, bool dryRun) { + static BuildModeImpl? parseBuildMode( + Map config, bool dryRun) { if (dryRun) { _throwIfNotNullInDryRun(config, BuildModeImpl.configKey); return null; @@ -264,7 +265,8 @@ abstract class HookConfigImpl implements HookConfig { } } - static LinkModePreferenceImpl parseLinkModePreference(Config config) => + static LinkModePreferenceImpl parseLinkModePreference( + Map config) => LinkModePreferenceImpl.fromString( config.string( LinkModePreferenceImpl.configKey, @@ -272,7 +274,7 @@ abstract class HookConfigImpl implements HookConfig { ), ); - static OSImpl parseTargetOS(Config config) => OSImpl.fromString( + static OSImpl parseTargetOS(Map config) => OSImpl.fromString( config.string( OSImpl.configKey, validValues: OSImpl.values.map((e) => '$e'), @@ -280,7 +282,7 @@ abstract class HookConfigImpl implements HookConfig { ); static ArchitectureImpl? parseTargetArchitecture( - Config config, + Map config, bool dryRun, OSImpl? targetOS, ) { @@ -305,7 +307,7 @@ abstract class HookConfigImpl implements HookConfig { } static IOSSdkImpl? parseTargetIOSSdk( - Config config, bool dryRun, OSImpl? targetOS) { + Map config, bool dryRun, OSImpl? targetOS) { if (dryRun) { _throwIfNotNullInDryRun(config, IOSSdkImpl.configKey); return null; @@ -322,7 +324,7 @@ abstract class HookConfigImpl implements HookConfig { } static int? parseTargetAndroidNdkApi( - Config config, + Map config, bool dryRun, OSImpl? targetOS, ) { @@ -337,7 +339,7 @@ abstract class HookConfigImpl implements HookConfig { } static int? parseTargetIosVersion( - Config config, + Map config, bool dryRun, OSImpl? targetOS, ) { @@ -352,7 +354,7 @@ abstract class HookConfigImpl implements HookConfig { } static int? parseTargetMacOSVersion( - Config config, + Map config, bool dryRun, OSImpl? targetOS, ) { @@ -366,84 +368,106 @@ abstract class HookConfigImpl implements HookConfig { } } - static Uri? _parseArchiver(Config config, bool dryRun) { - if (dryRun) { - _throwIfNotNullInDryRun(config, CCompilerConfigImpl.arConfigKeyFull); - return null; - } else { - return config.optionalPath( - CCompilerConfigImpl.arConfigKeyFull, + static Uri? _parseArchiver(Uri baseUri, Map config) => + config.optionalPath( + CCompilerConfigImpl.arConfigKey, + baseUri: baseUri, mustExist: true, ); - } - } - static Uri? _parseCompiler(Config config, bool dryRun) { - if (dryRun) { - _throwIfNotNullInDryRun(config, CCompilerConfigImpl.ccConfigKeyFull); - return null; - } else { - return config.optionalPath( - CCompilerConfigImpl.ccConfigKeyFull, + static Uri? _parseCompiler(Uri baseUri, Map config) => + config.optionalPath( + CCompilerConfigImpl.ccConfigKey, + baseUri: baseUri, mustExist: true, ); - } - } - static Uri? _parseLinker(Config config, bool dryRun) { - if (dryRun) { - _throwIfNotNullInDryRun(config, CCompilerConfigImpl.ccConfigKeyFull); - return null; - } else { - return config.optionalPath( - CCompilerConfigImpl.ldConfigKeyFull, + static Uri? _parseLinker(Uri baseUri, Map config) => + config.optionalPath( + CCompilerConfigImpl.ldConfigKey, + baseUri: baseUri, mustExist: true, ); - } - } - static Uri? _parseEnvScript(Config config, bool dryRun, Uri? compiler) { - if (dryRun) { - _throwIfNotNullInDryRun(config, CCompilerConfigImpl.ccConfigKeyFull); - return null; - } else { - return (compiler != null && compiler.toFilePath().endsWith('cl.exe')) - ? config.path(CCompilerConfigImpl.envScriptConfigKeyFull, - mustExist: true) + static Uri? _parseEnvScript( + Uri baseUri, Map config, Uri? compiler) => + (compiler != null && compiler.toFilePath().endsWith('cl.exe')) + ? config.path(CCompilerConfigImpl.envScriptConfigKey, + baseUri: baseUri, mustExist: true) : null; - } - } - static List? _parseEnvScriptArgs(Config config, bool dryRun) { - if (dryRun) { - _throwIfNotNullInDryRun(config, CCompilerConfigImpl.ccConfigKeyFull); - return null; - } else { - return config.optionalStringList( - CCompilerConfigImpl.envScriptArgsConfigKeyFull, - splitEnvironmentPattern: ' ', - ); - } - } + static List? _parseEnvScriptArgs(Map config) => + config.optionalStringList(CCompilerConfigImpl.envScriptArgsConfigKey); - static List parseSupportedAssetTypes(Config config) => + static List parseSupportedAssetTypes(Map config) => config.optionalStringList(supportedAssetTypesKey) ?? [NativeCodeAsset.type]; - static CCompilerConfigImpl parseCCompiler(Config config, bool dryRun) { - final parseCompiler = _parseCompiler(config, dryRun); - final cCompiler = CCompilerConfigImpl( - archiver: _parseArchiver(config, dryRun), - compiler: parseCompiler, - envScript: _parseEnvScript(config, dryRun, parseCompiler), - envScriptArgs: _parseEnvScriptArgs(config, dryRun), - linker: _parseLinker(config, dryRun), + static CCompilerConfigImpl parseCCompiler( + Uri baseUri, Map config, bool dryRun) { + if (dryRun) { + _throwIfNotNullInDryRun(config, CCompilerConfigImpl.configKey); + } + + final cCompilerJson = + config.getOptional>(CCompilerConfigImpl.configKey); + + Uri? archiver; + Uri? compiler; + Uri? linker; + Uri? envScript; + List? envScriptArgs; + if (cCompilerJson != null) { + compiler = _parseCompiler(baseUri, cCompilerJson); + archiver = _parseArchiver(baseUri, cCompilerJson); + envScript = _parseEnvScript(baseUri, cCompilerJson, compiler); + envScriptArgs = _parseEnvScriptArgs(cCompilerJson); + linker = _parseLinker(baseUri, cCompilerJson); + } + + // If the bundling tool didn't specify a C compiler we fallback to + // identifying the C compiler based on specific environment variables. + { + final env = Platform.environment; + String? unparseKey(String key) => key.replaceAll('.', '__').toUpperCase(); + String? lookup(String key) => env[unparseKey(key)]; + Uri? lookupUri(String key) { + final value = lookup(key); + return value != null ? Uri.file(value) : null; + } + + List? lookupList(String key) { + final value = lookup(key); + if (value == null) return null; + final list = value + .split(' ') + .map((arg) => arg.trim()) + .where((arg) => arg.isNotEmpty) + .toList(); + if (list.isEmpty) return null; + return list; + } + + archiver ??= lookupUri(CCompilerConfigImpl.arConfigKeyFull); + compiler ??= lookupUri(CCompilerConfigImpl.ccConfigKeyFull); + linker ??= lookupUri(CCompilerConfigImpl.ldConfigKeyFull); + envScript ??= lookupUri(CCompilerConfigImpl.envScriptConfigKeyFull); + envScriptArgs ??= + lookupList(CCompilerConfigImpl.envScriptArgsConfigKeyFull); + } + + return CCompilerConfigImpl( + archiver: archiver, + compiler: compiler, + envScript: envScript, + envScriptArgs: envScriptArgs, + linker: linker, ); - return cCompiler; } - static void _throwIfNotNullInDryRun(Config config, String key) { - final object = config.valueOf(key); + 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 diff --git a/pkgs/native_assets_cli/lib/src/model/link_config.dart b/pkgs/native_assets_cli/lib/src/model/link_config.dart index 08a9aab7b..211dbefe9 100644 --- a/pkgs/native_assets_cli/lib/src/model/link_config.dart +++ b/pkgs/native_assets_cli/lib/src/model/link_config.dart @@ -78,34 +78,30 @@ class LinkConfigImpl extends HookConfigImpl implements LinkConfig { }.sortOnKey(); static LinkConfig fromArguments(List arguments) { - final argParser = ArgParser()..addOption('config'); - - final results = argParser.parse(arguments); - final linkConfigContents = - File(results['config'] as String).readAsStringSync(); - final linkConfigJson = - jsonDecode(linkConfigContents) as Map; - - return fromJson(linkConfigJson); + final configPath = getConfigArgument(arguments); + final bytes = File(configPath).readAsBytesSync(); + final linkConfigJson = const Utf8Decoder() + .fuse(const JsonDecoder()) + .convert(bytes) as Map; + return fromJson(linkConfigJson, baseUri: Uri.parse(configPath)); } - static LinkConfigImpl fromJson(Map linkConfigJson) { - final config = - Config.fromConfigFileContents(fileContents: jsonEncode(linkConfigJson)); + static LinkConfigImpl fromJson(Map config, {Uri? baseUri}) { + baseUri = Uri.base; final dryRun = HookConfigImpl.parseDryRun(config) ?? false; final targetOS = HookConfigImpl.parseTargetOS(config); return LinkConfigImpl( - outputDirectory: HookConfigImpl.parseOutDir(config), - outputDirectoryShared: HookConfigImpl.parseOutDirShared(config), + outputDirectory: HookConfigImpl.parseOutDir(baseUri, config), + outputDirectoryShared: HookConfigImpl.parseOutDirShared(baseUri, config), packageName: HookConfigImpl.parsePackageName(config), - packageRoot: HookConfigImpl.parsePackageRoot(config), + packageRoot: HookConfigImpl.parsePackageRoot(baseUri, 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), + cCompiler: HookConfigImpl.parseCCompiler(baseUri, config, dryRun), supportedAssetTypes: HookConfigImpl.parseSupportedAssetTypes(config), targetAndroidNdkApi: HookConfigImpl.parseTargetAndroidNdkApi(config, dryRun, targetOS), @@ -115,16 +111,17 @@ class LinkConfigImpl extends HookConfigImpl implements LinkConfig { targetMacOSVersion: HookConfigImpl.parseTargetMacOSVersion(config, dryRun, targetOS), assets: parseAssets(config), - recordedUsagesFile: parseRecordedUsagesUri(config), + recordedUsagesFile: parseRecordedUsagesUri(baseUri, config), dryRun: dryRun, ); } - static Uri? parseRecordedUsagesUri(Config config) => - config.optionalPath(resourceIdentifierKey); + static Uri? parseRecordedUsagesUri( + Uri baseUri, Map config) => + config.optionalPath(resourceIdentifierKey, baseUri: baseUri); - static List parseAssets(Config config) => - AssetImpl.listFromJson(config.valueOf(assetsKey)); + static List parseAssets(Map config) => + AssetImpl.listFromJson(config.optionalList(assetsKey)); @override bool operator ==(Object other) { diff --git a/pkgs/native_assets_cli/pubspec.yaml b/pkgs/native_assets_cli/pubspec.yaml index 5530f45ed..944665ffe 100644 --- a/pkgs/native_assets_cli/pubspec.yaml +++ b/pkgs/native_assets_cli/pubspec.yaml @@ -16,8 +16,6 @@ environment: sdk: '>=3.5.0 <4.0.0' dependencies: - args: ^2.4.2 - cli_config: ^0.2.0 collection: ^1.17.1 crypto: ^3.0.3 logging: ^1.2.0