Skip to content

Commit 31043da

Browse files
authored
Add script to run dart run build_runner build using deps from pub. (#3917)
* Add script to run `dart run build_runner build` using deps from pub. * Address review comments. * Address review comments. * Update the year in the correct copyright header. * Address review comments.
1 parent 4eb39e4 commit 31043da

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

tool/build_runner_build.dart

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:convert';
6+
import 'dart:io';
7+
8+
/// Runs `dart run build_runner build` using `build` packages from pub instead
9+
/// of the local versions. This allows the build to run even when the local
10+
/// versions are in a broken state.
11+
///
12+
/// Usage: in one of the `build` repo packages, instead of running
13+
/// `dart run build_runner build`, run `dart ../tool/build_runner_build.dart`.
14+
void main() {
15+
final pathSegments = Directory.current.uri.pathSegments;
16+
if (pathSegments[pathSegments.length - 3] != 'build') {
17+
print('Current directly should be a package inside the build repo.');
18+
exit(1);
19+
}
20+
21+
// Run `pub get` in a temp folder to get paths for published versions of
22+
// `build` packages that won't break due to local changes.
23+
final tempDirectory = Directory.systemTemp.createTempSync(
24+
'build_runner_build',
25+
);
26+
tempDirectory.createSync(recursive: true);
27+
File.fromUri(tempDirectory.uri.resolve('pubspec.yaml')).writeAsStringSync('''
28+
name: none
29+
environment:
30+
sdk: ^3.7.0
31+
dependencies:
32+
build_runner: '2.4.15'
33+
build_test: any
34+
''');
35+
Process.runSync('dart', ['pub', 'get'], workingDirectory: tempDirectory.path);
36+
final pubConfig = PackageConfig(
37+
json.decode(
38+
File.fromUri(
39+
tempDirectory.uri.resolve('.dart_tool/package_config.json'),
40+
).readAsStringSync(),
41+
)
42+
as Map<String, Object?>,
43+
);
44+
45+
// Merge `pubConfig` into the local package config.
46+
//
47+
// `build_runner` expects to run with the local package config because it
48+
// creates a build script that depends on whatever generators the local
49+
// package uses.
50+
//
51+
// So the merged config will have the two things needed: `build` packages
52+
// not broken by local changes, and whatever generators are needed.
53+
var mergedConfig = PackageConfig(
54+
json.decode(
55+
File.fromUri(
56+
Directory.current.uri.resolve('../.dart_tool/package_config.json'),
57+
).readAsStringSync(),
58+
)
59+
as Map<String, Object?>,
60+
);
61+
62+
late String buildRunnerPath;
63+
for (final package in [
64+
'build',
65+
'build_config',
66+
'build_daemon',
67+
'build_resolvers',
68+
'build_runner',
69+
'build_runner_core',
70+
'build_test',
71+
]) {
72+
final packageConfig = pubConfig.packageNamed(package);
73+
mergedConfig.packageNamed(package).rootUri = packageConfig.rootUri;
74+
if (package == 'build_runner') {
75+
buildRunnerPath = packageConfig.rootUri;
76+
}
77+
}
78+
final mergedConfigFile = File.fromUri(
79+
tempDirectory.uri.resolve('package_config.json'),
80+
);
81+
mergedConfigFile.writeAsStringSync(json.encode(mergedConfig));
82+
83+
final buildResult = Process.runSync('dart', [
84+
'--packages=${mergedConfigFile.path}',
85+
'run',
86+
'$buildRunnerPath/bin/build_runner.dart',
87+
'build',
88+
'-d',
89+
], workingDirectory: Directory.current.path);
90+
91+
stdout.write(buildResult.stdout);
92+
stderr.write(buildResult.stderr);
93+
94+
if (buildResult.exitCode == 0) {
95+
tempDirectory.deleteSync(recursive: true);
96+
}
97+
exit(buildResult.exitCode);
98+
}
99+
100+
extension type PackageConfig(Map<String, Object?> node) {
101+
List<Package> get packages =>
102+
(node['packages'] as List<Object?>)
103+
.map((p) => Package(p as Map<String, Object?>))
104+
.toList();
105+
Package packageNamed(String name) =>
106+
packages.singleWhere((package) => package.name == name);
107+
}
108+
109+
extension type Package(Map<String, Object?> node) {
110+
String get name => node['name'] as String;
111+
String get rootUri => node['rootUri'] as String;
112+
set rootUri(String rootUri) => node['rootUri'] = rootUri;
113+
}

0 commit comments

Comments
 (0)