Skip to content
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

[native_assets_builder] Support pub workspaces #1911

Merged
merged 3 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions pkgs/native_assets_builder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## 0.11.0-wip

- **Breaking change** `runPackageName` is now required to properly support
pub workspaces.
- Bump `package:native_assets_cli` to 0.11.0.

## 0.10.2
Expand Down
36 changes: 24 additions & 12 deletions pkgs/native_assets_builder/lib/src/build_runner/build_planner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class NativeAssetsBuildPlanner {
required this.logger,
});

static Future<NativeAssetsBuildPlanner> fromRootPackageRoot({
required Uri rootPackageRoot,
static Future<NativeAssetsBuildPlanner> fromWorkingDirectory({
required Uri workingDirectory,
required List<Package> packagesWithNativeAssets,
required Uri dartExecutable,
required Logger logger,
Expand All @@ -35,7 +35,7 @@ class NativeAssetsBuildPlanner {
'deps',
'--json',
],
workingDirectory: rootPackageRoot.toFilePath(),
workingDirectory: workingDirectory.toFilePath(),
);
final packageGraph =
PackageGraph.fromPubDepsJsonString(result.stdout as String);
Expand All @@ -47,15 +47,13 @@ class NativeAssetsBuildPlanner {
);
}

List<Package>? plan({
String? runPackageName,
}) {
final PackageGraph packageGraph;
if (runPackageName != null) {
packageGraph = this.packageGraph.subGraph(runPackageName);
} else {
packageGraph = this.packageGraph;
}
/// Plans in what order to run build hooks.
///
/// [runPackageName] provides the entry-point in the graph. The hooks of
/// packages not in the transitive dependencies of [runPackageName] will not
/// be run.
List<Package>? plan(String runPackageName) {
final packageGraph = this.packageGraph.subGraph(runPackageName);
final packageMap = {
for (final package in packagesWithNativeAssets) package.name: package
};
Expand Down Expand Up @@ -136,4 +134,18 @@ class PackageGraph {
]
});
}

@override
String toString() {
final buffer = StringBuffer();
buffer.writeln('PackageGraph(');
for (final node in vertices) {
buffer.writeln(' $node ->');
for (final neighbor in neighborsOf(node)) {
buffer.writeln(' $neighbor');
}
}
buffer.writeln(')');
return buffer.toString();
}
}
36 changes: 13 additions & 23 deletions pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ class NativeAssetsBuildRunner {
required ApplicationAssetValidator applicationAssetValidator,
required Uri workingDirectory,
PackageLayout? packageLayout,
String? runPackageName,
required String runPackageName,
required List<String> buildAssetTypes,
required bool linkingEnabled,
}) async {
packageLayout ??=
await PackageLayout.fromRootPackageRoot(_fileSystem, workingDirectory);
await PackageLayout.fromWorkingDirectory(_fileSystem, workingDirectory);

final (buildPlan, packageGraph) = await _makePlan(
hook: Hook.build,
Expand Down Expand Up @@ -208,12 +208,12 @@ class NativeAssetsBuildRunner {
required ApplicationAssetValidator applicationAssetValidator,
PackageLayout? packageLayout,
Uri? resourceIdentifiers,
String? runPackageName,
required String runPackageName,
required List<String> buildAssetTypes,
required BuildResult buildResult,
}) async {
packageLayout ??=
await PackageLayout.fromRootPackageRoot(_fileSystem, workingDirectory);
await PackageLayout.fromWorkingDirectory(_fileSystem, workingDirectory);

final (buildPlan, packageGraph) = await _makePlan(
hook: Hook.link,
Expand Down Expand Up @@ -775,7 +775,7 @@ ${compileResult.stdout}

Future<(List<Package>? plan, PackageGraph? dependencyGraph)> _makePlan({
required PackageLayout packageLayout,
String? runPackageName,
required String runPackageName,
required Hook hook,
// TODO(dacoharkes): How to share these two? Make them extend each other?
BuildResult? buildResult,
Expand All @@ -785,24 +785,14 @@ ${compileResult.stdout}
final PackageGraph? packageGraph;
switch (hook) {
case Hook.build:
// Build hooks are run in toplogical order.
if (packagesWithHook.length <= 1 && runPackageName == null) {
final dependencyGraph = PackageGraph({
for (final p in packagesWithHook) p.name: [],
});
return (packagesWithHook, dependencyGraph);
} else {
final planner = await NativeAssetsBuildPlanner.fromRootPackageRoot(
rootPackageRoot: packageLayout.rootPackageRoot,
packagesWithNativeAssets: packagesWithHook,
dartExecutable: Uri.file(Platform.resolvedExecutable),
logger: logger,
);
final plan = planner.plan(
runPackageName: runPackageName,
);
return (plan, planner.packageGraph);
}
final planner = await NativeAssetsBuildPlanner.fromWorkingDirectory(
workingDirectory: packageLayout.packageConfigUri.resolve('../'),
packagesWithNativeAssets: packagesWithHook,
dartExecutable: Uri.file(Platform.resolvedExecutable),
logger: logger,
);
final plan = planner.plan(runPackageName);
return (plan, planner.packageGraph);
case Hook.link:
// Link hooks are not run in any particular order.
// Link hooks are skipped if no assets for linking are provided.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ import 'package:package_config/package_config.dart';
class PackageLayout {
final FileSystem _fileSystem;

/// The root folder of the current dart invocation root package.
///
/// `$rootPackageRoot`.
final Uri rootPackageRoot;

/// Package config containing the information of where to foot the root [Uri]s
/// of other packages.
///
Expand All @@ -30,8 +25,11 @@ class PackageLayout {

final Uri packageConfigUri;

PackageLayout._(this._fileSystem, this.rootPackageRoot, this.packageConfig,
this.packageConfigUri);
PackageLayout._(
this._fileSystem,
this.packageConfig,
this.packageConfigUri,
);

factory PackageLayout.fromPackageConfig(
FileSystem fileSystem,
Expand All @@ -40,36 +38,53 @@ class PackageLayout {
) {
assert(fileSystem.file(packageConfigUri).existsSync());
packageConfigUri = packageConfigUri.normalizePath();
final rootPackageRoot = packageConfigUri.resolve('../');
return PackageLayout._(
fileSystem,
rootPackageRoot,
packageConfig,
packageConfigUri,
);
}

static Future<PackageLayout> fromRootPackageRoot(
static Future<PackageLayout> fromWorkingDirectory(
FileSystem fileSystem,
Uri workingDirectory,
) async {
workingDirectory = workingDirectory.normalizePath();
final packageConfigUri =
await findPackageConfig(fileSystem, workingDirectory);
assert(await fileSystem.file(packageConfigUri).exists());
final packageConfig = await loadPackageConfigUri(packageConfigUri!);
return PackageLayout._(fileSystem, packageConfig, packageConfigUri);
}

static Future<Uri?> findPackageConfig(
FileSystem fileSystem,
Uri rootPackageRoot,
) async {
rootPackageRoot = rootPackageRoot.normalizePath();
final packageConfigUri =
rootPackageRoot.resolve('.dart_tool/package_config.json');
assert(await fileSystem.file(packageConfigUri).exists());
final packageConfig = await loadPackageConfigUri(packageConfigUri);
return PackageLayout._(
fileSystem, rootPackageRoot, packageConfig, packageConfigUri);
final file = fileSystem.file(packageConfigUri);
if (await file.exists()) {
return file.uri;
}
final parentUri = rootPackageRoot.resolve('../');
if (parentUri == rootPackageRoot) {
return null;
}
return findPackageConfig(fileSystem, parentUri);
}

/// The .dart_tool directory is used to store built artifacts and caches.
///
/// `$rootPackageRoot/.dart_tool/`.
/// This is the `.dart_tool/` directory where the package config is.
///
/// When pub workspaces are used, the hook results are shared across all
/// packages in the workspace.
///
/// Each package should only modify the subfolder of `.dart_tool/` with its
/// own name.
/// https://dart.dev/tools/pub/package-layout#project-specific-caching-for-tools
late final Uri dartTool = rootPackageRoot.resolve('.dart_tool/');
late final Uri dartTool = packageConfigUri.resolve('./');

/// The directory where `package:native_assets_builder` stores all persistent
/// information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void main() async {

final graph = PackageGraph.fromPubDepsJsonString(result.stdout);

final packageLayout = await PackageLayout.fromRootPackageRoot(
final packageLayout = await PackageLayout.fromWorkingDirectory(
const LocalFileSystem(), nativeAddUri);
final packagesWithNativeAssets =
await packageLayout.packagesWithAssets(Hook.build);
Expand All @@ -46,7 +46,7 @@ void main() async {
dartExecutable: Uri.file(Platform.resolvedExecutable),
logger: logger,
);
final buildPlan = planner.plan();
final buildPlan = planner.plan('native_add');
expect(buildPlan!.length, 1);
expect(buildPlan.single.name, 'native_add');
});
Expand All @@ -60,18 +60,18 @@ void main() async {
// First, run `pub get`, we need pub to resolve our dependencies.
await runPubGet(workingDirectory: nativeAddUri, logger: logger);

final packageLayout = await PackageLayout.fromRootPackageRoot(
final packageLayout = await PackageLayout.fromWorkingDirectory(
const LocalFileSystem(), nativeAddUri);
final packagesWithNativeAssets =
await packageLayout.packagesWithAssets(Hook.build);
final nativeAssetsBuildPlanner =
await NativeAssetsBuildPlanner.fromRootPackageRoot(
rootPackageRoot: nativeAddUri,
await NativeAssetsBuildPlanner.fromWorkingDirectory(
workingDirectory: nativeAddUri,
packagesWithNativeAssets: packagesWithNativeAssets,
dartExecutable: Uri.file(Platform.resolvedExecutable),
logger: logger,
);
final buildPlan = nativeAssetsBuildPlanner.plan();
final buildPlan = nativeAssetsBuildPlanner.plan('native_add');
expect(buildPlan!.length, 1);
expect(buildPlan.single.name, 'native_add');
});
Expand All @@ -87,20 +87,18 @@ void main() async {
// First, run `pub get`, we need pub to resolve our dependencies.
await runPubGet(workingDirectory: nativeAddUri, logger: logger);

final packageLayout = await PackageLayout.fromRootPackageRoot(
final packageLayout = await PackageLayout.fromWorkingDirectory(
const LocalFileSystem(), nativeAddUri);
final packagesWithNativeAssets =
await packageLayout.packagesWithAssets(Hook.build);
final nativeAssetsBuildPlanner =
await NativeAssetsBuildPlanner.fromRootPackageRoot(
rootPackageRoot: nativeAddUri,
await NativeAssetsBuildPlanner.fromWorkingDirectory(
workingDirectory: nativeAddUri,
packagesWithNativeAssets: packagesWithNativeAssets,
dartExecutable: Uri.file(Platform.resolvedExecutable),
logger: logger,
);
final buildPlan = nativeAssetsBuildPlanner.plan(
runPackageName: runPackageName,
);
final buildPlan = nativeAssetsBuildPlanner.plan(runPackageName);
expect(buildPlan!.length, 0);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ void main() async {
test('multiple build invocations', timeout: longTimeout, () async {
await inTempDir((tempUri) async {
await copyTestProjects(targetUri: tempUri);
final packageUri = tempUri.resolve('package_reading_metadata/');
const packageName = 'package_reading_metadata';
final packageUri = tempUri.resolve('$packageName/');

// First, run `pub get`, we need pub to resolve our dependencies.
await runPubGet(
Expand Down Expand Up @@ -49,6 +50,7 @@ void main() async {
inputValidator: (input) async => [],
buildValidator: (input, output) async => [],
applicationAssetValidator: (_) async => [],
runPackageName: packageName,
);
await buildRunner.build(
inputCreator: inputCreator,
Expand All @@ -58,6 +60,7 @@ void main() async {
inputValidator: (input) async => [],
buildValidator: (input, output) async => [],
applicationAssetValidator: (_) async => [],
runPackageName: packageName,
);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void main() async {
for (final passPackageLayout in [true, false]) {
PackageLayout? packageLayout;
if (passPackageLayout) {
packageLayout = await PackageLayout.fromRootPackageRoot(
packageLayout = await PackageLayout.fromWorkingDirectory(
const LocalFileSystem(), packageUri);
}
final logMessages = <String>[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import '../helpers.dart';
// Is invoked concurrently multiple times in separate processes.
void main(List<String> args) async {
final packageUri = Uri.directory(args[0]);
final packageName = packageUri.pathSegments.lastWhere((e) => e.isNotEmpty);
final target = Target.fromString(args[1]);

final logger = Logger('')
Expand Down Expand Up @@ -49,6 +50,7 @@ void main(List<String> args) async {
...await validateCodeAssetBuildOutput(input, output),
],
applicationAssetValidator: validateCodeAssetInApplication,
runPackageName: packageName,
);
if (result == null) {
throw Error();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'helpers.dart';
// Is invoked concurrently multiple times in separate processes.
void main(List<String> args) async {
final packageUri = Uri.directory(args[0]);
final packageName = packageUri.pathSegments.lastWhere((e) => e.isNotEmpty);
Duration? timeout;
if (args.length >= 2) {
timeout = Duration(milliseconds: int.parse(args[1]));
Expand Down Expand Up @@ -50,6 +51,7 @@ void main(List<String> args) async {
...await validateDataAssetBuildOutput(input, output),
],
applicationAssetValidator: validateCodeAssetInApplication,
runPackageName: packageName,
);
if (result == null) {
throw Error();
Expand Down
Loading
Loading