Unverified Commit f5f70f0c authored by Jacob Richman's avatar Jacob Richman Committed by GitHub

Include .track in file names for cached dill files for builds with --track-widget-creation (#23299)

Ensure that cached dill files for builds with --track-widget-creation
always have .track. in the file name to avoid mixing transformed and
untransformed kernel files.
parent 93573de2
......@@ -9,6 +9,7 @@ import 'package:meta/meta.dart';
import '../android/android_sdk.dart';
import '../artifacts.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../compile.dart';
import '../dart/package_map.dart';
import '../globals.dart';
......@@ -293,6 +294,7 @@ class AOTSnapshotter {
@required String mainPath,
@required String packagesPath,
@required String outputPath,
@required bool trackWidgetCreation,
List<String> extraFrontEndOptions = const <String>[],
}) async {
final Directory outputDir = fs.directory(outputPath);
......@@ -308,12 +310,15 @@ class AOTSnapshotter {
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
mainPath: mainPath,
packagesPath: packagesPath,
outputFilePath: fs.path.join(outputPath, 'app.dill'),
outputFilePath: getKernelPathForTransformerOptions(
fs.path.join(outputPath, 'app.dill'),
trackWidgetCreation: trackWidgetCreation,
),
depFilePath: depfilePath,
extraFrontEndOptions: extraFrontEndOptions,
linkPlatformKernelIn: true,
aot: true,
trackWidgetCreation: false,
trackWidgetCreation: trackWidgetCreation,
targetProductVm: buildMode == BuildMode.release,
);
......
......@@ -4,6 +4,8 @@
import 'dart:async';
import 'package:meta/meta.dart';
import 'artifacts.dart';
import 'asset.dart';
import 'base/build.dart';
......@@ -19,7 +21,24 @@ const String defaultMainPath = 'lib/main.dart';
const String defaultAssetBasePath = '.';
const String defaultManifestPath = 'pubspec.yaml';
String get defaultDepfilePath => fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d');
String get defaultApplicationKernelPath => fs.path.join(getBuildDirectory(), 'app.dill');
String getDefaultApplicationKernelPath({@required bool trackWidgetCreation}) {
return getKernelPathForTransformerOptions(
fs.path.join(getBuildDirectory(), 'app.dill'),
trackWidgetCreation: trackWidgetCreation,
);
}
String getKernelPathForTransformerOptions(
String path, {
@required bool trackWidgetCreation,
}) {
if (trackWidgetCreation) {
path += '.track.dill';
}
return path;
}
const String defaultPrivateKeyPath = 'privatekey.der';
const String _kKernelKey = 'kernel_blob.bin';
......@@ -50,7 +69,7 @@ Future<void> build({
depfilePath ??= defaultDepfilePath;
assetDirPath ??= getAssetBuildDirectory();
packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
applicationKernelFilePath ??= defaultApplicationKernelPath;
applicationKernelFilePath ??= getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation);
DevFSContent kernelContent;
if (!precompiledSnapshot) {
......
......@@ -85,6 +85,7 @@ class BuildAotCommand extends BuildSubCommand {
buildMode: buildMode,
mainPath: mainPath,
packagesPath: PackageMap.globalPackagesPath,
trackWidgetCreation: false,
outputPath: outputPath,
extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
);
......
......@@ -23,7 +23,6 @@ class BuildBundleCommand extends BuildSubCommand {
..addOption('manifest', defaultsTo: defaultManifestPath)
..addOption('private-key', defaultsTo: defaultPrivateKeyPath)
..addOption('depfile', defaultsTo: defaultDepfilePath)
..addOption('kernel-file', defaultsTo: defaultApplicationKernelPath)
..addOption('target-platform',
defaultsTo: 'android-arm',
allowed: <String>['android-arm', 'android-arm64', 'ios']
......@@ -92,7 +91,6 @@ class BuildBundleCommand extends BuildSubCommand {
buildMode: buildMode,
mainPath: targetFile,
manifestPath: argResults['manifest'],
applicationKernelFilePath: argResults['kernel-file'],
depfilePath: argResults['depfile'],
privateKeyPath: argResults['private-key'],
assetDirPath: argResults['asset-dir'],
......
......@@ -165,7 +165,8 @@ class FuchsiaReloadCommand extends FlutterCommand {
debuggingOptions: DebuggingOptions.enabled(getBuildInfo()),
target: _target,
projectRootPath: _fuchsiaProjectPath,
packagesFilePath: _dotPackagesPath);
packagesFilePath: _dotPackagesPath,
);
printStatus('Connecting to $_modName');
await hotRunner.attach();
} finally {
......
......@@ -5,6 +5,7 @@
import 'dart:async';
import 'dart:convert';
import 'package:meta/meta.dart';
import 'package:usage/uuid/uuid.dart';
import 'artifacts.dart';
......@@ -123,7 +124,7 @@ class KernelCompiler {
String depFilePath,
bool linkPlatformKernelIn = false,
bool aot = false,
bool trackWidgetCreation = false,
@required bool trackWidgetCreation,
List<String> extraFrontEndOptions,
String incrementalCompilerByteStorePath,
String packagesPath,
......@@ -331,7 +332,8 @@ class ResidentCompiler {
/// Binary file name is returned if compilation was successful, otherwise
/// null is returned.
Future<CompilerOutput> recompile(String mainPath, List<String> invalidatedFiles,
{String outputPath, String packagesFilePath}) async {
{@required String outputPath, String packagesFilePath}) async {
assert (outputPath != null);
if (!_controller.hasListener) {
_controller.stream.listen(_handleCompilationRequest);
}
......
......@@ -13,6 +13,7 @@ import 'base/context.dart';
import 'base/file_system.dart';
import 'base/io.dart';
import 'build_info.dart';
import 'bundle.dart';
import 'compile.dart';
import 'dart/package_map.dart';
import 'globals.dart';
......@@ -431,10 +432,13 @@ class DevFS {
Set<String> fileFilter,
@required ResidentCompiler generator,
String dillOutputPath,
@required bool trackWidgetCreation,
bool fullRestart = false,
String projectRootPath,
@required String pathToReload,
}) async {
assert(trackWidgetCreation != null);
assert(generator != null);
// Mark all entries as possibly deleted.
for (DevFSContent content in _entries.values) {
content._exists = false;
......@@ -526,7 +530,7 @@ class DevFS {
final CompilerOutput compilerOutput = await generator.recompile(
mainPath,
invalidatedFiles,
outputPath: dillOutputPath ?? fs.path.join(getBuildDirectory(), 'app.dill'),
outputPath: dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
packagesFilePath : _packagesFilePath,
);
// Don't send full kernel file that would overwrite what VM already
......
......@@ -30,13 +30,14 @@ import 'vmservice.dart';
class FlutterDevice {
FlutterDevice(this.device, {
@required bool trackWidgetCreation,
@required this.trackWidgetCreation,
this.dillOutputPath,
this.fileSystemRoots,
this.fileSystemScheme,
this.viewFilter,
ResidentCompiler generator,
}) : generator = generator ?? ResidentCompiler(
}) : assert(trackWidgetCreation != null),
generator = generator ?? ResidentCompiler(
artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
trackWidgetCreation: trackWidgetCreation,
fileSystemRoots: fileSystemRoots, fileSystemScheme: fileSystemScheme
......@@ -53,6 +54,7 @@ class FlutterDevice {
String fileSystemScheme;
StreamSubscription<String> _loggingSubscription;
final String viewFilter;
final bool trackWidgetCreation;
/// If the [reloadSources] parameter is not null the 'reloadSources' service
/// will be registered.
......@@ -390,6 +392,7 @@ class FlutterDevice {
generator: generator,
fullRestart: fullRestart,
dillOutputPath: dillOutputPath,
trackWidgetCreation: trackWidgetCreation,
projectRootPath: projectRootPath,
pathToReload: pathToReload
);
......@@ -443,6 +446,7 @@ abstract class ResidentRunner {
String _mainPath;
String get mainPath => _mainPath;
String getReloadPath({bool fullRestart}) => mainPath + (fullRestart ? '' : '.incremental') + '.dill';
AssetBundle _assetBundle;
AssetBundle get assetBundle => _assetBundle;
......
......@@ -20,6 +20,7 @@ import '../base/io.dart';
import '../base/process_manager.dart';
import '../base/terminal.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../compile.dart';
import '../dart/package_map.dart';
import '../globals.dart';
......@@ -230,7 +231,10 @@ class _Compiler {
printError('$message');
}
final String testFilePath = fs.path.join(fs.path.fromUri(projectRootDirectory), getBuildDirectory(), 'testfile.dill');
final String testFilePath = getKernelPathForTransformerOptions(
fs.path.join(fs.path.fromUri(projectRootDirectory), getBuildDirectory(), 'testfile.dill'),
trackWidgetCreation: trackWidgetCreation,
);
ResidentCompiler createCompiler() {
return ResidentCompiler(
......
......@@ -127,8 +127,10 @@ class FlutterTesterDevice extends Device {
// Build assets and perform initial compilation.
final String assetDirPath = getAssetBuildDirectory();
final String applicationKernelFilePath =
fs.path.join(getBuildDirectory(), 'flutter-tester-app.dill');
final String applicationKernelFilePath = bundle.getKernelPathForTransformerOptions(
fs.path.join(getBuildDirectory(), 'flutter-tester-app.dill'),
trackWidgetCreation: buildInfo.trackWidgetCreation,
);
await bundle.build(
mainPath: mainPath,
assetDirPath: assetDirPath,
......@@ -138,10 +140,7 @@ class FlutterTesterDevice extends Device {
);
command.add('--flutter-assets-dir=$assetDirPath');
// TODO(scheglov): Either remove the check, or make it fail earlier.
if (applicationKernelFilePath != null) {
command.add(applicationKernelFilePath);
}
command.add(applicationKernelFilePath);
try {
printTrace(command.join(' '));
......
......@@ -48,7 +48,8 @@ void main() {
))
));
final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart'
mainPath: '/path/to/main.dart',
trackWidgetCreation: false,
);
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
expect(logger.errorText, equals('\nCompiler message:\nline1\nline2\n'));
......@@ -70,7 +71,8 @@ void main() {
));
final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart'
mainPath: '/path/to/main.dart',
trackWidgetCreation: false,
);
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
expect(logger.errorText, equals('\nCompiler message:\nline1\nline2\n'));
......@@ -93,8 +95,10 @@ void main() {
))
));
final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart'
final CompilerOutput output = await kernelCompiler.compile(
sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart',
trackWidgetCreation: false,
);
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
expect(logger.errorText, equals('\nCompiler message:\nline1\nline2\n'));
......@@ -149,7 +153,9 @@ void main() {
));
final CompilerOutput output = await generator.recompile(
'/path/to/main.dart', null /* invalidatedFiles */
'/path/to/main.dart',
null /* invalidatedFiles */,
outputPath: '/build/',
);
expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
verifyNoMoreInteractions(mockFrontendServerStdIn);
......@@ -167,7 +173,9 @@ void main() {
);
final CompilerOutput output = await generator.recompile(
'/path/to/main.dart', null /* invalidatedFiles */
'/path/to/main.dart',
null, /* invalidatedFiles */
outputPath: '/build/',
);
expect(output, equals(null));
}, overrides: <Type, Generator>{
......@@ -183,7 +191,11 @@ void main() {
when(mockFrontendServer.stdout)
.thenAnswer((Invocation invocation) => streamController.stream);
streamController.add(utf8.encode('result abc\nline0\nline1\nabc /path/to/main.dart.dill 0\n'));
await generator.recompile('/path/to/main.dart', null /* invalidatedFiles */);
await generator.recompile(
'/path/to/main.dart',
null, /* invalidatedFiles */
outputPath: '/build/',
);
expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
await _recompile(streamController, generator, mockFrontendServerStdIn,
......@@ -210,7 +222,7 @@ void main() {
streamController.add(utf8.encode(
'result abc\nline0\nline1\nabc /path/to/main.dart.dill 0\n'
));
await generator.recompile('/path/to/main.dart', null /* invalidatedFiles */);
await generator.recompile('/path/to/main.dart', null /* invalidatedFiles */, outputPath: '/build/');
expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
await _recompile(streamController, generator, mockFrontendServerStdIn,
......@@ -292,7 +304,9 @@ void main() {
)));
await generator.recompile(
'/path/to/main.dart', null /* invalidatedFiles */
'/path/to/main.dart',
null, /* invalidatedFiles */
outputPath: '/build/',
).then((CompilerOutput output) {
expect(mockFrontendServerStdIn.getAndClear(),
'compile /path/to/main.dart\n');
......@@ -339,7 +353,9 @@ void main() {
// The test manages timing via completers.
generator.recompile( // ignore: unawaited_futures
'/path/to/main.dart', null /* invalidatedFiles */
'/path/to/main.dart',
null, /* invalidatedFiles */
outputPath: '/build/',
).then((CompilerOutput outputCompile) {
expect(logger.errorText,
equals('\nCompiler message:\nline1\nline2\n'));
......@@ -394,7 +410,11 @@ Future<void> _recompile(StreamController<List<int>> streamController,
scheduleMicrotask(() {
streamController.add(utf8.encode(mockCompilerOutput));
});
final CompilerOutput output = await generator.recompile(null /* mainPath */, <String>['/path/to/main.dart']);
final CompilerOutput output = await generator.recompile(
null /* mainPath */,
<String>['/path/to/main.dart'],
outputPath: '/build/',
);
expect(output.outputFilename, equals('/path/to/main.dart.dill'));
final String commands = mockFrontendServerStdIn.getAndClear();
final RegExp re = RegExp('^recompile (.*)\\n/path/to/main.dart\\n(.*)\\n\$');
......
......@@ -119,13 +119,25 @@ void main() {
devFSOperations.expectMessages(<String>['create test']);
expect(devFS.assetPathsToEvict, isEmpty);
final int bytes = await devFS.update(
int bytes = await devFS.update(
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
bytes = await devFS.update(
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: true,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill build/app.dill.track.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
......@@ -142,9 +154,10 @@ void main() {
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
......@@ -157,9 +170,10 @@ void main() {
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
......@@ -171,9 +185,10 @@ void main() {
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
......@@ -183,12 +198,41 @@ void main() {
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
// Set the last modified time to 5 seconds in the past.
updateFileModificationTime(file.path, DateTime.now(), -5);
bytes = await devFS.update(
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: true,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill build/app.dill.track.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
await file.writeAsBytes(<int>[1, 2, 3, 4, 5, 6]);
bytes = await devFS.update(
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: true,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill build/app.dill.track.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
});
......@@ -200,10 +244,11 @@ void main() {
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'deleteFile test lib/foo.txt',
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
......@@ -213,16 +258,30 @@ void main() {
testUsingContext('add new package', () async {
await _createPackage(fs, 'newpkg', 'anotherfile.txt');
final int bytes = await devFS.update(
int bytes = await devFS.update(
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
bytes = await devFS.update(
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: true,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill build/app.dill.track.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
});
......@@ -248,9 +307,10 @@ void main() {
fileFilter: fileFilter,
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, isEmpty);
expect(bytes, 22);
......@@ -266,10 +326,11 @@ void main() {
bundleDirty: true,
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test ${_inAssetBuildDirectory(fs, 'a.txt')}',
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, unorderedMatches(<String>['a.txt']));
devFS.assetPathsToEvict.clear();
......@@ -286,12 +347,13 @@ void main() {
bundleDirty: true,
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
// Expect entire asset bundle written because bundleDirty is true
devFSOperations.expectMessages(<String>[
'writeFile test ${_inAssetBuildDirectory(fs, 'a.txt')}',
'writeFile test ${_inAssetBuildDirectory(fs, 'b.txt')}',
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, unorderedMatches(<String>[
'a.txt', 'b.txt']));
......@@ -308,10 +370,11 @@ void main() {
bundle: assetBundle,
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'writeFile test ${_inAssetBuildDirectory(fs, 'c.txt')}',
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, unorderedMatches(<String>[
'c.txt']));
......@@ -328,10 +391,11 @@ void main() {
bundle: assetBundle,
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'deleteFile test ${_inAssetBuildDirectory(fs, 'c.txt')}',
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, unorderedMatches(<String>['c.txt']));
devFS.assetPathsToEvict.clear();
......@@ -348,11 +412,12 @@ void main() {
bundleDirty: true,
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
devFSOperations.expectMessages(<String>[
'deleteFile test ${_inAssetBuildDirectory(fs, 'a.txt')}',
'deleteFile test ${_inAssetBuildDirectory(fs, 'b.txt')}',
'writeFile test lib/foo.txt.dill',
'writeFile test lib/foo.txt.dill build/app.dill',
]);
expect(devFS.assetPathsToEvict, unorderedMatches(<String>[
'a.txt', 'b.txt'
......@@ -405,6 +470,7 @@ void main() {
mainPath: 'lib/foo.txt',
generator: residentCompiler,
pathToReload: 'lib/foo.txt.dill',
trackWidgetCreation: false,
);
vmService.expectMessages(<String>[
'writeFile test lib/foo.txt.dill',
......
......@@ -427,7 +427,11 @@ class MockDevFSOperations extends BasicMock implements DevFSOperations {
@override
Future<dynamic> writeFile(String fsName, Uri deviceUri, DevFSContent content) async {
messages.add('writeFile $fsName $deviceUri');
String message = 'writeFile $fsName $deviceUri';
if (content is DevFSFileContent) {
message += ' ${content.file.path}';
}
messages.add(message);
devicePathToContent[deviceUri] = content;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment