Skip to content
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
55 changes: 24 additions & 31 deletions _test_common/lib/test_phases.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import 'dart:async';
import 'dart:convert';

import 'package:build/build.dart';
// ignore: implementation_imports
import 'package:build_runner/src/internal.dart';
import 'package:build_runner_core/build_runner_core.dart';
import 'package:build_test/build_test.dart';
// ignore: implementation_imports
Expand Down Expand Up @@ -81,13 +83,11 @@ Future<TestBuildersResult> testPhases(
// A better way to "silence" logging than setting logLevel to OFF.
void Function(LogRecord record) onLog = _printOnFailure,
bool checkBuildStatus = true,
bool deleteFilesByDefault = true,
bool enableLowResourcesMode = false,
bool verbose = false,
Set<BuildDirectory> buildDirs = const {},
Set<BuildFilter> buildFilters = const {},
String? logPerformanceDir,
String expectedGeneratedDir = 'generated',
void Function(AssetId id)? onDelete,
}) async {
packageGraph ??= buildPackageGraph({rootPackage('a'): []});
Expand Down Expand Up @@ -132,38 +132,33 @@ Future<TestBuildersResult> testPhases(
}
});

var environment = BuildEnvironment(
packageGraph,
reader: readerWriter,
writer: readerWriter,
);

buildLog.configuration = buildLog.configuration.rebuild((b) {
b.onLog = onLog;
b.verbose = verbose;
});

var options = await BuildConfiguration.create(
packageGraph: packageGraph,
reader: environment.reader,
skipBuildScriptCheck: true,
enableLowResourcesMode: enableLowResourcesMode,
logPerformanceDir: logPerformanceDir,
final buildPlan = await BuildPlan.load(
builders: builders.build(),
// ignore: invalid_use_of_visible_for_testing_member
buildOptions: BuildOptions.forTests(
buildDirs: buildDirs.build(),
buildFilters: buildFilters.build(),
enableLowResourcesMode: enableLowResourcesMode,
logPerformanceDir: logPerformanceDir,
skipBuildScriptCheck: true,
trackPerformance: logPerformanceDir != null,
verbose: verbose,
),
testingOverrides: TestingOverrides(
packageGraph: packageGraph,
reader: readerWriter,
writer: readerWriter,
),
);

BuildResult result;
var build = await BuildRunner.create(
options,
environment,
builders.build(),
BuiltMap(),
isReleaseBuild: false,
);
result = await build.run(
{},
buildDirs: buildDirs.build(),
buildFilters: buildFilters.build(),
);
final build = await BuildSeries.create(buildPlan: buildPlan);
result = await build.run({});
await build.beforeExit();

if (checkBuildStatus) {
Expand All @@ -173,7 +168,6 @@ Future<TestBuildersResult> testPhases(
readerWriter: readerWriter,
status: status,
rootPackage: packageGraph.root.name,
expectedGeneratedDir: expectedGeneratedDir,
);
}

Expand All @@ -188,7 +182,6 @@ void checkBuild(
required TestReaderWriter readerWriter,
BuildStatus status = BuildStatus.success,
String rootPackage = 'a',
String expectedGeneratedDir = 'generated',
}) {
expect(result.status, status, reason: '$result');

Expand All @@ -204,11 +197,11 @@ void checkBuild(
}
}

AssetId mapHidden(AssetId id, String expectedGeneratedDir) =>
AssetId mapHidden(AssetId id) =>
unhiddenAssets.contains(id)
? AssetId(
rootPackage,
'.dart_tool/build/$expectedGeneratedDir/${id.package}/${id.path}',
'.dart_tool/build/generated/${id.package}/${id.path}',
)
: id;

Expand All @@ -217,7 +210,7 @@ void checkBuild(
unhiddenOutputs,
result.outputs,
readerWriter,
mapAssetIds: (id) => mapHidden(id, expectedGeneratedDir),
mapAssetIds: mapHidden,
);
}
}
Expand Down
1 change: 1 addition & 0 deletions _test_common/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ environment:
dependencies:
build: any
build_config: any
build_runner: any
build_runner_core: any
build_test: any
built_collection: any
Expand Down
104 changes: 104 additions & 0 deletions build_runner/lib/src/build_plan.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:build/build.dart';
import 'package:build_runner_core/build_runner_core.dart';
import 'package:built_collection/built_collection.dart';

import 'commands/build_filter.dart';
import 'commands/build_options.dart';

/// Options and derived configuration for a build.
class BuildPlan {
final BuiltList<BuilderApplication> builders;
final BuildOptions buildOptions;
final TestingOverrides testingOverrides;

final PackageGraph packageGraph;
final AssetReader reader;
final RunnerAssetWriter writer;
final TargetGraph targetGraph;
final BuildPhases buildPhases;

BuildPlan({
required this.builders,
required this.buildOptions,
required this.testingOverrides,
required this.packageGraph,
required this.reader,
required this.writer,
required this.targetGraph,
required this.buildPhases,
});

/// Loads a build plan.
///
/// Loads the package strucure and build configuration; prepares [reader]
/// and [writer] and deduces the [buildPhases] that will run.
static Future<BuildPlan> load({
required BuiltList<BuilderApplication> builders,
required BuildOptions buildOptions,
required TestingOverrides testingOverrides,
}) async {
final packageGraph =
testingOverrides.packageGraph ?? await PackageGraph.forThisPackage();

var reader = testingOverrides.reader;
var writer = testingOverrides.writer;

if (reader == null || writer == null) {
final readerWriter = ReaderWriter(packageGraph);
reader ??= readerWriter;
writer ??= readerWriter;
}

final targetGraph = await TargetGraph.forPackageGraph(
reader: reader,
packageGraph: packageGraph,
testingOverrides: testingOverrides,
configKey: buildOptions.configKey,
);

final buildPhases = await createBuildPhases(
targetGraph,
builders,
buildOptions.builderConfigOverrides,
buildOptions.isReleaseBuild,
);
if (buildPhases.inBuildPhases.isEmpty &&
buildPhases.postBuildPhase.builderActions.isEmpty) {
buildLog.warning('Nothing to build.');
}

return BuildPlan(
builders: builders,
buildOptions: buildOptions,
testingOverrides: testingOverrides,
packageGraph: packageGraph,
reader: reader,
writer: writer,
targetGraph: targetGraph,
buildPhases: buildPhases,
);
}

BuildPlan copyWith({
BuiltSet<BuildDirectory>? buildDirs,
BuiltSet<BuildFilter>? buildFilters,
AssetReader? reader,
RunnerAssetWriter? writer,
}) => BuildPlan(
builders: builders,
buildOptions: buildOptions.copyWith(
buildDirs: buildDirs,
buildFilters: buildFilters,
),
testingOverrides: testingOverrides,
packageGraph: packageGraph,
targetGraph: targetGraph,
reader: reader ?? this.reader,
writer: writer ?? this.writer,
buildPhases: buildPhases,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import 'package:graphs/graphs.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';

import '../package_graph/build_config_overrides.dart';
import 'builder_ordering.dart';

const scriptLocation = '$entryPointDir/build.dart';
Expand Down Expand Up @@ -81,7 +80,11 @@ Future<BuildScriptInfo> findBuildScriptOptions() async {
hashCode: (n) => n.name.hashCode,
).expand((c) => c);
var reader = ReaderWriter(packageGraph);
var overrides = await findBuildConfigOverrides(packageGraph, reader);
var overrides = await findBuildConfigOverrides(
packageGraph: packageGraph,
reader: reader,
configKey: null,
);
Future<BuildConfig> packageBuildConfig(PackageNode package) async {
if (overrides.containsKey(package.name)) {
return overrides[package.name]!;
Expand Down
44 changes: 8 additions & 36 deletions build_runner/lib/src/commands/build_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import 'package:build_runner_core/build_runner_core.dart';
import 'package:built_collection/built_collection.dart';
import 'package:io/io.dart';

import '../build_plan.dart';
import '../build_script_generate/build_process_state.dart';
import '../package_graph/build_config_overrides.dart';
import 'build_options.dart';
import 'build_runner_command.dart';

Expand Down Expand Up @@ -42,42 +42,14 @@ class BuildCommand implements BuildRunnerCommand {
b.verbose = buildOptions.verbose;
b.onLog = testingOverrides.onLog;
});
final packageGraph =
testingOverrides.packageGraph ?? await PackageGraph.forThisPackage();
var environment = BuildEnvironment(
packageGraph,
outputSymlinksOnly: buildOptions.outputSymlinksOnly,
reader: testingOverrides.reader,
writer: testingOverrides.writer,
);
var options = await BuildConfiguration.create(
packageGraph: packageGraph,
reader: environment.reader,
skipBuildScriptCheck: buildOptions.skipBuildScriptCheck,
overrideBuildConfig:
testingOverrides.buildConfig ??
await findBuildConfigOverrides(
packageGraph,
environment.reader,
configKey: buildOptions.configKey,
),
enableLowResourcesMode: buildOptions.enableLowResourcesMode,
trackPerformance: buildOptions.trackPerformance,
logPerformanceDir: buildOptions.logPerformanceDir,
resolvers: testingOverrides.resolvers,
);
var build = await BuildRunner.create(
options,
environment,
builders,
buildOptions.builderConfigOverrides,
isReleaseBuild: buildOptions.isReleaseBuild,
);
var result = await build.run(
{},
buildDirs: buildOptions.buildDirs,
buildFilters: buildOptions.buildFilters,

final buildPlan = await BuildPlan.load(
builders: builders,
buildOptions: buildOptions,
testingOverrides: testingOverrides,
);
final build = await BuildSeries.create(buildPlan: buildPlan);
final result = await build.run({});
await build.beforeExit();
return result;
}
Expand Down
61 changes: 61 additions & 0 deletions build_runner/lib/src/commands/build_filter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:build/build.dart';
import 'package:glob/glob.dart';
import 'package:path/path.dart' as p;

/// Describes a set of files that should be built.
class BuildFilter {
/// The package name glob that files must live under in order to match.
final Glob _package;

/// A glob for files under [_package] that must match.
final Glob _path;

BuildFilter(this._package, this._path);

/// Builds a [BuildFilter] from a command line argument.
///
/// Both relative paths and package: uris are supported. Relative
/// paths are treated as relative to the [rootPackage].
///
/// Globs are supported in package names and paths.
factory BuildFilter.fromArg(String arg, String rootPackage) {
var uri = Uri.parse(arg);
if (uri.scheme == 'package') {
var package = uri.pathSegments.first;
var glob = Glob(p.url.joinAll(['lib', ...uri.pathSegments.skip(1)]));
return BuildFilter(Glob(package), glob);
} else if (uri.scheme.isEmpty) {
return BuildFilter(Glob(rootPackage), Glob(uri.path));
} else {
throw FormatException('Unsupported scheme ${uri.scheme}', uri);
}
}

/// Returns whether or not [id] mathes this filter.
bool matches(AssetId id) =>
_package.matches(id.package) && _path.matches(id.path);

@override
int get hashCode => Object.hash(
_package.context,
_package.pattern,
_package.recursive,
_path.context,
_path.pattern,
_path.recursive,
);

@override
bool operator ==(Object other) =>
other is BuildFilter &&
other._path.context == _path.context &&
other._path.pattern == _path.pattern &&
other._path.recursive == _path.recursive &&
other._package.context == _package.context &&
other._package.pattern == _package.pattern &&
other._package.recursive == _package.recursive;
}
Loading
Loading