Skip to content

Commit bc04cab

Browse files
authored
Minimize generated code, load configuration at runtime. (#4215)
1 parent a9aa456 commit bc04cab

26 files changed

+431
-352
lines changed

build_runner/bin/build_runner.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
import 'package:build_runner/src/build_runner.dart';
66

77
Future<void> main(List<String> arguments) =>
8-
BuildRunner(arguments: arguments, builders: null).run();
8+
BuildRunner(arguments: arguments, builderFactories: null).run();

build_runner/lib/build_runner.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'src/build_plan/builder_application.dart';
5+
import 'src/build_plan/builder_factories.dart';
66
import 'src/build_runner.dart' show BuildRunner;
77

88
export 'src/commands/daemon/constants.dart' show assetServerPort;
99

10-
/// Runs `build_runner` with [arguments] and [builders].
10+
/// Runs `build_runner` with [arguments] and [builderFactories].
1111
///
1212
/// The `build_runner` tool generates a script `.dart_tool/build/entrypoint/build.dart` that
13-
/// depends on the configured builders so it can instantiate them to pass the
14-
/// [builders] parameter.
15-
Future<int> run(List<String> arguments, List<BuilderApplication> builders) =>
16-
BuildRunner(arguments: arguments, builders: builders).run();
13+
/// depends on the builders so it can pass in [builderFactories].
14+
Future<int> run(List<String> arguments, BuilderFactories builderFactories) =>
15+
BuildRunner(arguments: arguments, builderFactories: builderFactories).run();

build_runner/lib/src/bootstrap/build_script_generate.dart

Lines changed: 51 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import 'dart:async';
66

7-
import 'package:build/build.dart';
87
import 'package:build_config/build_config.dart';
98
import 'package:code_builder/code_builder.dart';
109
import 'package:dart_style/dart_style.dart';
@@ -18,7 +17,6 @@ import '../constants.dart';
1817
import '../exceptions.dart';
1918
import '../io/reader_writer.dart';
2019
import '../logging/build_log.dart';
21-
import 'builder_ordering.dart';
2220

2321
const scriptLocation = '$entryPointDir/build.dart';
2422
const scriptKernelLocation = '$scriptLocation$scriptKernelSuffix';
@@ -31,19 +29,20 @@ final _lastShortFormatDartVersion = Version(3, 6, 0);
3129

3230
Future<String> generateBuildScript() async {
3331
buildLog.doing('Generating the build script.');
34-
final info = await findBuildScriptOptions();
35-
final builders = info.builderApplications;
32+
final builderFactories = await loadBuilderFactories();
3633
final library = Library(
3734
(b) => b.body.addAll([
38-
declareFinal('_builders')
35+
declareFinal('_builderFactories')
3936
.assign(
40-
literalList(
41-
builders,
42-
refer(
43-
'BuilderApplication',
44-
'package:build_runner/src/build_plan/builder_application.dart',
37+
refer(
38+
'BuilderFactories',
39+
'package:build_runner/src/build_plan/builder_factories.dart',
40+
).call([], {
41+
'builderFactories': literalMap(builderFactories.builderFactories),
42+
'postProcessBuilderFactories': literalMap(
43+
builderFactories.postProcessBuilderFactories,
4544
),
46-
),
45+
}),
4746
)
4847
.statement,
4948
_main(),
@@ -76,7 +75,7 @@ ${library.accept(emitter)}
7675
}
7776
}
7877

79-
Future<BuildScriptInfo> findBuildScriptOptions() async {
78+
Future<BuilderFactoriesExpressions> loadBuilderFactories() async {
8079
final packageGraph = await PackageGraph.forThisPackage();
8180
final orderedPackages = stronglyConnectedComponents<PackageNode>(
8281
[packageGraph.root],
@@ -118,37 +117,42 @@ Future<BuildScriptInfo> findBuildScriptOptions() async {
118117
return import.startsWith('package:') || package == packageGraph.root.name;
119118
}
120119

121-
final orderedConfigs = await Future.wait(
120+
final buildConfigs = await Future.wait(
122121
orderedPackages.map(packageBuildConfig),
123122
);
124-
final builderDefinitions = orderedConfigs
125-
.expand((c) => c.builderDefinitions.values)
126-
.where(isPackageImportOrForRoot);
127-
128-
final rootBuildConfig = orderedConfigs.last;
129-
final orderedBuilders =
130-
findBuilderOrder(
131-
builderDefinitions,
132-
rootBuildConfig.globalOptions,
133-
).toList();
134-
135-
final postProcessBuilderDefinitions = orderedConfigs
136-
.expand((c) => c.postProcessBuilderDefinitions.values)
137-
.where(isPackageImportOrForRoot);
138-
139-
final applications = [
140-
for (final builder in orderedBuilders) _applyBuilder(builder),
141-
for (final builder in postProcessBuilderDefinitions)
142-
_applyPostProcessBuilder(builder),
143-
];
144-
145-
return BuildScriptInfo(applications);
123+
final builderDefinitions =
124+
buildConfigs
125+
.expand((c) => c.builderDefinitions.values)
126+
.where(isPackageImportOrForRoot)
127+
.toList()
128+
..sort((a, b) => a.key.compareTo(b.key));
129+
final postProcessBuilderDefinitions =
130+
buildConfigs
131+
.expand((c) => c.postProcessBuilderDefinitions.values)
132+
.where(isPackageImportOrForRoot)
133+
.toList()
134+
..sort((a, b) => a.key.compareTo(b.key));
135+
136+
return BuilderFactoriesExpressions(
137+
builderFactories: {
138+
for (final builder in builderDefinitions)
139+
builder.key: _builderFactories(builder),
140+
},
141+
postProcessBuilderFactories: {
142+
for (final postProcessBuilder in postProcessBuilderDefinitions)
143+
postProcessBuilder.key: _postProcessBuilderFactory(postProcessBuilder),
144+
},
145+
);
146146
}
147147

148-
class BuildScriptInfo {
149-
final Iterable<Expression> builderApplications;
148+
class BuilderFactoriesExpressions {
149+
final Map<String, Expression> builderFactories;
150+
final Map<String, Expression> postProcessBuilderFactories;
150151

151-
BuildScriptInfo(this.builderApplications);
152+
BuilderFactoriesExpressions({
153+
required this.builderFactories,
154+
required this.postProcessBuilderFactories,
155+
});
152156
}
153157

154158
/// A method forwarding to `run`.
@@ -189,7 +193,7 @@ Method _main() => Method((b) {
189193
refer(
190194
'run',
191195
'package:build_runner/build_runner.dart',
192-
).call([refer('args'), refer('_builders')]).awaited,
196+
).call([refer('args'), refer('_builderFactories')]).awaited,
193197
)
194198
.statement,
195199
refer('exitCode', 'dart:io').assign(isolateExitCode).nullChecked.statement,
@@ -200,88 +204,20 @@ Method _main() => Method((b) {
200204
]);
201205
});
202206

203-
/// An expression calling `apply` with appropriate setup for a Builder.
204-
Expression _applyBuilder(BuilderDefinition definition) {
205-
final namedArgs = {
206-
if (definition.isOptional) 'isOptional': literalTrue,
207-
if (definition.buildTo == BuildTo.cache)
208-
'hideOutput': literalTrue
209-
else
210-
'hideOutput': literalFalse,
211-
if (!identical(definition.defaults.generateFor, InputSet.anything))
212-
'defaultGenerateFor': refer(
213-
'InputSet',
214-
'package:build_config/build_config.dart',
215-
).constInstance([], {
216-
if (definition.defaults.generateFor.include != null)
217-
'include': _rawStringList(definition.defaults.generateFor.include!),
218-
if (definition.defaults.generateFor.exclude != null)
219-
'exclude': _rawStringList(definition.defaults.generateFor.exclude!),
220-
}),
221-
if (definition.defaults.options.isNotEmpty)
222-
'defaultOptions': _constructBuilderOptions(definition.defaults.options),
223-
if (definition.defaults.devOptions.isNotEmpty)
224-
'defaultDevOptions': _constructBuilderOptions(
225-
definition.defaults.devOptions,
226-
),
227-
if (definition.defaults.releaseOptions.isNotEmpty)
228-
'defaultReleaseOptions': _constructBuilderOptions(
229-
definition.defaults.releaseOptions,
230-
),
231-
if (definition.appliesBuilders.isNotEmpty)
232-
'appliesBuilders': _rawStringList(definition.appliesBuilders),
233-
};
207+
/// The `List` of `BuilderFactory` declared in [definition].
208+
Expression _builderFactories(BuilderDefinition definition) {
234209
final import = _buildScriptImport(definition.import);
235-
return refer(
236-
'apply',
237-
'package:build_runner/src/bootstrap/apply_builders.dart',
238-
).call([
239-
literalString(definition.key, raw: true),
240-
literalList([
241-
for (final f in definition.builderFactories) refer(f, import),
242-
]),
243-
_findToExpression(definition),
244-
], namedArgs);
210+
return literalList([
211+
for (final f in definition.builderFactories) refer(f, import),
212+
]);
245213
}
246214

247-
/// An expression calling `applyPostProcess` with appropriate setup for a
248-
/// PostProcessBuilder.
249-
Expression _applyPostProcessBuilder(PostProcessBuilderDefinition definition) {
250-
final namedArgs = {
251-
if (!identical(definition.defaults.generateFor, InputSet.anything))
252-
'defaultGenerateFor': refer(
253-
'InputSet',
254-
'package:build_config/build_config.dart',
255-
).constInstance([], {
256-
if (definition.defaults.generateFor.include != null)
257-
'include': _rawStringList(definition.defaults.generateFor.include!),
258-
if (definition.defaults.generateFor.exclude != null)
259-
'exclude': _rawStringList(definition.defaults.generateFor.exclude!),
260-
}),
261-
if (definition.defaults.options.isNotEmpty)
262-
'defaultOptions': _constructBuilderOptions(definition.defaults.options),
263-
if (definition.defaults.devOptions.isNotEmpty)
264-
'defaultDevOptions': _constructBuilderOptions(
265-
definition.defaults.devOptions,
266-
),
267-
if (definition.defaults.releaseOptions.isNotEmpty)
268-
'defaultReleaseOptions': _constructBuilderOptions(
269-
definition.defaults.releaseOptions,
270-
),
271-
};
215+
/// The `PostProcessBuilderFactory` declared in [definition].
216+
Expression _postProcessBuilderFactory(PostProcessBuilderDefinition definition) {
272217
final import = _buildScriptImport(definition.import);
273-
return refer(
274-
'applyPostProcess',
275-
'package:build_runner/src/bootstrap/apply_builders.dart',
276-
).call([
277-
literalString(definition.key, raw: true),
278-
refer(definition.builderFactory, import),
279-
], namedArgs);
218+
return refer(definition.builderFactory, import);
280219
}
281220

282-
Expression _rawStringList(List<String> strings) =>
283-
literalConstList([for (final s in strings) literalString(s, raw: true)]);
284-
285221
/// Returns the actual import to put in the generated script based on an import
286222
/// found in the build.yaml.
287223
String _buildScriptImport(String import) {
@@ -293,63 +229,3 @@ String _buildScriptImport(String import) {
293229
return p.url.relative(import, from: p.url.dirname(scriptLocation));
294230
}
295231
}
296-
297-
Expression _findToExpression(BuilderDefinition definition) {
298-
switch (definition.autoApply) {
299-
case AutoApply.none:
300-
return refer(
301-
'toNoneByDefault',
302-
'package:build_runner/src/bootstrap/apply_builders.dart',
303-
).call([]);
304-
case AutoApply.dependents:
305-
return refer(
306-
'toDependentsOf',
307-
'package:build_runner/src/bootstrap/apply_builders.dart',
308-
).call([literalString(definition.package, raw: true)]);
309-
case AutoApply.allPackages:
310-
return refer(
311-
'toAllPackages',
312-
'package:build_runner/src/bootstrap/apply_builders.dart',
313-
).call([]);
314-
case AutoApply.rootPackage:
315-
return refer(
316-
'toRoot',
317-
'package:build_runner/src/bootstrap/apply_builders.dart',
318-
).call([]);
319-
}
320-
}
321-
322-
/// An expression creating a [BuilderOptions] from a json string.
323-
Expression _constructBuilderOptions(Map<String, dynamic> options) => refer(
324-
'BuilderOptions',
325-
'package:build/build.dart',
326-
).constInstance([options.toExpression()]);
327-
328-
/// Converts a Dart object to a source code representation.
329-
///
330-
/// This is similar to [literal] from `package:code_builder`, except that it
331-
/// always writes raw string literals.
332-
extension ConvertToExpression on Object? {
333-
Expression toExpression() {
334-
final $this = this;
335-
336-
if ($this is Map) {
337-
return literalMap(
338-
{
339-
for (final entry in $this.cast<Object?, Object?>().entries)
340-
entry.key.toExpression(): entry.value.toExpression(),
341-
},
342-
refer('String'),
343-
refer('dynamic'),
344-
);
345-
} else if ($this is List) {
346-
return literalList([
347-
for (final entry in $this.cast<Object?>()) entry.toExpression(),
348-
], refer('dynamic'));
349-
} else if ($this is String) {
350-
return literalString($this, raw: true);
351-
} else {
352-
return literal(this);
353-
}
354-
}
355-
}

build_runner/lib/src/bootstrap/apply_builders.dart renamed to build_runner/lib/src/build_plan/apply_builders.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
import 'package:build/build.dart';
66
import 'package:build_config/build_config.dart';
77

8-
import '../build_plan/builder_application.dart';
9-
import '../build_plan/package_graph.dart';
10-
import '../build_plan/phase.dart';
118
import '../exceptions.dart';
129
import '../logging/build_log.dart';
1310
import '../logging/build_log_logger.dart';
11+
import 'builder_application.dart';
12+
import 'package_graph.dart';
13+
import 'phase.dart';
1414

1515
/// Run a builder on all packages in the package graph.
1616
PackageFilter toAllPackages() => (_) => true;
@@ -70,7 +70,7 @@ BuilderApplication applyToRoot(
7070
/// because it matches [filter] or because it was enabled manually.
7171
BuilderApplication apply(
7272
String builderKey,
73-
List<BuilderFactory> builderFactories,
73+
Iterable<BuilderFactory> builderFactories,
7474
PackageFilter filter, {
7575
bool isOptional = false,
7676
bool hideOutput = true,
@@ -115,7 +115,7 @@ BuilderApplication applyPostProcess(
115115

116116
BuilderApplication _forBuilder(
117117
String builderKey,
118-
List<BuilderFactory> builderFactories,
118+
Iterable<BuilderFactory> builderFactories,
119119
PackageFilter filter, {
120120
bool isOptional = false,
121121
bool hideOutput = true,

0 commit comments

Comments
 (0)