Skip to content

Commit 72343ee

Browse files
[flutter_tools] refactor build_system and targets to be context-free (flutter#53268)
1 parent 4605b51 commit 72343ee

21 files changed

+474
-276
lines changed

packages/flutter_tools/lib/src/aot.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,11 @@ class AotBuilder {
9595
kExtraFrontEndOptions: buildInfo.extraFrontEndOptions.join(','),
9696
if (platform == TargetPlatform.ios)
9797
kIosArchs: iosBuildArchs.map(getNameForDarwinArch).join(' ')
98-
}
98+
},
99+
artifacts: globals.artifacts,
100+
fileSystem: globals.fs,
101+
logger: globals.logger,
102+
processManager: globals.processManager,
99103
);
100104
final BuildResult result = await globals.buildSystem.build(target, environment);
101105
status?.stop();

packages/flutter_tools/lib/src/base/logger.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ class BufferLogger extends Logger {
382382
_timeoutConfiguration = timeoutConfiguration,
383383
_stopwatchFactory = stopwatchFactory;
384384

385-
@visibleForTesting
385+
/// Create a [BufferLogger] with test preferences.
386386
BufferLogger.test({
387387
Terminal terminal,
388388
OutputPreferences outputPreferences,

packages/flutter_tools/lib/src/build_system/build_system.dart

Lines changed: 74 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ import 'package:async/async.dart';
88
import 'package:convert/convert.dart';
99
import 'package:crypto/crypto.dart';
1010
import 'package:meta/meta.dart';
11+
import 'package:platform/platform.dart';
1112
import 'package:pool/pool.dart';
13+
import 'package:process/process.dart';
1214

15+
import '../artifacts.dart';
1316
import '../base/file_system.dart';
17+
import '../base/logger.dart';
1418
import '../base/utils.dart';
1519
import '../cache.dart';
1620
import '../convert.dart';
17-
import '../globals.dart' as globals;
1821
import 'exceptions.dart';
1922
import 'file_hash_store.dart';
2023
import 'source.dart';
@@ -286,6 +289,10 @@ class Environment {
286289
@required Directory outputDir,
287290
@required Directory cacheDir,
288291
@required Directory flutterRootDir,
292+
@required FileSystem fileSystem,
293+
@required Logger logger,
294+
@required Artifacts artifacts,
295+
@required ProcessManager processManager,
289296
Directory buildDir,
290297
Map<String, String> defines = const <String, String>{},
291298
}) {
@@ -314,6 +321,10 @@ class Environment {
314321
cacheDir: cacheDir,
315322
defines: defines,
316323
flutterRootDir: flutterRootDir,
324+
fileSystem: fileSystem,
325+
logger: logger,
326+
artifacts: artifacts,
327+
processManager: processManager,
317328
);
318329
}
319330

@@ -327,6 +338,10 @@ class Environment {
327338
Directory flutterRootDir,
328339
Directory buildDir,
329340
Map<String, String> defines = const <String, String>{},
341+
@required FileSystem fileSystem,
342+
@required Logger logger,
343+
@required Artifacts artifacts,
344+
@required ProcessManager processManager,
330345
}) {
331346
return Environment(
332347
projectDir: projectDir ?? testDirectory,
@@ -335,6 +350,10 @@ class Environment {
335350
flutterRootDir: flutterRootDir ?? testDirectory,
336351
buildDir: buildDir,
337352
defines: defines,
353+
fileSystem: fileSystem,
354+
logger: logger,
355+
artifacts: artifacts,
356+
processManager: processManager,
338357
);
339358
}
340359

@@ -346,6 +365,10 @@ class Environment {
346365
@required this.cacheDir,
347366
@required this.defines,
348367
@required this.flutterRootDir,
368+
@required this.processManager,
369+
@required this.logger,
370+
@required this.fileSystem,
371+
@required this.artifacts,
349372
});
350373

351374
/// The [Source] value which is substituted with the path to [projectDir].
@@ -399,6 +422,14 @@ class Environment {
399422

400423
/// The root build directory shared by all builds.
401424
final Directory rootBuildDir;
425+
426+
final ProcessManager processManager;
427+
428+
final Logger logger;
429+
430+
final Artifacts artifacts;
431+
432+
final FileSystem fileSystem;
402433
}
403434

404435
/// The result information from the build system.
@@ -422,7 +453,17 @@ class BuildResult {
422453

423454
/// The build system is responsible for invoking and ordering [Target]s.
424455
class BuildSystem {
425-
const BuildSystem();
456+
const BuildSystem({
457+
@required FileSystem fileSystem,
458+
@required Platform platform,
459+
@required Logger logger,
460+
}) : _fileSystem = fileSystem,
461+
_platform = platform,
462+
_logger = logger;
463+
464+
final FileSystem _fileSystem;
465+
final Platform _platform;
466+
final Logger _logger;
426467

427468
/// Build `target` and all of its dependencies.
428469
Future<BuildResult> build(
@@ -436,15 +477,22 @@ class BuildSystem {
436477
// Load file hash store from previous builds.
437478
final FileHashStore fileCache = FileHashStore(
438479
environment: environment,
439-
fileSystem: globals.fs,
440-
logger: globals.logger,
480+
fileSystem: _fileSystem,
481+
logger: _logger,
441482
)..initialize();
442483

443484
// Perform sanity checks on build.
444485
checkCycles(target);
445486

446487
final Node node = target._toNode(environment);
447-
final _BuildInstance buildInstance = _BuildInstance(environment, fileCache, buildSystemConfig);
488+
final _BuildInstance buildInstance = _BuildInstance(
489+
environment: environment,
490+
fileCache: fileCache,
491+
buildSystemConfig: buildSystemConfig,
492+
logger: _logger,
493+
fileSystem: _fileSystem,
494+
platform: _platform,
495+
);
448496
bool passed = true;
449497
try {
450498
passed = await buildInstance.invokeTarget(node);
@@ -486,9 +534,18 @@ class BuildSystem {
486534

487535
/// An active instance of a build.
488536
class _BuildInstance {
489-
_BuildInstance(this.environment, this.fileCache, this.buildSystemConfig)
490-
: resourcePool = Pool(buildSystemConfig.resourcePoolSize ?? globals.platform?.numberOfProcessors ?? 1);
491-
537+
_BuildInstance({
538+
this.environment,
539+
this.fileCache,
540+
this.buildSystemConfig,
541+
this.logger,
542+
this.fileSystem,
543+
Platform platform,
544+
})
545+
: resourcePool = Pool(buildSystemConfig.resourcePoolSize ?? platform?.numberOfProcessors ?? 1);
546+
547+
final Logger logger;
548+
final FileSystem fileSystem;
492549
final BuildSystemConfig buildSystemConfig;
493550
final Pool resourcePool;
494551
final Map<String, AsyncMemoizer<bool>> pending = <String, AsyncMemoizer<bool>>{};
@@ -545,17 +602,17 @@ class _BuildInstance {
545602
// If we're missing a depfile, wait until after evaluating the target to
546603
// compute changes.
547604
final bool canSkip = !node.missingDepfile &&
548-
await node.computeChanges(environment, fileCache);
605+
await node.computeChanges(environment, fileCache, fileSystem, logger);
549606

550607
if (canSkip) {
551608
skipped = true;
552-
globals.printTrace('Skipping target: ${node.target.name}');
609+
logger.printTrace('Skipping target: ${node.target.name}');
553610
updateGraph();
554611
return passed;
555612
}
556-
globals.printTrace('${node.target.name}: Starting due to ${node.invalidatedReasons}');
613+
logger.printTrace('${node.target.name}: Starting due to ${node.invalidatedReasons}');
557614
await node.target.build(environment);
558-
globals.printTrace('${node.target.name}: Complete');
615+
logger.printTrace('${node.target.name}: Complete');
559616

560617
node.inputs
561618
..clear()
@@ -581,7 +638,7 @@ class _BuildInstance {
581638
if (outputFiles.containsKey(previousOutput)) {
582639
continue;
583640
}
584-
final File previousFile = globals.fs.file(previousOutput);
641+
final File previousFile = fileSystem.file(previousOutput);
585642
if (previousFile.existsSync()) {
586643
previousFile.deleteSync();
587644
}
@@ -771,6 +828,8 @@ class Node {
771828
Future<bool> computeChanges(
772829
Environment environment,
773830
FileHashStore fileHashStore,
831+
FileSystem fileSystem,
832+
Logger logger,
774833
) async {
775834
final Set<String> currentOutputPaths = <String>{
776835
for (final File file in outputs) file.path,
@@ -808,7 +867,7 @@ class Node {
808867
// if this isn't a current output file there is no reason to compute the hash.
809868
continue;
810869
}
811-
final File file = globals.fs.file(previousOutput);
870+
final File file = fileSystem.file(previousOutput);
812871
if (!file.existsSync()) {
813872
invalidatedReasons.add(InvalidatedReason.outputMissing);
814873
_dirty = true;
@@ -833,7 +892,7 @@ class Node {
833892
if (missingInputs.isNotEmpty) {
834893
_dirty = true;
835894
final String missingMessage = missingInputs.map((File file) => file.path).join(', ');
836-
globals.printTrace('invalidated build due to missing files: $missingMessage');
895+
logger.printTrace('invalidated build due to missing files: $missingMessage');
837896
invalidatedReasons.add(InvalidatedReason.inputMissing);
838897
}
839898

packages/flutter_tools/lib/src/build_system/source.dart

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import '../artifacts.dart';
66
import '../base/file_system.dart';
77
import '../build_info.dart';
8-
import '../globals.dart' as globals;
98
import 'build_system.dart';
109
import 'exceptions.dart';
1110

@@ -24,7 +23,7 @@ abstract class ResolvedFiles {
2423
/// Collects sources for a [Target] into a single list of [FileSystemEntities].
2524
class SourceVisitor implements ResolvedFiles {
2625
/// Create a new [SourceVisitor] from an [Environment].
27-
SourceVisitor(this.environment, [this.inputs = true]);
26+
SourceVisitor(this.environment, [ this.inputs = true ]);
2827

2928
/// The current environment.
3029
final Environment environment;
@@ -56,7 +55,7 @@ class SourceVisitor implements ResolvedFiles {
5655
final String contents = depfile.readAsStringSync();
5756
final List<String> colonSeparated = contents.split(': ');
5857
if (colonSeparated.length != 2) {
59-
globals.printError('Invalid depfile: ${depfile.path}');
58+
environment.logger.printError('Invalid depfile: ${depfile.path}');
6059
return;
6160
}
6261
if (inputs) {
@@ -78,7 +77,7 @@ class SourceVisitor implements ResolvedFiles {
7877
.map<String>((String path) => path.replaceAllMapped(_escapeExpr, (Match match) => match.group(1)).trim())
7978
.where((String path) => path.isNotEmpty)
8079
.toSet()
81-
.map((String path) => globals.fs.file(path));
80+
.map(environment.fileSystem.file);
8281
}
8382

8483
/// Visit a [Source] which contains a file URL.
@@ -101,35 +100,36 @@ class SourceVisitor implements ResolvedFiles {
101100
switch (rawParts.first) {
102101
case Environment.kProjectDirectory:
103102
segments.addAll(
104-
globals.fs.path.split(environment.projectDir.resolveSymbolicLinksSync()));
103+
environment.fileSystem.path.split(environment.projectDir.resolveSymbolicLinksSync()));
105104
break;
106105
case Environment.kBuildDirectory:
107-
segments.addAll(globals.fs.path.split(
108-
environment.buildDir.resolveSymbolicLinksSync()));
106+
segments.addAll(environment.fileSystem.path.split(
107+
environment.buildDir.resolveSymbolicLinksSync()));
109108
break;
110109
case Environment.kCacheDirectory:
111110
segments.addAll(
112-
globals.fs.path.split(environment.cacheDir.resolveSymbolicLinksSync()));
111+
environment.fileSystem.path.split(environment.cacheDir.resolveSymbolicLinksSync()));
113112
break;
114113
case Environment.kFlutterRootDirectory:
115114
// flutter root will not contain a symbolic link.
116115
segments.addAll(
117-
globals.fs.path.split(environment.flutterRootDir.absolute.path));
116+
environment.fileSystem.path.split(environment.flutterRootDir.absolute.path));
118117
break;
119118
case Environment.kOutputDirectory:
120119
segments.addAll(
121-
globals.fs.path.split(environment.outputDir.resolveSymbolicLinksSync()));
120+
environment.fileSystem.path.split(environment.outputDir.resolveSymbolicLinksSync()));
122121
break;
123122
default:
124123
throw InvalidPatternException(pattern);
125124
}
126125
rawParts.skip(1).forEach(segments.add);
127-
final String filePath = globals.fs.path.joinAll(segments);
126+
final String filePath = environment.fileSystem.path.joinAll(segments);
128127
if (!hasWildcard) {
129-
if (optional && !globals.fs.isFileSync(filePath)) {
128+
if (optional && !environment.fileSystem.isFileSync(filePath)) {
130129
return;
131130
}
132-
sources.add(globals.fs.file(globals.fs.path.normalize(filePath)));
131+
sources.add(environment.fileSystem.file(
132+
environment.fileSystem.path.normalize(filePath)));
133133
return;
134134
}
135135
// Perform a simple match by splitting the wildcard containing file one
@@ -143,21 +143,21 @@ class SourceVisitor implements ResolvedFiles {
143143
if (wildcardSegments.length > 2) {
144144
throw InvalidPatternException(pattern);
145145
}
146-
if (!globals.fs.directory(filePath).existsSync()) {
146+
if (!environment.fileSystem.directory(filePath).existsSync()) {
147147
throw Exception('$filePath does not exist!');
148148
}
149-
for (final FileSystemEntity entity in globals.fs.directory(filePath).listSync()) {
150-
final String filename = globals.fs.path.basename(entity.path);
149+
for (final FileSystemEntity entity in environment.fileSystem.directory(filePath).listSync()) {
150+
final String filename = environment.fileSystem.path.basename(entity.path);
151151
if (wildcardSegments.isEmpty) {
152-
sources.add(globals.fs.file(entity.absolute));
152+
sources.add(environment.fileSystem.file(entity.absolute));
153153
} else if (wildcardSegments.length == 1) {
154154
if (filename.startsWith(wildcardSegments[0]) ||
155155
filename.endsWith(wildcardSegments[0])) {
156-
sources.add(globals.fs.file(entity.absolute));
156+
sources.add(environment.fileSystem.file(entity.absolute));
157157
}
158158
} else if (filename.startsWith(wildcardSegments[0])) {
159159
if (filename.substring(wildcardSegments[0].length).endsWith(wildcardSegments[1])) {
160-
sources.add(globals.fs.file(entity.absolute));
160+
sources.add(environment.fileSystem.file(entity.absolute));
161161
}
162162
}
163163
}
@@ -167,15 +167,16 @@ class SourceVisitor implements ResolvedFiles {
167167
///
168168
/// If the [Artifact] points to a directory then all child files are included.
169169
void visitArtifact(Artifact artifact, TargetPlatform platform, BuildMode mode) {
170-
final String path = globals.artifacts.getArtifactPath(artifact, platform: platform, mode: mode);
171-
if (globals.fs.isDirectorySync(path)) {
170+
final String path = environment.artifacts
171+
.getArtifactPath(artifact, platform: platform, mode: mode);
172+
if (environment.fileSystem.isDirectorySync(path)) {
172173
sources.addAll(<File>[
173-
for (FileSystemEntity entity in globals.fs.directory(path).listSync(recursive: true))
174+
for (FileSystemEntity entity in environment.fileSystem.directory(path).listSync(recursive: true))
174175
if (entity is File)
175176
entity,
176177
]);
177178
} else {
178-
sources.add(globals.fs.file(path));
179+
sources.add(environment.fileSystem.file(path));
179180
}
180181
}
181182
}

0 commit comments

Comments
 (0)