Skip to content

[native_assets_cli] Add base path for user-defines #2209

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 16, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion pkgs/hooks/doc/schema/shared/shared_definitions.schema.json
Original file line number Diff line number Diff line change
@@ -176,7 +176,11 @@
},
"user_defines": {
"type": "object",
"additionalProperties": true
"properties": {
"workspace_pubspec": {
"$ref": "#/definitions/UserDefinesSource"
}
}
},
"version": {
"type": "string"
@@ -256,6 +260,22 @@
"key"
]
},
"UserDefinesSource": {
"type": "object",
"properties": {
"base_path": {
"$ref": "#/definitions/absolutePath"
},
"defines": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"base_path",
"defines"
]
},
"absolutePath": {
"type": "string",
"pattern": "^(\\/|[A-Za-z]:)"
5 changes: 5 additions & 0 deletions pkgs/native_assets_builder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.16.0-wip

- Pass in path to pubspec (to read user-defines) in this package rather than in
the SDKs using this package.

## 0.15.0

- Bump `package:native_assets_cli` to 0.15.0.
6 changes: 5 additions & 1 deletion pkgs/native_assets_builder/lib/native_assets_builder.dart
Original file line number Diff line number Diff line change
@@ -3,7 +3,11 @@
// BSD-style license that can be found in the LICENSE file.

export 'package:native_assets_builder/src/build_runner/build_runner.dart'
show BuildInputCreator, LinkInputCreator, NativeAssetsBuildRunner;
show
BuildInputCreator,
LinkInputCreator,
NativeAssetsBuildRunner,
UserDefines;
export 'package:native_assets_builder/src/model/build_result.dart'
show BuildResult;
export 'package:native_assets_builder/src/model/kernel_assets.dart';
119 changes: 102 additions & 17 deletions pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import 'package:logging/logging.dart';
import 'package:meta/meta.dart';
import 'package:native_assets_cli/native_assets_cli_internal.dart';
import 'package:package_config/package_config.dart';
import 'package:yaml/yaml.dart';

import '../dependencies_hash_file/dependencies_hash_file.dart';
import '../locking/locking.dart';
@@ -46,7 +47,7 @@ class NativeAssetsBuildRunner {
final Uri dartExecutable;
final Duration singleHookTimeout;
final Map<String, String> hookEnvironment;
final Map<String, Map<String, Object?>?> userDefines;
final UserDefines? userDefines;
final PackageLayout packageLayout;

NativeAssetsBuildRunner({
@@ -56,7 +57,7 @@ class NativeAssetsBuildRunner {
required this.packageLayout,
Duration? singleHookTimeout,
Map<String, String>? hookEnvironment,
this.userDefines = const {},
this.userDefines,
}) : _fileSystem = fileSystem,
singleHookTimeout = singleHookTimeout ?? const Duration(minutes: 5),
hookEnvironment =
@@ -73,6 +74,24 @@ class NativeAssetsBuildRunner {
return packagesWithHook.map((e) => e.name).toList();
}

Future<HookResult?> _checkUserDefines(
LoadedUserDefines? loadedUserDefines,
) async {
if (loadedUserDefines?.pubspecErrors.isNotEmpty ?? false) {
logger.severe('pubspec.yaml contains errors');
for (final error in loadedUserDefines!.pubspecErrors) {
logger.severe(error);
}
return null;
}
return HookResult(
dependencies: switch (userDefines?.workspacePubspec) {
null => [],
final pubspec => [pubspec],
},
);
}

/// This method is invoked by launchers such as dartdev (for `dart run`) and
/// flutter_tools (for `flutter run` and `flutter build`).
///
@@ -86,14 +105,19 @@ class NativeAssetsBuildRunner {
required List<ProtocolExtension> extensions,
required bool linkingEnabled,
}) async {
final loadedUserDefines = await _loadedUserDefines;
final hookResultUserDefines = await _checkUserDefines(loadedUserDefines);
if (hookResultUserDefines == null) {
return null;
}
var hookResult = hookResultUserDefines;

final (buildPlan, packageGraph) = await _makePlan(
hook: Hook.build,
buildResult: null,
);
if (buildPlan == null) return null;

var hookResult = HookResult();

/// Key is packageName.
final globalMetadata = <String, Metadata>{};

@@ -133,7 +157,7 @@ class NativeAssetsBuildRunner {
outputFile: buildDirUri.resolve('output.json'),
outputDirectory: outDirUri,
outputDirectoryShared: outDirSharedUri,
userDefines: userDefines[package.name],
userDefines: loadedUserDefines?[package.name],
);

final input = BuildInput(inputBuilder.json);
@@ -199,13 +223,19 @@ class NativeAssetsBuildRunner {
Uri? resourceIdentifiers,
required BuildResult buildResult,
}) async {
final loadedUserDefines = await _loadedUserDefines;
final hookResultUserDefines = await _checkUserDefines(loadedUserDefines);
if (hookResultUserDefines == null) {
return null;
}
var linkResult = hookResultUserDefines;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering if its worthwhile to factor this logic out since it seems to be 1:1 repeated from above?

final (buildPlan, packageGraph) = await _makePlan(
hook: Hook.link,
buildResult: buildResult,
);
if (buildPlan == null) return null;

var linkResult = HookResult();
for (final package in buildPlan) {
final inputBuilder = LinkInputBuilder();
for (final e in extensions) {
@@ -231,7 +261,7 @@ class NativeAssetsBuildRunner {
outputFile: buildDirUri.resolve('output.json'),
outputDirectory: outDirUri,
outputDirectoryShared: outDirSharedUri,
userDefines: userDefines[package.name],
userDefines: loadedUserDefines?[package.name],
);
inputBuilder.setupLink(
assets: buildResult.encodedAssetsForLinking[package.name] ?? [],
@@ -461,9 +491,9 @@ ${e.message}
) async {
final inputFile = buildDirUri.resolve('input.json');
final inputFileContents = const JsonEncoder.withIndent(
' ',
' ',
).convert(input.json);
logger.info('input.json contents: $inputFileContents');
logger.info('input.json contents:\n$inputFileContents');
await _fileSystem.file(inputFile).writeAsString(inputFileContents);
final hookOutputUri = input.outputFile;
final hookOutputFile = _fileSystem.file(hookOutputUri);
@@ -856,18 +886,18 @@ ${compileResult.stdout}
// TODO(dcharkes): Remove when hooks with 1.7.0 are no longer supported.
File hookOutputFileDeprecated,
) {
final decode = const Utf8Decoder().fuse(const JsonDecoder()).convert;
final file =
hookOutputFile.existsSync() ? hookOutputFile : hookOutputFileDeprecated;
final hookOutputJson =
decode(file.readAsBytesSync()) as Map<String, Object?>;
final fileContents = file.readAsStringSync();
logger.info('output.json contents:\n$fileContents');
final hookOutputJson = jsonDecode(fileContents) as Map<String, Object?>;
return hook == Hook.build
? BuildOutput(hookOutputJson)
: LinkOutput(hookOutputJson);
}

/// Returns a list of errors for [readHooksUserDefinesFromPubspec].
static List<String> validateHooksUserDefinesFromPubspec(
/// Returns a list of errors for [_readHooksUserDefinesFromPubspec].
static List<String> _validateHooksUserDefinesFromPubspec(
Map<Object?, Object?> pubspec,
) {
final hooks = pubspec['hooks'];
@@ -916,11 +946,11 @@ ${compileResult.stdout}
///
/// The [pubspec] is expected to be the decoded yaml, a Map.
///
/// Before invoking, check errors with [validateHooksUserDefinesFromPubspec].
static Map<String, Map<String, Object?>> readHooksUserDefinesFromPubspec(
/// Before invoking, check errors with [_validateHooksUserDefinesFromPubspec].
static Map<String, Map<String, Object?>> _readHooksUserDefinesFromPubspec(
Map<Object?, Object?> pubspec,
) {
assert(validateHooksUserDefinesFromPubspec(pubspec).isEmpty);
assert(_validateHooksUserDefinesFromPubspec(pubspec).isEmpty);
final hooks = pubspec['hooks'];
if (hooks is! Map) {
return {};
@@ -939,6 +969,61 @@ ${compileResult.stdout}
},
};
}

late final Future<LoadedUserDefines?> _loadedUserDefines = () async {
final pubspec = userDefines?.workspacePubspec;
if (pubspec == null) {
return null;
}
final contents = await _fileSystem.file(pubspec).readAsString();
final decoded = loadYaml(contents) as Map<Object?, Object?>;
final errors = _validateHooksUserDefinesFromPubspec(decoded);
final defines = _readHooksUserDefinesFromPubspec(decoded);
return LoadedUserDefines(
pubspecErrors: errors,
pubspecDefines: defines,
pubspecBasePath: pubspec,
);
}();
}

/// The user-defines information passed from the SDK to the
/// [NativeAssetsBuildRunner].
///
/// Currently only holds [workspacePubspec]. (In the future this class will also
/// take command-line arguments and a working directory for the command-line
/// argument paths to be resolved against.)
class UserDefines {
/// The pubspec.yaml of the pub workspace.
///
/// User-defines are read from this file.
final Uri? workspacePubspec;

UserDefines({required this.workspacePubspec});
}

class LoadedUserDefines {
final List<String> pubspecErrors;

final Map<String, Map<String, Object?>> pubspecDefines;

final Uri pubspecBasePath;

LoadedUserDefines({
required this.pubspecErrors,
required this.pubspecDefines,
required this.pubspecBasePath,
});

PackageUserDefines operator [](String packageName) => PackageUserDefines(
workspacePubspec: switch (pubspecDefines[packageName]) {
null => null,
final defines => PackageUserDefinesSource(
defines: defines,
basePath: pubspecBasePath,
),
},
);
}

/// Parses depfile contents.
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ import '../../native_assets_builder.dart';
/// convention for caching:
/// https://dart.dev/tools/pub/package-layout#project-specific-caching-for-tools
class PackageLayout {
/// Package config containing the information of where to foot the root [Uri]s
/// Package config containing the information of where to find the root [Uri]s
/// of other packages.
///
/// Can be `null` to enable quick construction of a
4 changes: 2 additions & 2 deletions pkgs/native_assets_builder/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: native_assets_builder
description: >-
This package is the backend that invokes build hooks.
version: 0.15.0
version: 0.16.0-wip
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_assets_builder

resolution: workspace
@@ -16,7 +16,7 @@ dependencies:
graphs: ^2.3.2
logging: ^1.3.0
meta: ^1.16.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip
package_config: ^2.1.0
pub_semver: ^2.2.0
yaml: ^3.1.3
4 changes: 2 additions & 2 deletions pkgs/native_assets_builder/test/build_runner/helpers.dart
Original file line number Diff line number Diff line change
@@ -75,7 +75,7 @@ Future<BuildResult?> build(
bool linkingEnabled = false,
required List<BuildAssetType> buildAssetTypes,
Map<String, String>? hookEnvironment,
Map<String, Map<String, Object?>?>? userDefines,
UserDefines? userDefines,
}) async {
final targetOS = target?.os ?? OS.current;
final runPackageName_ =
@@ -92,7 +92,7 @@ Future<BuildResult?> build(
fileSystem: const LocalFileSystem(),
hookEnvironment: hookEnvironment,
packageLayout: packageLayout,
userDefines: userDefines ?? {},
userDefines: userDefines,
).build(
extensions: [
if (buildAssetTypes.contains(BuildAssetType.code))
31 changes: 14 additions & 17 deletions pkgs/native_assets_builder/test/test_data/user_defines_test.dart
Original file line number Diff line number Diff line change
@@ -7,9 +7,10 @@ library;

import 'dart:io';

import 'package:file_testing/file_testing.dart';
import 'package:native_assets_builder/native_assets_builder.dart';
import 'package:native_assets_builder/src/build_runner/build_runner.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';

import '../build_runner/helpers.dart';
import '../helpers.dart';
@@ -25,32 +26,28 @@ void main() async {

await runPubGet(workingDirectory: packageUri, logger: logger);

final pubspec =
loadYamlDocument(
File.fromUri(
packageUri.resolve('pubspec.yaml'),
).readAsStringSync(),
).contents
as YamlMap;
expect(
NativeAssetsBuildRunner.validateHooksUserDefinesFromPubspec(pubspec),
isEmpty,
);
final userDefines =
NativeAssetsBuildRunner.readHooksUserDefinesFromPubspec(pubspec);

final logMessages = <String>[];
final pubspecUri = packageUri.resolve('pubspec.yaml');
final result =
(await build(
packageUri,
logger,
dartExecutable,
capturedLogs: logMessages,
buildAssetTypes: [BuildAssetType.data],
userDefines: userDefines,
userDefines: UserDefines(workspacePubspec: pubspecUri),
))!;

expect(result.encodedAssets.length, 1);
final dataAssets =
result.encodedAssets.map((e) => e.asDataAsset).toList();
expect(dataAssets.length, 2);
for (final dataAsset in dataAssets) {
expect(File.fromUri(dataAsset.file), exists);
}

// The native assets build runner must be reinvoked if the pubspec
// changes, as the pubspec could contain user-defines.
expect(result.dependencies, contains(pubspecUri));
}),
);
}
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@ environment:
dependencies:
logging: ^1.3.0
meta: ^1.16.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ dependencies:
complex_link_helper:
path: ../complex_link_helper/
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
cli_config: ^0.2.0
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
cyclic_package_2:
path: ../cyclic_package_2
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
cyclic_package_1:
path: ../cyclic_package_1
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
fail_build:
path: ../fail_build/
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
depend_on_fail_build:
path: ../depend_on_fail_build/
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
fail_on_os_sdk_version_linker:
path: ../fail_on_os_sdk_version_linker/
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
ffigen: ^18.0.0
1 change: 1 addition & 0 deletions pkgs/native_assets_builder/test_data/manifest.yaml
Original file line number Diff line number Diff line change
@@ -179,6 +179,7 @@
- use_all_api/hook/build.dart
- use_all_api/hook/link.dart
- use_all_api/pubspec.yaml
- user_defines/assets/data.json
- user_defines/bin/user_defines.dart
- user_defines/hook/build.dart
- user_defines/pubspec.yaml
4 changes: 2 additions & 2 deletions pkgs/native_assets_builder/test_data/native_add/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -13,8 +13,8 @@ dependencies:
logging: ^1.3.0
native_add:
path: ../native_add/
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
logging: ^1.3.0
meta: ^1.16.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
4 changes: 2 additions & 2 deletions pkgs/native_assets_builder/test_data/no_hook/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip
package_with_metadata:
path: ../package_with_metadata/

Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -13,8 +13,8 @@ environment:

dependencies:
logging: ^1.1.1
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@ environment:

dependencies:
logging: ^1.1.1
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip
reusable_dynamic_library:
path: ../reusable_dynamic_library/

Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
cli_config: ^0.2.0
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ environment:

dependencies:
crypto: ^3.0.6
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ environment:
dependencies:
cli_config: ^0.2.0
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"foo": "bar"
}
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ void main(List<String> arguments) async {
final value1 = input.userDefines['user_define_key'];
if (value1 != 'user_define_value') {
throw Exception(
'User-define user_define_key does not have the right value.',
'User-define user_define_key does not have the right value: $value1.',
);
}
final value2 = input.userDefines['user_define_key2'];
@@ -23,5 +23,19 @@ void main(List<String> arguments) async {
);
File.fromUri(dataAsset.file).writeAsStringSync(jsonEncode(value2));
output.assets.data.add(dataAsset);

// Load some relative path as absolute path from user-defines.
final someFile = input.userDefines.path('some_file');
if (someFile == null) {
throw Exception(
'User-define some_file does not have the right value: '
'${input.userDefines['some_file']}.',
);
}
final file = File.fromUri(someFile);
output.addDependency(file.uri);
output.assets.data.add(
DataAsset(file: file.uri, name: 'data.json', package: input.packageName),
);
});
}
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
@@ -25,5 +25,6 @@ hooks:
user_define_key: user_define_value
user_define_key2:
foo: bar
some_file: assets/data.json
some_other_package: # package name
user_define_key3: user_define_value3
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ environment:
sdk: '>=3.7.0 <4.0.0'

dependencies:
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
lints: ^5.1.1
4 changes: 4 additions & 0 deletions pkgs/native_assets_cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.16.0-wip

- Pass the base path for the user-defines in the JSON.

## 0.15.0

- **Breaking change** JSON encoding migration: change written asset type to the
Original file line number Diff line number Diff line change
@@ -13,8 +13,8 @@ environment:
dependencies:
crypto: ^3.0.6
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
args: ^2.6.0
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ environment:

dependencies:
logging: ^1.3.0
native_assets_cli: ^0.15.0
native_toolchain_c: ^0.12.0
native_assets_cli: ^0.16.0-wip
native_toolchain_c: ^0.13.0-wip

dev_dependencies:
ffigen: ^18.0.0
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ environment:
dependencies:
logging: ^1.3.0
meta: ^1.16.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip
record_use: ^0.3.0

dev_dependencies:
2 changes: 2 additions & 0 deletions pkgs/native_assets_cli/lib/native_assets_cli_builder.dart
Original file line number Diff line number Diff line change
@@ -19,6 +19,8 @@ export 'src/extension.dart';
export 'src/model/dependencies.dart';
export 'src/model/resource_identifiers.dart';
export 'src/target.dart' show Target;
export 'src/user_defines.dart'
show PackageUserDefines, PackageUserDefinesSource;
export 'src/validation.dart'
show
validateBuildInput,
6 changes: 3 additions & 3 deletions pkgs/native_assets_cli/lib/src/api/build.dart
Original file line number Diff line number Diff line change
@@ -107,9 +107,9 @@ Future<void> build(
await builder(input, output);
final errors = await validateBuildOutput(input, BuildOutput(output.json));
if (errors.isEmpty) {
final jsonOutput = const JsonEncoder()
.fuse(const Utf8Encoder())
.convert(output.json);
final jsonOutput = const JsonEncoder.withIndent(
' ',
).fuse(const Utf8Encoder()).convert(output.json);
await File.fromUri(input.outputFile).writeAsBytes(jsonOutput);
} else {
final message = [
46 changes: 41 additions & 5 deletions pkgs/native_assets_cli/lib/src/config.dart
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ import 'encoded_asset.dart';
import 'extension.dart';
import 'hooks/syntax.g.dart' as syntax;
import 'metadata.dart';
import 'user_defines.dart';
import 'utils/datetime.dart';
import 'utils/json.dart';

@@ -99,7 +100,44 @@ extension type HookInputUserDefines._(HookInput _input) {
///
/// This can be arbitrary JSON/YAML if provided from the SDK from such source.
/// If it's provided from command-line arguments, it's likely a string.
Object? operator [](String key) => _input._syntax.userDefines?.json[key];
Object? operator [](String key) {
final syntaxNode = _input._syntax.userDefines;
if (syntaxNode == null) {
return null;
}
final packageUserDefines = PackageUserDefinesSyntax.fromSyntax(syntaxNode);
final pubspecSource = packageUserDefines.workspacePubspec;
return pubspecSource?.defines[key];
}

/// The absolute path for user-defines for [key] for this package.key
///
/// The relative path passed as user-define is resolved against the base path.
/// For user-defines originating from a JSON/YAML, the base path is this
/// JSON/YAML. For user-defines originating from command-line aruments, the
/// base path is the working directory of the command-line invocation.
///
/// If the user-define is `null` or not a [String], returns `null`.
Uri? path(String key) {
final syntaxNode = _input._syntax.userDefines;
if (syntaxNode == null) {
return null;
}
final packageUserDefines = PackageUserDefinesSyntax.fromSyntax(syntaxNode);
final pubspecSource = packageUserDefines.workspacePubspec;
final sources = <PackageUserDefinesSource>[];
if (pubspecSource != null) {
sources.add(pubspecSource);
}
// TODO: Add commandline arguments.
for (final source in sources) {
final relativepath = source.defines[key];
if (relativepath is String) {
return source.basePath.resolve(relativepath);
}
}
return null;
}
}

sealed class HookInputBuilder {
@@ -120,17 +158,15 @@ sealed class HookInputBuilder {
required Uri outputDirectory,
required Uri outputDirectoryShared,
required Uri outputFile,
Map<String, Object?>? userDefines,
PackageUserDefines? userDefines,
}) {
_syntax.version = latestVersion.toString();
_syntax.packageRoot = packageRoot;
_syntax.packageName = packageName;
_syntax.outDir = outputDirectory;
_syntax.outDirShared = outputDirectoryShared;
_syntax.outFile = outputFile;
_syntax.userDefines = userDefines == null
? null
: syntax.JsonObject.fromJson(userDefines);
_syntax.userDefines = userDefines?.toSyntax();
}

/// Constructs a checksum for a [BuildInput].
96 changes: 92 additions & 4 deletions pkgs/native_assets_cli/lib/src/hooks/syntax.g.dart
Original file line number Diff line number Diff line change
@@ -488,7 +488,7 @@ class HookInput extends JsonObject {
required Uri? outFile,
required String packageName,
required Uri packageRoot,
required JsonObject? userDefines,
required UserDefines? userDefines,
required String? version,
}) : super() {
this.config = config;
@@ -567,13 +567,13 @@ class HookInput extends JsonObject {

List<String> _validatePackageRoot() => _reader.validatePath('package_root');

JsonObject? get userDefines {
UserDefines? get userDefines {
final jsonValue = _reader.optionalMap('user_defines');
if (jsonValue == null) return null;
return JsonObject.fromJson(jsonValue, path: [...path, 'user_defines']);
return UserDefines.fromJson(jsonValue, path: [...path, 'user_defines']);
}

set userDefines(JsonObject? value) {
set userDefines(UserDefines? value) {
json.setOrRemove('user_defines', value?.json);
json.sortOnKey();
}
@@ -879,6 +879,94 @@ class MetadataAssetEncoding extends JsonObject {
String toString() => 'MetadataAssetEncoding($json)';
}

class UserDefines extends JsonObject {
UserDefines.fromJson(super.json, {super.path = const []}) : super.fromJson();

UserDefines({required UserDefinesSource? workspacePubspec}) : super() {
_workspacePubspec = workspacePubspec;
json.sortOnKey();
}

UserDefinesSource? get workspacePubspec {
final jsonValue = _reader.optionalMap('workspace_pubspec');
if (jsonValue == null) return null;
return UserDefinesSource.fromJson(
jsonValue,
path: [...path, 'workspace_pubspec'],
);
}

set _workspacePubspec(UserDefinesSource? value) {
json.setOrRemove('workspace_pubspec', value?.json);
}

List<String> _validateWorkspacePubspec() {
final mapErrors = _reader.validate<Map<String, Object?>?>(
'workspace_pubspec',
);
if (mapErrors.isNotEmpty) {
return mapErrors;
}
return workspacePubspec?.validate() ?? [];
}

@override
List<String> validate() => [
...super.validate(),
..._validateWorkspacePubspec(),
];

@override
String toString() => 'UserDefines($json)';
}

class UserDefinesSource extends JsonObject {
UserDefinesSource.fromJson(super.json, {super.path = const []})
: super.fromJson();

UserDefinesSource({required Uri basePath, required JsonObject defines})
: super() {
_basePath = basePath;
_defines = defines;
json.sortOnKey();
}

Uri get basePath => _reader.path$('base_path');

set _basePath(Uri value) {
json['base_path'] = value.toFilePath();
}

List<String> _validateBasePath() => _reader.validatePath('base_path');

JsonObject get defines {
final jsonValue = _reader.map$('defines');
return JsonObject.fromJson(jsonValue, path: [...path, 'defines']);
}

set _defines(JsonObject value) {
json['defines'] = value.json;
}

List<String> _validateDefines() {
final mapErrors = _reader.validate<Map<String, Object?>>('defines');
if (mapErrors.isNotEmpty) {
return mapErrors;
}
return defines.validate();
}

@override
List<String> validate() => [
...super.validate(),
..._validateBasePath(),
..._validateDefines(),
];

@override
String toString() => 'UserDefinesSource($json)';
}

class JsonObject {
final Map<String, Object?> json;

71 changes: 71 additions & 0 deletions pkgs/native_assets_cli/lib/src/user_defines.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) 2025, 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 'hooks/syntax.g.dart' as syntax;

/// The user-defines for a single build hokok invocation
///
/// Currently only holds [workspacePubspec]. (In the future this class will also
/// take command-line arguments and a working directory for the command-line
/// argument paths to be resolved against.)
class PackageUserDefines {
final PackageUserDefinesSource? workspacePubspec;

PackageUserDefines({required this.workspacePubspec});

@override
String toString() =>
'PackageUserDefines(workspacePubspec: $workspacePubspec)';
}

extension PackageUserDefinesSyntax on PackageUserDefines {
static PackageUserDefines fromSyntax(syntax.UserDefines syntaxNode) =>
PackageUserDefines(
workspacePubspec: switch (syntaxNode.workspacePubspec) {
null => PackageUserDefinesSource(
// Fallback behavior for old SDKs: read object as user-defines.
defines: syntaxNode.json,
// No known base path.
basePath: Uri.directory('/unknown/'),
),
final o => PackageUserDefinesSourceSyntax.fromSyntax(o),
},
);

syntax.UserDefines toSyntax() {
final result = syntax.UserDefines(
workspacePubspec: workspacePubspec?.toSyntax(),
);
// Fallback behavior for old hooks: write user-defines here.
result.json.addAll(workspacePubspec!.defines);
return result;
}
}

class PackageUserDefinesSource {
final Map<String, Object?> defines;

/// The base path for relative paths in [defines].
final Uri basePath;

PackageUserDefinesSource({required this.defines, required this.basePath});

@override
String toString() =>
'PackageUserDefinesSource(defines: $defines, basePath: $basePath)';
}

extension PackageUserDefinesSourceSyntax on PackageUserDefinesSource {
static PackageUserDefinesSource fromSyntax(
syntax.UserDefinesSource syntaxNode,
) => PackageUserDefinesSource(
defines: syntaxNode.defines.json,
basePath: syntaxNode.basePath,
);

syntax.UserDefinesSource toSyntax() => syntax.UserDefinesSource(
basePath: basePath,
defines: syntax.JsonObject.fromJson(defines),
);
}
2 changes: 1 addition & 1 deletion pkgs/native_assets_cli/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ description: >-
A library that contains the argument and file formats for implementing a
native assets CLI.

version: 0.15.0
version: 0.16.0-wip
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_assets_cli

topics:
4 changes: 4 additions & 0 deletions pkgs/native_toolchain_c/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.13.0-wip

- Bump `package:native_assets_cli` to 0.16.0.

## 0.12.0

- Bump `package:native_assets_cli` to 0.15.0.
4 changes: 2 additions & 2 deletions pkgs/native_toolchain_c/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: native_toolchain_c
description: >-
A library to invoke the native C compiler installed on the host machine.
version: 0.12.0
version: 0.13.0-wip
repository: https://github.com/dart-lang/native/tree/main/pkgs/native_toolchain_c

topics:
@@ -20,7 +20,7 @@ dependencies:
glob: ^2.1.1
logging: ^1.3.0
meta: ^1.16.0
native_assets_cli: ^0.15.0
native_assets_cli: ^0.16.0-wip
pub_semver: ^2.2.0

dev_dependencies:
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -66,5 +66,6 @@ hooks:
user_define_key: user_define_value
user_define_key2:
foo: bar
some_file: pkgs/native_assets_builder/test_data/user_defines/assets/data.json
some_other_package: # package name
user_define_key3: user_define_value3