refactor depfile usage and update linux rule (#42487)
diff --git a/packages/flutter_tools/lib/src/build_system/build_system.dart b/packages/flutter_tools/lib/src/build_system/build_system.dart index cba474a..bb7d035 100644 --- a/packages/flutter_tools/lib/src/build_system/build_system.dart +++ b/packages/flutter_tools/lib/src/build_system/build_system.dart
@@ -502,7 +502,7 @@ outputFiles[output.path] = output; } for (File input in node.inputs) { - final String resolvedPath = input.resolveSymbolicLinksSync(); + final String resolvedPath = input.absolute.path; if (outputFiles.containsKey(resolvedPath)) { continue; } @@ -704,7 +704,7 @@ /// One or more reasons why a task was invalidated. /// /// May be empty if the task was skipped. - final Set<InvalidedReason> invalidatedReasons = <InvalidedReason>{}; + final Set<InvalidatedReason> invalidatedReasons = <InvalidatedReason>{}; /// Whether this node needs an action performed. bool get dirty => _dirty; @@ -735,7 +735,7 @@ if (fileHashStore.currentHashes.containsKey(absolutePath)) { final String currentHash = fileHashStore.currentHashes[absolutePath]; if (currentHash != previousHash) { - invalidatedReasons.add(InvalidedReason.inputChanged); + invalidatedReasons.add(InvalidatedReason.inputChanged); _dirty = true; } } else { @@ -749,13 +749,13 @@ // output paths changed. if (!currentOutputPaths.contains(previousOutput)) { _dirty = true; - invalidatedReasons.add(InvalidedReason.outputSetChanged); + invalidatedReasons.add(InvalidatedReason.outputSetChanged); // if this isn't a current output file there is no reason to compute the hash. continue; } final File file = fs.file(previousOutput); if (!file.existsSync()) { - invalidatedReasons.add(InvalidedReason.outputMissing); + invalidatedReasons.add(InvalidatedReason.outputMissing); _dirty = true; continue; } @@ -764,7 +764,7 @@ if (fileHashStore.currentHashes.containsKey(absolutePath)) { final String currentHash = fileHashStore.currentHashes[absolutePath]; if (currentHash != previousHash) { - invalidatedReasons.add(InvalidedReason.outputChanged); + invalidatedReasons.add(InvalidatedReason.outputChanged); _dirty = true; } } else { @@ -772,9 +772,14 @@ } } - // If we depend on a file that doesnt exist on disk, kill the build. + // If we depend on a file that doesnt exist on disk, mark the build as + // dirty. if the rule is not correctly specified, this will result in it + // always being rerun. if (missingInputs.isNotEmpty) { - throw MissingInputException(missingInputs, target.name); + _dirty = true; + final String missingMessage = missingInputs.map((File file) => file.path).join(', '); + printTrace('invalidated build due to missing files: $missingMessage'); + invalidatedReasons.add(InvalidatedReason.inputMissing); } // If we have files to hash, compute them asynchronously and then @@ -782,7 +787,7 @@ if (sourcesToHash.isNotEmpty) { final List<File> dirty = await fileHashStore.hashFiles(sourcesToHash); if (dirty.isNotEmpty) { - invalidatedReasons.add(InvalidedReason.inputChanged); + invalidatedReasons.add(InvalidatedReason.inputChanged); _dirty = true; } } @@ -790,8 +795,12 @@ } } -/// A description of why a task was rerun. -enum InvalidedReason { +/// A description of why a target was rerun. +enum InvalidatedReason { + /// An input file that was expected is missing. This can occur when using + /// depfile dependencies, or if a target is incorrectly specified. + inputMissing, + /// An input file has an updated hash. inputChanged,
diff --git a/packages/flutter_tools/lib/src/build_system/depfile.dart b/packages/flutter_tools/lib/src/build_system/depfile.dart new file mode 100644 index 0000000..1df5e7d --- /dev/null +++ b/packages/flutter_tools/lib/src/build_system/depfile.dart
@@ -0,0 +1,78 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../base/file_system.dart'; +import '../base/platform.dart'; +import '../globals.dart'; + +/// A class for representing depfile formats. +class Depfile { + /// Create a [Depfile] from a list of [input] files and [output] files. + const Depfile(this.inputs, this.outputs); + + /// Parse the depfile contents from [file]. + /// + /// If the syntax is invalid, returns an empty [Depfile]. + factory Depfile.parse(File file) { + final String contents = file.readAsStringSync(); + final List<String> colonSeparated = contents.split(': '); + if (colonSeparated.length != 2) { + printError('Invalid depfile: ${file.path}'); + return const Depfile(<File>[], <File>[]); + } + final List<File> inputs = _processList(colonSeparated[1].trim()); + final List<File> outputs = _processList(colonSeparated[0].trim()); + return Depfile(inputs, outputs); + } + + /// The input files for this depfile. + final List<File> inputs; + + /// The output files for this depfile. + final List<File> outputs; + + /// Given an [depfile] File, write the depfile contents. + /// + /// If either [inputs] or [outputs] is empty, does not write to the file. + void writeToFile(File depfile) { + if (inputs.isEmpty || outputs.isEmpty) { + return; + } + final StringBuffer buffer = StringBuffer(); + _writeFilesToBuffer(outputs, buffer); + buffer.write(': '); + _writeFilesToBuffer(inputs, buffer); + depfile.writeAsStringSync(buffer.toString()); + } + + void _writeFilesToBuffer(List<File> files, StringBuffer buffer) { + for (File outputFile in files) { + if (platform.isWindows) { + // Paths in a depfile have to be escaped on windows. + final String escapedPath = outputFile.path.replaceAll(r'\', r'\\'); + buffer.write(' $escapedPath'); + } else { + buffer.write(' ${outputFile.path}'); + } + } + } + + static final RegExp _separatorExpr = RegExp(r'([^\\]) '); + static final RegExp _escapeExpr = RegExp(r'\\(.)'); + + static List<File> _processList(String rawText) { + return rawText + // Put every file on right-hand side on the separate line + .replaceAllMapped(_separatorExpr, (Match match) => '${match.group(1)}\n') + .split('\n') + // Expand escape sequences, so that '\ ', for example,ß becomes ' ' + .map<String>((String path) => path.replaceAllMapped(_escapeExpr, (Match match) => match.group(1)).trim()) + .where((String path) => path.isNotEmpty) + // The tool doesn't write duplicates to these lists. This call is an attempt to + // be resillient to the outputs of other tools which write or user edits to depfiles. + .toSet() + .map((String path) => fs.file(path)) + .toList(); + } +}
diff --git a/packages/flutter_tools/lib/src/build_system/targets/linux.dart b/packages/flutter_tools/lib/src/build_system/targets/linux.dart index 4821163..ab9abc9 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/linux.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/linux.dart
@@ -11,10 +11,22 @@ import '../../devfs.dart'; import '../../globals.dart'; import '../build_system.dart'; +import '../depfile.dart'; import '../exceptions.dart'; import 'assets.dart'; import 'dart.dart'; +/// The only files/subdirectories we care out. +const List<String> _kLinuxArtifacts = <String>[ + 'libflutter_linux_glfw.so', + 'flutter_export.h', + 'flutter_messenger.h', + 'flutter_plugin_registrar.h', + 'flutter_glfw.h', + 'icudtl.dat', + 'cpp_client_wrapper_glfw/', +]; + /// Copies the Linux desktop embedding files to the copy directory. class UnpackLinuxDebug extends Target { const UnpackLinuxDebug(); @@ -25,17 +37,12 @@ @override List<Source> get inputs => const <Source>[ Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/linux.dart'), - Source.artifact(Artifact.linuxDesktopPath, mode: BuildMode.debug), + Source.depfile('linux_engine_sources.d'), ]; @override List<Source> get outputs => const <Source>[ - Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/libflutter_linux_glfw.so'), - Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/flutter_export.h'), - Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/flutter_messenger.h'), - Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/flutter_plugin_registrar.h'), - Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/flutter_glfw.h'), - Source.pattern('{PROJECT_DIR}/linux/flutter/ephemeral/icudtl.dat'), + Source.depfile('linux_engine_sources.d'), ]; @override @@ -44,22 +51,55 @@ @override Future<void> build(Environment environment) async { final String basePath = artifacts.getArtifactPath(Artifact.linuxDesktopPath); - for (File input in fs.directory(basePath) - .listSync(recursive: true) - .whereType<File>()) { - final String outputPath = fs.path.join( - environment.projectDir.path, - 'linux', - 'flutter', - 'ephemeral', - fs.path.relative(input.path, from: basePath), - ); - final File destinationFile = fs.file(outputPath); - if (!destinationFile.parent.existsSync()) { - destinationFile.parent.createSync(recursive: true); + final List<File> inputs = <File>[]; + final List<File> outputs = <File>[]; + final String outputPrefix = fs.path.join( + environment.projectDir.path, + 'linux', + 'flutter', + 'ephemeral', + ); + // The native linux artifacts are composed of 6 files and a directory (listed above) + // which need to be copied to the target directory. + for (String artifact in _kLinuxArtifacts) { + final String entityPath = fs.path.join(basePath, artifact); + // If this artifact is a file, just copy the source over. + if (fs.isFileSync(entityPath)) { + final String outputPath = fs.path.join( + outputPrefix, + fs.path.relative(entityPath, from: basePath), + ); + final File destinationFile = fs.file(outputPath); + if (!destinationFile.parent.existsSync()) { + destinationFile.parent.createSync(recursive: true); + } + final File inputFile = fs.file(entityPath); + inputFile.copySync(destinationFile.path); + inputs.add(inputFile); + outputs.add(destinationFile); + continue; } - fs.file(input).copySync(destinationFile.path); + // If the artifact is the directory cpp_client_wrapper, recursively + // copy every file from it. + for (File input in fs.directory(entityPath) + .listSync(recursive: true) + .whereType<File>()) { + final String outputPath = fs.path.join( + outputPrefix, + fs.path.relative(input.path, from: basePath), + ); + final File destinationFile = fs.file(outputPath); + if (!destinationFile.parent.existsSync()) { + destinationFile.parent.createSync(recursive: true); + } + final File inputFile = fs.file(input); + inputFile.copySync(destinationFile.path); + inputs.add(inputFile); + outputs.add(destinationFile); + } } + final Depfile depfile = Depfile(inputs, outputs); + depfile.writeToFile(environment.buildDir.childFile('linux_engine_sources.d')); } }
diff --git a/packages/flutter_tools/lib/src/bundle.dart b/packages/flutter_tools/lib/src/bundle.dart index 65cd920..996b166 100644 --- a/packages/flutter_tools/lib/src/bundle.dart +++ b/packages/flutter_tools/lib/src/bundle.dart
@@ -7,15 +7,13 @@ import 'package:meta/meta.dart'; import 'package:pool/pool.dart'; -import 'artifacts.dart'; import 'asset.dart'; import 'base/common.dart'; import 'base/file_system.dart'; -import 'base/platform.dart'; import 'build_info.dart'; import 'build_system/build_system.dart'; +import 'build_system/depfile.dart'; import 'build_system/targets/dart.dart'; -import 'compile.dart'; import 'dart/package_map.dart'; import 'devfs.dart'; import 'globals.dart'; @@ -45,10 +43,6 @@ const String defaultPrivateKeyPath = 'privatekey.der'; -const String _kKernelKey = 'kernel_blob.bin'; -const String _kVMSnapshotData = 'vm_snapshot_data'; -const String _kIsolateSnapshotData = 'isolate_snapshot_data'; - /// Provides a `build` method that builds the bundle. class BundleBuilder { /// Builds the bundle for the given target platform. @@ -72,73 +66,29 @@ List<String> extraGenSnapshotOptions = const <String>[], List<String> fileSystemRoots, String fileSystemScheme, - bool shouldBuildWithAssemble = false, }) async { mainPath ??= defaultMainPath; depfilePath ??= defaultDepfilePath; assetDirPath ??= getAssetBuildDirectory(); packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath); - applicationKernelFilePath ??= getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation); final FlutterProject flutterProject = FlutterProject.current(); - - if (shouldBuildWithAssemble) { - await buildWithAssemble( - buildMode: buildMode ?? BuildMode.debug, - targetPlatform: platform, - mainPath: mainPath, - flutterProject: flutterProject, - outputDir: assetDirPath, - depfilePath: depfilePath, - precompiled: precompiledSnapshot, - ); - return; - } - - DevFSContent kernelContent; - if (!precompiledSnapshot) { - if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty) { - printTrace('Extra front-end options: $extraFrontEndOptions'); - } - ensureDirectoryExists(applicationKernelFilePath); - final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(flutterProject); - final CompilerOutput compilerOutput = await kernelCompiler.compile( - sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath, mode: buildMode), - mainPath: fs.file(mainPath).absolute.path, - outputFilePath: applicationKernelFilePath, - depFilePath: depfilePath, - buildMode: buildMode, - trackWidgetCreation: trackWidgetCreation, - extraFrontEndOptions: extraFrontEndOptions, - fileSystemRoots: fileSystemRoots, - fileSystemScheme: fileSystemScheme, - packagesPath: packagesPath, - ); - if (compilerOutput?.outputFilename == null) { - throwToolExit('Compiler failed on $mainPath'); - } - kernelContent = DevFSFileContent(fs.file(compilerOutput.outputFilename)); - - fs.directory(getBuildDirectory()).childFile('frontend_server.d') - .writeAsStringSync('frontend_server.d: ${artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk)}\n'); - } - - final AssetBundle assets = await buildAssets( - manifestPath: manifestPath, - assetDirPath: assetDirPath, - packagesPath: packagesPath, - reportLicensedPackages: reportLicensedPackages, + await buildWithAssemble( + buildMode: buildMode ?? BuildMode.debug, + targetPlatform: platform, + mainPath: mainPath, + flutterProject: flutterProject, + outputDir: assetDirPath, + depfilePath: depfilePath, + precompiled: precompiledSnapshot, ); - if (assets == null) { - throwToolExit('Error building assets', exitCode: 1); + // Work around for flutter_tester placing kernel artifacts in odd places. + if (applicationKernelFilePath != null) { + final File outputDill = fs.directory(assetDirPath).childFile('kernel_blob.bin'); + if (outputDill.existsSync()) { + outputDill.copySync(applicationKernelFilePath); + } } - - await assemble( - buildMode: buildMode, - assetBundle: assets, - kernelContent: kernelContent, - privateKeyPath: privateKeyPath, - assetDirPath: assetDirPath, - ); + return; } } @@ -178,30 +128,13 @@ } throwToolExit('Failed to build bundle.'); } - - // Output depfile format: - final StringBuffer buffer = StringBuffer(); - buffer.write('flutter_bundle'); - _writeFilesToBuffer(result.outputFiles, buffer); - buffer.write(': '); - _writeFilesToBuffer(result.inputFiles, buffer); - - final File depfile = fs.file(depfilePath); - if (!depfile.parent.existsSync()) { - depfile.parent.createSync(recursive: true); - } - depfile.writeAsStringSync(buffer.toString()); -} - -void _writeFilesToBuffer(List<File> files, StringBuffer buffer) { - for (File outputFile in files) { - if (platform.isWindows) { - // Paths in a depfile have to be escaped on windows. - final String escapedPath = outputFile.path.replaceAll(r'\', r'\\'); - buffer.write(' $escapedPath'); - } else { - buffer.write(' ${outputFile.path}'); + if (depfilePath != null) { + final Depfile depfile = Depfile(result.inputFiles, result.outputFiles); + final File outputDepfile = fs.file(depfilePath); + if (!outputDepfile.parent.existsSync()) { + outputDepfile.parent.createSync(recursive: true); } + depfile.writeToFile(outputDepfile); } } @@ -231,32 +164,6 @@ return assetBundle; } -Future<void> assemble({ - BuildMode buildMode, - AssetBundle assetBundle, - DevFSContent kernelContent, - String privateKeyPath = defaultPrivateKeyPath, - String assetDirPath, -}) async { - assetDirPath ??= getAssetBuildDirectory(); - printTrace('Building bundle'); - - final Map<String, DevFSContent> assetEntries = Map<String, DevFSContent>.from(assetBundle.entries); - if (kernelContent != null) { - final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData, mode: buildMode); - final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData, mode: buildMode); - assetEntries[_kKernelKey] = kernelContent; - assetEntries[_kVMSnapshotData] = DevFSFileContent(fs.file(vmSnapshotData)); - assetEntries[_kIsolateSnapshotData] = DevFSFileContent(fs.file(isolateSnapshotData)); - } - - printTrace('Writing asset files to $assetDirPath'); - ensureDirectoryExists(assetDirPath); - - await writeBundle(fs.directory(assetDirPath), assetEntries); - printTrace('Wrote $assetDirPath'); -} - Future<void> writeBundle( Directory bundleDir, Map<String, DevFSContent> assetEntries,
diff --git a/packages/flutter_tools/lib/src/commands/build_bundle.dart b/packages/flutter_tools/lib/src/commands/build_bundle.dart index a65803a..72e9be5 100644 --- a/packages/flutter_tools/lib/src/commands/build_bundle.dart +++ b/packages/flutter_tools/lib/src/commands/build_bundle.dart
@@ -138,7 +138,6 @@ extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions], fileSystemScheme: argResults['filesystem-scheme'], fileSystemRoots: argResults['filesystem-root'], - shouldBuildWithAssemble: true, ); return null; }
diff --git a/packages/flutter_tools/lib/src/tester/flutter_tester.dart b/packages/flutter_tools/lib/src/tester/flutter_tester.dart index 9deadc0..75844c9 100644 --- a/packages/flutter_tools/lib/src/tester/flutter_tester.dart +++ b/packages/flutter_tools/lib/src/tester/flutter_tester.dart
@@ -145,12 +145,13 @@ trackWidgetCreation: buildInfo.trackWidgetCreation, ); await BundleBuilder().build( + buildMode: buildInfo.mode, mainPath: mainPath, assetDirPath: assetDirPath, applicationKernelFilePath: applicationKernelFilePath, precompiledSnapshot: false, - buildMode: buildInfo.mode, trackWidgetCreation: buildInfo.trackWidgetCreation, + platform: getTargetPlatformForName(getNameForHostPlatform(getCurrentHostPlatform())), ); command.add('--flutter-assets-dir=$assetDirPath');
diff --git a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart index 809ea03..b782682 100644 --- a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart +++ b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart
@@ -106,13 +106,12 @@ ); }); - test('Throws exception if asked to build with missing inputs', () => testbed.run(() async { + test('Does not throw exception if asked to build with missing inputs', () => testbed.run(() async { // Delete required input file. fs.file('foo.dart').deleteSync(); final BuildResult buildResult = await buildSystem.build(fooTarget, environment); - expect(buildResult.hasException, true); - expect(buildResult.exceptions.values.single.exception, isInstanceOf<MissingInputException>()); + expect(buildResult.hasException, false); })); test('Throws exception if it does not produce a specified output', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/build_system/depfile_test.dart b/packages/flutter_tools/test/general.shard/build_system/depfile_test.dart new file mode 100644 index 0000000..aa0fd38 --- /dev/null +++ b/packages/flutter_tools/test/general.shard/build_system/depfile_test.dart
@@ -0,0 +1,106 @@ +// Copyright 2019 The Chromium Authors. 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:file/memory.dart'; +import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/build_system/depfile.dart'; + +import '../../src/common.dart'; +import '../../src/testbed.dart'; + +void main() { + Testbed testbed; + + setUp(() { + testbed = Testbed(); + }); + test('Can parse depfile from file', () => testbed.run(() { + final File depfileSource = fs.file('example.d')..writeAsStringSync(''' +a.txt: b.txt +'''); + final Depfile depfile = Depfile.parse(depfileSource); + + expect(depfile.inputs.single.path, 'b.txt'); + expect(depfile.outputs.single.path, 'a.txt'); + })); + + test('Can parse depfile with multiple inputs', () => testbed.run(() { + final FileSystem fs = MemoryFileSystem(); + final File depfileSource = fs.file('example.d')..writeAsStringSync(''' +a.txt: b.txt c.txt d.txt +'''); + final Depfile depfile = Depfile.parse(depfileSource); + + expect(depfile.inputs.map((File file) => file.path), <String>[ + 'b.txt', + 'c.txt', + 'd.txt', + ]); + expect(depfile.outputs.single.path, 'a.txt'); + })); + + test('Can parse depfile with multiple outputs', () => testbed.run(() { + final FileSystem fs = MemoryFileSystem(); + final File depfileSource = fs.file('example.d')..writeAsStringSync(''' +a.txt c.txt d.txt: b.txt +'''); + final Depfile depfile = Depfile.parse(depfileSource); + + expect(depfile.inputs.single.path, 'b.txt'); + expect(depfile.outputs.map((File file) => file.path), <String>[ + 'a.txt', + 'c.txt', + 'd.txt', + ]); + })); + + test('Can parse depfile with windows file paths', () => testbed.run(() { + final FileSystem fs = MemoryFileSystem(); + final File depfileSource = fs.file('example.d')..writeAsStringSync(r''' +C:\\a.txt: C:\\b.txt +'''); + final Depfile depfile = Depfile.parse(depfileSource); + + expect(depfile.inputs.single.path, r'C:\b.txt'); + expect(depfile.outputs.single.path, r'C:\a.txt'); + }, overrides: <Type, Generator>{ + FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows), + })); + + test('Resillient to weird whitespace', () => testbed.run(() { + final FileSystem fs = MemoryFileSystem(); + final File depfileSource = fs.file('example.d')..writeAsStringSync(r''' +a.txt + : b.txt c.txt + + +'''); + final Depfile depfile = Depfile.parse(depfileSource); + + expect(depfile.inputs, hasLength(2)); + expect(depfile.outputs.single.path, 'a.txt'); + })); + + test('Resillient to duplicate files', () => testbed.run(() { + final FileSystem fs = MemoryFileSystem(); + final File depfileSource = fs.file('example.d')..writeAsStringSync(r''' +a.txt: b.txt b.txt +'''); + final Depfile depfile = Depfile.parse(depfileSource); + + expect(depfile.inputs.single.path, 'b.txt'); + expect(depfile.outputs.single.path, 'a.txt'); + })); + + test('Resillient to malformed file, missing :', () => testbed.run(() { + final FileSystem fs = MemoryFileSystem(); + final File depfileSource = fs.file('example.d')..writeAsStringSync(r''' +a.text b.txt +'''); + final Depfile depfile = Depfile.parse(depfileSource); + + expect(depfile.inputs, isEmpty); + expect(depfile.outputs, isEmpty); + })); +}
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/linux_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/linux_test.dart index d707235..f4bb3dd 100644 --- a/packages/flutter_tools/test/general.shard/build_system/targets/linux_test.dart +++ b/packages/flutter_tools/test/general.shard/build_system/targets/linux_test.dart
@@ -39,6 +39,7 @@ kBuildMode: 'debug', } ); + fs.file('bin/cache/artifacts/engine/linux-x64/unrelated-stuff').createSync(recursive: true); fs.file('bin/cache/artifacts/engine/linux-x64/libflutter_linux_glfw.so').createSync(recursive: true); fs.file('bin/cache/artifacts/engine/linux-x64/flutter_export.h').createSync(); fs.file('bin/cache/artifacts/engine/linux-x64/flutter_messenger.h').createSync(); @@ -53,7 +54,7 @@ }); }); - test('Copies files to correct cache directory', () => testbed.run(() async { + test('Copies files to correct cache directory, excluding unrelated code', () => testbed.run(() async { final BuildResult result = await buildSystem.build(const UnpackLinuxDebug(), environment); expect(result.hasException, false); @@ -64,6 +65,7 @@ expect(fs.file('linux/flutter/ephemeral/flutter_glfw.h').existsSync(), true); expect(fs.file('linux/flutter/ephemeral/icudtl.dat').existsSync(), true); expect(fs.file('linux/flutter/ephemeral/cpp_client_wrapper_glfw/foo').existsSync(), true); + expect(fs.file('linux/flutter/ephemeral/unrelated-stuff').existsSync(), false); })); test('Does not re-copy files unecessarily', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/bundle_shim_test.dart b/packages/flutter_tools/test/general.shard/bundle_shim_test.dart index be36d51..6b678c1 100644 --- a/packages/flutter_tools/test/general.shard/bundle_shim_test.dart +++ b/packages/flutter_tools/test/general.shard/bundle_shim_test.dart
@@ -43,7 +43,7 @@ ); expect(fs.file(fs.path.join('example', 'kernel_blob.bin')).existsSync(), true); expect(fs.file(fs.path.join('example', 'LICENSE')).existsSync(), true); - expect(fs.file(fs.path.join('example.d')).existsSync(), true); + expect(fs.file(fs.path.join('example.d')).existsSync(), false); })); test('Handles build system failure', () => testbed.run(() {
diff --git a/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart b/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart index f782d78..fa6a4f0 100644 --- a/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart +++ b/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart
@@ -9,10 +9,8 @@ import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/build_info.dart'; -import 'package:flutter_tools/src/cache.dart'; -import 'package:flutter_tools/src/compile.dart'; +import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/device.dart'; -import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/tester/flutter_tester.dart'; import 'package:mockito/mockito.dart'; import 'package:process/process.dart'; @@ -102,24 +100,23 @@ String mainPath; MockArtifacts mockArtifacts; - MockKernelCompiler mockKernelCompiler; MockProcessManager mockProcessManager; MockProcess mockProcess; + MockBuildSystem mockBuildSystem; final Map<Type, Generator> startOverrides = <Type, Generator>{ Platform: () => FakePlatform(operatingSystem: 'linux'), FileSystem: () => fs, ProcessManager: () => mockProcessManager, - Cache: () => Cache(rootOverride: fs.directory(flutterRoot)), - KernelCompilerFactory: () => FakeKernelCompilerFactory(mockKernelCompiler), Artifacts: () => mockArtifacts, + BuildSystem: () => mockBuildSystem, }; setUp(() { + mockBuildSystem = MockBuildSystem(); flutterRoot = fs.path.join('home', 'me', 'flutter'); flutterTesterPath = fs.path.join(flutterRoot, 'bin', 'cache', 'artifacts', 'engine', 'linux-x64', 'flutter_tester'); - final File flutterTesterFile = fs.file(flutterTesterPath); flutterTesterFile.parent.createSync(recursive: true); flutterTesterFile.writeAsBytesSync(const <int>[]); @@ -139,24 +136,23 @@ mode: anyNamed('mode') )).thenReturn(artifactPath); - mockKernelCompiler = MockKernelCompiler(); + when(mockBuildSystem.build( + any, + any, + )).thenAnswer((_) async { + fs.file('$mainPath.dill').createSync(recursive: true); + return BuildResult(success: true); + }); }); testUsingContext('not debug', () async { final LaunchResult result = await device.startApp(null, mainPath: mainPath, debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null))); + expect(result.started, isFalse); }, overrides: startOverrides); - testUsingContext('no flutter_tester', () async { - fs.file(flutterTesterPath).deleteSync(); - expect(() async { - await device.startApp(null, - mainPath: mainPath, - debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.debug, null))); - }, throwsToolExit()); - }, overrides: startOverrides); testUsingContext('start', () async { final Uri observatoryUri = Uri.parse('http://127.0.0.1:6666/'); @@ -168,22 +164,6 @@ .codeUnits, ])); - when(mockKernelCompiler.compile( - sdkRoot: anyNamed('sdkRoot'), - mainPath: anyNamed('mainPath'), - outputFilePath: anyNamed('outputFilePath'), - depFilePath: anyNamed('depFilePath'), - buildMode: BuildMode.debug, - trackWidgetCreation: anyNamed('trackWidgetCreation'), - extraFrontEndOptions: anyNamed('extraFrontEndOptions'), - fileSystemRoots: anyNamed('fileSystemRoots'), - fileSystemScheme: anyNamed('fileSystemScheme'), - packagesPath: anyNamed('packagesPath'), - )).thenAnswer((_) async { - fs.file('$mainPath.dill').createSync(recursive: true); - return CompilerOutput('$mainPath.dill', 0, <Uri>[]); - }); - final LaunchResult result = await device.startApp(null, mainPath: mainPath, debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null))); @@ -195,15 +175,5 @@ }); } +class MockBuildSystem extends Mock implements BuildSystem {} class MockArtifacts extends Mock implements Artifacts {} -class MockKernelCompiler extends Mock implements KernelCompiler {} -class FakeKernelCompilerFactory implements KernelCompilerFactory { - FakeKernelCompilerFactory(this.kernelCompiler); - - final KernelCompiler kernelCompiler; - - @override - Future<KernelCompiler> create(FlutterProject flutterProject) async { - return kernelCompiler; - } -}