Skip to content

Commit 3fbbf07

Browse files
authored
[native_assets_cli] Add user_defines (#2165)
Bug: #39 Note passing in the user-defines should be done by the Dart and Flutter SDK, they need to decide where to take the command-line arguments, and how to read from the `pubspec.yaml`. The `NativeAssetsBuildRunner` provides a suggestion about where to put user-defines in the `pubspec.yaml`: ```yaml hooks: user_defines: my_package: user_define_key: user_define_value user_define_key2: foo: bar some_other_package: user_define_key3: user_define_value3 ``` Moreover, it provides a helper function that can be reused in SDKs after the pubspec yaml is parsed. ### Design choices (According to the discussion on the bug.) * User-defines are name-spaced per package, we don't want new user-defines to invalidate the cache for other packages. * User-defines can be provided for any package in the dependency graph. * If user-defines need to be shared across packages, the common dependency package can export it as metadata. ### Test This change is tested by invoking the build with user-defines, and in the hook failing if the defines are not available.
1 parent 8a1f836 commit 3fbbf07

File tree

16 files changed

+229
-0
lines changed

16 files changed

+229
-0
lines changed

.github/workflows/native.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ jobs:
114114
- run: dart pub get -C test_data/reuse_dynamic_library/
115115
if: ${{ matrix.package == 'native_assets_builder' }}
116116

117+
- run: dart pub get -C test_data/user_defines/
118+
if: ${{ matrix.package == 'native_assets_builder' }}
119+
117120
- run: dart pub get -C test_data/no_hook/
118121
if: ${{ matrix.package == 'native_assets_builder' }}
119122

pkgs/code_assets/test/data/build_input_macos.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,8 @@
7171
"out_file": "/Users/dacoharkes/src/dacoharkes/playground/my_package/example/.dart_tool/native_assets_builder/my_package/ca4e7d3d4e7b8912cbd24d9e8a6cecdc/output.json",
7272
"package_name": "my_package",
7373
"package_root": "/Users/dacoharkes/src/dacoharkes/playground/my_package/",
74+
"user_defines": {
75+
"some_key": "some_value"
76+
},
7477
"version": "1.9.0"
7578
}

pkgs/code_assets/test/data/link_input_macos.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,8 @@
7171
"out_file": "/Users/dacoharkes/src/dacoharkes/playground/my_package/example/.dart_tool/native_assets_builder/my_package/ca4e7d3d4e7b8912cbd24d9e8a6cecdc/output.json",
7272
"package_name": "my_package",
7373
"package_root": "/Users/dacoharkes/src/dacoharkes/playground/my_package/",
74+
"user_defines": {
75+
"some_key": "some_value"
76+
},
7477
"version": "1.9.0"
7578
}

pkgs/data_assets/test/data/build_input.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,8 @@
4646
"out_file": "/Users/dacoharkes/src/dacoharkes/playground/my_package/example/.dart_tool/native_assets_builder/my_package/ca4e7d3d4e7b8912cbd24d9e8a6cecdc/output.json",
4747
"package_name": "my_package",
4848
"package_root": "/Users/dacoharkes/src/dacoharkes/playground/my_package/",
49+
"user_defines": {
50+
"some_key": "some_value"
51+
},
4952
"version": "1.9.0"
5053
}

pkgs/data_assets/test/data/link_input.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,8 @@
3232
"out_file": "/Users/dacoharkes/src/dacoharkes/playground/my_package/example/.dart_tool/native_assets_builder/my_package/ca4e7d3d4e7b8912cbd24d9e8a6cecdc/output.json",
3333
"package_name": "my_package",
3434
"package_root": "/Users/dacoharkes/src/dacoharkes/playground/my_package/",
35+
"user_defines": {
36+
"some_key": "some_value"
37+
},
3538
"version": "1.9.0"
3639
}

pkgs/hooks/doc/schema/shared/shared_definitions.schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@
174174
"package_root": {
175175
"$ref": "#/definitions/absolutePath"
176176
},
177+
"user_defines": {
178+
"type": "object",
179+
"additionalProperties": true
180+
},
177181
"version": {
178182
"type": "string"
179183
}

pkgs/hooks/test/data/build_input.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,8 @@
3535
"out_file": "/Users/dacoharkes/src/dacoharkes/playground/my_package/example/.dart_tool/native_assets_builder/my_package/ca4e7d3d4e7b8912cbd24d9e8a6cecdc/output.json",
3636
"package_name": "my_package",
3737
"package_root": "/Users/dacoharkes/src/dacoharkes/playground/my_package/",
38+
"user_defines": {
39+
"some_key": "some_value"
40+
},
3841
"version": "1.9.0"
3942
}

pkgs/hooks/test/data/link_input.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,8 @@
2424
"out_file": "/Users/dacoharkes/src/dacoharkes/playground/my_package/example/.dart_tool/native_assets_builder/my_package/ca4e7d3d4e7b8912cbd24d9e8a6cecdc/output.json",
2525
"package_name": "my_package",
2626
"package_root": "/Users/dacoharkes/src/dacoharkes/playground/my_package/",
27+
"user_defines": {
28+
"some_key": "some_value"
29+
},
2730
"version": "1.9.0"
2831
}

pkgs/hooks/test/schema/helpers.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ FieldsReturn _hookFields({
323323
([r'$schema'], expectOptionalFieldMissing),
324324
(['version'], versionMissingExpectation),
325325
if (inputOrOutput == InputOrOutput.input) ...[
326+
(['user_defines'], expectOptionalFieldMissing),
326327
(['out_dir_shared'], expectRequiredFieldMissing),
327328
(['out_dir'], expectRequiredFieldMissing),
328329
(['package_name'], expectRequiredFieldMissing),

pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class NativeAssetsBuildRunner {
4646
final Uri dartExecutable;
4747
final Duration singleHookTimeout;
4848
final Map<String, String> hookEnvironment;
49+
final Map<String, Map<String, Object?>?> userDefines;
4950
final PackageLayout packageLayout;
5051

5152
NativeAssetsBuildRunner({
@@ -55,6 +56,7 @@ class NativeAssetsBuildRunner {
5556
required this.packageLayout,
5657
Duration? singleHookTimeout,
5758
Map<String, String>? hookEnvironment,
59+
this.userDefines = const {},
5860
}) : _fileSystem = fileSystem,
5961
singleHookTimeout = singleHookTimeout ?? const Duration(minutes: 5),
6062
hookEnvironment =
@@ -131,6 +133,7 @@ class NativeAssetsBuildRunner {
131133
outputFile: buildDirUri.resolve('output.json'),
132134
outputDirectory: outDirUri,
133135
outputDirectoryShared: outDirSharedUri,
136+
userDefines: userDefines[package.name],
134137
);
135138

136139
final input = BuildInput(inputBuilder.json);
@@ -228,6 +231,7 @@ class NativeAssetsBuildRunner {
228231
outputFile: buildDirUri.resolve('output.json'),
229232
outputDirectory: outDirUri,
230233
outputDirectoryShared: outDirSharedUri,
234+
userDefines: userDefines[package.name],
231235
);
232236
inputBuilder.setupLink(
233237
assets: buildResult.encodedAssetsForLinking[package.name] ?? [],
@@ -861,6 +865,80 @@ ${compileResult.stdout}
861865
? BuildOutput(hookOutputJson)
862866
: LinkOutput(hookOutputJson);
863867
}
868+
869+
/// Returns a list of errors for [readHooksUserDefinesFromPubspec].
870+
static List<String> validateHooksUserDefinesFromPubspec(
871+
Map<Object?, Object?> pubspec,
872+
) {
873+
final hooks = pubspec['hooks'];
874+
if (hooks == null) return [];
875+
if (hooks is! Map) {
876+
return ["Expected 'hooks' to be a map. Found: '$hooks'"];
877+
}
878+
final userDefines = hooks['user_defines'];
879+
if (userDefines == null) return [];
880+
if (userDefines is! Map) {
881+
return [
882+
"Expected 'hooks.user_defines' to be a map. Found: '$userDefines'",
883+
];
884+
}
885+
886+
final errors = <String>[];
887+
for (final MapEntry(:key, :value) in userDefines.entries) {
888+
if (key is! String) {
889+
errors.add(
890+
"Expected 'hooks.user_defines' to be a map with string keys."
891+
" Found key: '$key'.",
892+
);
893+
}
894+
if (value is! Map) {
895+
errors.add(
896+
"Expected 'hooks.user_defines.$key' to be a map. Found: '$value'",
897+
);
898+
continue;
899+
}
900+
for (final childKey in value.keys) {
901+
if (childKey is! String) {
902+
errors.add(
903+
"Expected 'hooks.user_defines.$key' to be a "
904+
"map with string keys. Found key: '$childKey'.",
905+
);
906+
}
907+
}
908+
}
909+
return errors;
910+
}
911+
912+
/// Reads the user-defines from a pubspec.yaml in the suggested location.
913+
///
914+
/// SDKs do not have to follow this, they might support user-defines in a
915+
/// different way.
916+
///
917+
/// The [pubspec] is expected to be the decoded yaml, a Map.
918+
///
919+
/// Before invoking, check errors with [validateHooksUserDefinesFromPubspec].
920+
static Map<String, Map<String, Object?>> readHooksUserDefinesFromPubspec(
921+
Map<Object?, Object?> pubspec,
922+
) {
923+
assert(validateHooksUserDefinesFromPubspec(pubspec).isEmpty);
924+
final hooks = pubspec['hooks'];
925+
if (hooks is! Map) {
926+
return {};
927+
}
928+
final userDefines = hooks['user_defines'];
929+
if (userDefines is! Map) {
930+
return {};
931+
}
932+
return {
933+
for (final MapEntry(:key, :value) in userDefines.entries)
934+
if (key is String)
935+
key: {
936+
if (value is Map)
937+
for (final MapEntry(:key, :value) in value.entries)
938+
if (key is String) key: value,
939+
},
940+
};
941+
}
864942
}
865943

866944
/// Parses depfile contents.

0 commit comments

Comments
 (0)