Skip to content

Commit 549efc9

Browse files
committed
[native_assets_builder] Support pub workspaces 2
1 parent 3849808 commit 549efc9

File tree

11 files changed

+191
-122
lines changed

11 files changed

+191
-122
lines changed

pkgs/native_assets_builder/lib/native_assets_builder.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ export 'package:native_assets_builder/src/build_runner/build_runner.dart'
1212
LinkInputValidator,
1313
LinkValidator,
1414
NativeAssetsBuildRunner;
15-
export 'package:native_assets_builder/src/model/build_result.dart';
15+
export 'package:native_assets_builder/src/model/build_result.dart'
16+
show BuildResult;
1617
export 'package:native_assets_builder/src/model/kernel_assets.dart';
17-
export 'package:native_assets_builder/src/model/link_result.dart';
18-
export 'package:native_assets_builder/src/package_layout/package_layout.dart';
18+
export 'package:native_assets_builder/src/model/link_result.dart'
19+
show LinkResult;
20+
export 'package:native_assets_builder/src/package_layout/package_layout.dart'
21+
show PackageLayout;

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

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,37 @@
55
import 'dart:convert';
66
import 'dart:io' show Process;
77

8+
import 'package:file/file.dart';
89
import 'package:graphs/graphs.dart' as graphs;
910
import 'package:logging/logging.dart';
11+
import 'package:meta/meta.dart';
12+
import 'package:native_assets_cli/native_assets_cli_internal.dart';
1013
import 'package:package_config/package_config.dart';
1114

15+
import '../package_layout/package_layout.dart';
16+
17+
@internal
1218
class NativeAssetsBuildPlanner {
1319
final PackageGraph packageGraph;
14-
final List<Package> packagesWithNativeAssets;
1520
final Uri dartExecutable;
1621
final Logger logger;
22+
final PackageLayout packageLayout;
23+
final FileSystem fileSystem;
1724

18-
NativeAssetsBuildPlanner({
25+
NativeAssetsBuildPlanner._({
1926
required this.packageGraph,
20-
required this.packagesWithNativeAssets,
2127
required this.dartExecutable,
2228
required this.logger,
29+
required this.packageLayout,
30+
required this.fileSystem,
2331
});
2432

2533
static Future<NativeAssetsBuildPlanner> fromPackageConfigUri({
2634
required Uri packageConfigUri,
27-
required List<Package> packagesWithNativeAssets,
2835
required Uri dartExecutable,
2936
required Logger logger,
37+
required PackageLayout packageLayout,
38+
required FileSystem fileSystem,
3039
}) async {
3140
final workingDirectory = packageConfigUri.resolve('../');
3241
final result = await Process.run(
@@ -40,21 +49,67 @@ class NativeAssetsBuildPlanner {
4049
);
4150
final packageGraph =
4251
PackageGraph.fromPubDepsJsonString(result.stdout as String);
43-
return NativeAssetsBuildPlanner(
44-
packageGraph: packageGraph,
45-
packagesWithNativeAssets: packagesWithNativeAssets,
52+
final packageGraphFromRunPackage =
53+
packageGraph.subGraph(packageLayout.runPackageName);
54+
return NativeAssetsBuildPlanner._(
55+
packageGraph: packageGraphFromRunPackage,
4656
dartExecutable: dartExecutable,
4757
logger: logger,
58+
packageLayout: packageLayout,
59+
fileSystem: fileSystem,
4860
);
4961
}
5062

63+
/// All packages in [PackageLayout.packageConfig] with native assets.
64+
///
65+
/// Whether a package has native assets is defined by whether it contains
66+
/// a `hook/build.dart` or `hook/link.dart`.
67+
///
68+
/// For backwards compatibility, a toplevel `build.dart` is also supported.
69+
// TODO(https://github.com/dart-lang/native/issues/823): Remove fallback when
70+
// everyone has migrated. (Probably once we stop backwards compatibility of
71+
// the protocol version pre 1.2.0 on some future version.)
72+
Future<List<Package>> packagesWithHook(Hook hook) async => switch (hook) {
73+
Hook.build => _packagesWithBuildHook ??=
74+
await _runPackagesWithHook(hook),
75+
Hook.link => _packagesWithLinkHook ??= await _runPackagesWithHook(hook),
76+
};
77+
78+
List<Package>? _packagesWithBuildHook;
79+
List<Package>? _packagesWithLinkHook;
80+
81+
Future<List<Package>> _runPackagesWithHook(Hook hook) async {
82+
final packageNamesInDependencies = packageGraph.vertices.toSet();
83+
final result = <Package>[];
84+
for (final package in packageLayout.packageConfig.packages) {
85+
if (!packageNamesInDependencies.contains(package.name)) {
86+
continue;
87+
}
88+
final packageRoot = package.root;
89+
if (packageRoot.scheme == 'file') {
90+
if (await fileSystem
91+
.file(packageRoot.resolve('hook/').resolve(hook.scriptName))
92+
.exists() ||
93+
await fileSystem
94+
.file(packageRoot.resolve(hook.scriptName))
95+
.exists()) {
96+
result.add(package);
97+
}
98+
}
99+
}
100+
return result;
101+
}
102+
103+
List<Package>? _buildHookPlan;
104+
51105
/// Plans in what order to run build hooks.
52106
///
53-
/// [runPackageName] provides the entry-point in the graph. The hooks of
54-
/// packages not in the transitive dependencies of [runPackageName] will not
55-
/// be run.
56-
List<Package>? plan(String runPackageName) {
57-
final packageGraph = this.packageGraph.subGraph(runPackageName);
107+
/// [PackageLayout.runPackageName] provides the entry-point in the graph. The
108+
/// hooks of packages not in the transitive dependencies of
109+
/// [PackageLayout.runPackageName] will not be run.
110+
Future<List<Package>?> makeBuildHookPlan() async {
111+
if (_buildHookPlan != null) return _buildHookPlan;
112+
final packagesWithNativeAssets = await packagesWithHook(Hook.build);
58113
final packageMap = {
59114
for (final package in packagesWithNativeAssets) package.name: package
60115
};
@@ -77,6 +132,7 @@ class NativeAssetsBuildPlanner {
77132
packageMap[stronglyConnectedComponentWithNativeAssets.single]!);
78133
}
79134
}
135+
_buildHookPlan = result;
80136
return result;
81137
}
82138
}

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

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'dart:io' show Platform;
88

99
import 'package:file/file.dart';
1010
import 'package:logging/logging.dart';
11+
import 'package:meta/meta.dart';
1112
import 'package:native_assets_cli/native_assets_cli_internal.dart';
1213
import 'package:package_config/package_config.dart';
1314

@@ -82,6 +83,16 @@ class NativeAssetsBuildRunner {
8283
hookEnvironment = hookEnvironment ??
8384
filteredEnvironment(hookEnvironmentVariablesFilter);
8485

86+
/// Checks whether any hooks need to be run.
87+
///
88+
/// This method is invoked by launchers such as dartdev (for `dart run`) and
89+
/// flutter_tools (for `flutter run` and `flutter build`).
90+
Future<bool> hasBuildHooks() async {
91+
final planner = await _planner;
92+
final packagesWithHook = await planner.packagesWithHook(Hook.build);
93+
return packagesWithHook.isNotEmpty;
94+
}
95+
8596
/// This method is invoked by launchers such as dartdev (for `dart run`) and
8697
/// flutter_tools (for `flutter run` and `flutter build`).
8798
///
@@ -713,7 +724,7 @@ ${compileResult.stdout}
713724

714725
if (input is BuildInput) {
715726
final packagesWithLink =
716-
(await packageLayout.packagesWithAssets(Hook.link))
727+
(await (await _planner).packagesWithHook(Hook.link))
717728
.map((p) => p.name);
718729
for (final targetPackage
719730
in (output as BuildOutput).assets.encodedAssetsForLinking.keys) {
@@ -731,30 +742,37 @@ ${compileResult.stdout}
731742
return errors;
732743
}
733744

745+
late final _planner = () async {
746+
final planner = await NativeAssetsBuildPlanner.fromPackageConfigUri(
747+
packageConfigUri: packageLayout.packageConfigUri,
748+
dartExecutable: Uri.file(Platform.resolvedExecutable),
749+
logger: logger,
750+
packageLayout: packageLayout,
751+
fileSystem: _fileSystem,
752+
);
753+
return planner;
754+
}();
755+
734756
Future<(List<Package>? plan, PackageGraph? dependencyGraph)> _makePlan({
735757
required Hook hook,
736758
// TODO(dacoharkes): How to share these two? Make them extend each other?
737759
BuildResult? buildResult,
738760
}) async {
739-
final packagesWithHook = await packageLayout.packagesWithAssets(hook);
740761
final List<Package> buildPlan;
741762
final PackageGraph? packageGraph;
742763
switch (hook) {
743764
case Hook.build:
744-
final planner = await NativeAssetsBuildPlanner.fromPackageConfigUri(
745-
packageConfigUri: packageLayout.packageConfigUri,
746-
packagesWithNativeAssets: packagesWithHook,
747-
dartExecutable: Uri.file(Platform.resolvedExecutable),
748-
logger: logger,
749-
);
750-
final plan = planner.plan(packageLayout.runPackageName);
765+
final planner = await _planner;
766+
final plan = await planner.makeBuildHookPlan();
751767
return (plan, planner.packageGraph);
752768
case Hook.link:
753769
// Link hooks are not run in any particular order.
754770
// Link hooks are skipped if no assets for linking are provided.
755771
buildPlan = [];
756772
final skipped = <String>[];
757773
final encodedAssetsForLinking = buildResult!.encodedAssetsForLinking;
774+
final planner = await _planner;
775+
final packagesWithHook = await planner.packagesWithHook(Hook.link);
758776
for (final package in packagesWithHook) {
759777
if (encodedAssetsForLinking[package.name]?.isNotEmpty ?? false) {
760778
buildPlan.add(package);
@@ -802,6 +820,7 @@ ${compileResult.stdout}
802820
/// return path.replaceAll('\\', '\\\\').replaceAll(' ', '\\ ');
803821
/// }
804822
/// ```
823+
@internal
805824
List<String> parseDepFileInputs(String contents) {
806825
final output = contents.substring(0, contents.indexOf(': '));
807826
contents = contents.substring(output.length + ': '.length).trim();
@@ -844,6 +863,7 @@ Future<List<Uri>> _readDepFile(File depFile) async {
844863
return dartSources.map(Uri.file).toList();
845864
}
846865

866+
@internal
847867
Map<String, String> filteredEnvironment(Set<String> allowList) => {
848868
for (final entry in Platform.environment.entries)
849869
if (allowList.contains(entry.key.toUpperCase())) entry.key: entry.value,

pkgs/native_assets_builder/lib/src/package_layout/package_layout.dart

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,25 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:file/file.dart';
6-
import 'package:native_assets_cli/native_assets_cli_internal.dart';
76
import 'package:package_config/package_config.dart';
87

8+
import '../../native_assets_builder.dart';
9+
910
/// Directory layout for dealing with native assets.
1011
///
11-
/// Build hooks for native assets will be run from the context of another root
12-
/// package.
12+
/// For the [NativeAssetsBuildRunner] to correctly run hooks, multiple pieces of
13+
/// information are required:
14+
/// * [packageConfig] to know the list of all packages that may contain hooks.
15+
/// * [packageConfigUri] to be able to get a dependency graph with `pub` and to
16+
/// know where to cache/share asset builds.
17+
/// * [runPackageName] to know which package build hooks to invoke and ignore.
18+
/// Only dependencies of the "run package" are built.
1319
///
14-
/// The directory layout follows pub's convention for caching:
20+
/// The [NativeAssetsBuildRunner] builds assets in
21+
/// `.dart_tool/native_assets_builder`. The directory layout follows pub's
22+
/// convention for caching:
1523
/// https://dart.dev/tools/pub/package-layout#project-specific-caching-for-tools
1624
class PackageLayout {
17-
final FileSystem _fileSystem;
18-
1925
/// Package config containing the information of where to foot the root [Uri]s
2026
/// of other packages.
2127
///
@@ -29,7 +35,6 @@ class PackageLayout {
2935
final String runPackageName;
3036

3137
PackageLayout._(
32-
this._fileSystem,
3338
this.packageConfig,
3439
this.packageConfigUri,
3540
this.runPackageName,
@@ -44,7 +49,6 @@ class PackageLayout {
4449
assert(fileSystem.file(packageConfigUri).existsSync());
4550
packageConfigUri = packageConfigUri.normalizePath();
4651
return PackageLayout._(
47-
fileSystem,
4852
packageConfig,
4953
packageConfigUri,
5054
runPackageName,
@@ -62,7 +66,6 @@ class PackageLayout {
6266
assert(await fileSystem.file(packageConfigUri).exists());
6367
final packageConfig = await loadPackageConfigUri(packageConfigUri!);
6468
return PackageLayout._(
65-
fileSystem,
6669
packageConfig,
6770
packageConfigUri,
6871
runPackgeName,
@@ -121,40 +124,4 @@ class PackageLayout {
121124
}
122125
return package.root;
123126
}
124-
125-
/// All packages in [packageConfig] with native assets.
126-
///
127-
/// Whether a package has native assets is defined by whether it contains
128-
/// a `hook/build.dart` or `hook/link.dart`.
129-
///
130-
/// For backwards compatibility, a toplevel `build.dart` is also supported.
131-
// TODO(https://github.com/dart-lang/native/issues/823): Remove fallback when
132-
// everyone has migrated. (Probably once we stop backwards compatibility of
133-
// the protocol version pre 1.2.0 on some future version.)
134-
Future<List<Package>> packagesWithAssets(Hook hook) async => switch (hook) {
135-
Hook.build => _packagesWithBuildAssets ??=
136-
await _packagesWithHook(hook),
137-
Hook.link => _packagesWithLinkAssets ??= await _packagesWithHook(hook),
138-
};
139-
140-
List<Package>? _packagesWithBuildAssets;
141-
List<Package>? _packagesWithLinkAssets;
142-
143-
Future<List<Package>> _packagesWithHook(Hook hook) async {
144-
final result = <Package>[];
145-
for (final package in packageConfig.packages) {
146-
final packageRoot = package.root;
147-
if (packageRoot.scheme == 'file') {
148-
if (await _fileSystem
149-
.file(packageRoot.resolve('hook/').resolve(hook.scriptName))
150-
.exists() ||
151-
await _fileSystem
152-
.file(packageRoot.resolve(hook.scriptName))
153-
.exists()) {
154-
result.add(package);
155-
}
156-
}
157-
}
158-
return result;
159-
}
160127
}

pkgs/native_assets_builder/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ dependencies:
1515
file: ^7.0.1
1616
graphs: ^2.3.1
1717
logging: ^1.2.0
18+
meta: ^1.16.0
1819
# native_assets_cli: ^0.10.0
1920
native_assets_cli:
2021
path: ../native_assets_cli/

0 commit comments

Comments
 (0)