diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle index 34161320b8..79326de971 100644 --- a/packages/flutter_tools/gradle/flutter.gradle +++ b/packages/flutter_tools/gradle/flutter.gradle @@ -260,6 +260,14 @@ class FlutterPlugin implements Plugin { if (project.hasProperty('preview-dart-2')) { previewDart2Value = project.property('preview-dart-2') } + String[] fileSystemRootsValue = null + if (project.hasProperty('filesystem-roots')) { + fileSystemRootsValue = project.property('filesystem-roots').split('\\|') + } + String fileSystemSchemeValue = null + if (project.hasProperty('filesystem-scheme')) { + fileSystemSchemeValue = project.property('filesystem-scheme') + } Boolean trackWidgetCreationValue = false if (project.hasProperty('track-widget-creation')) { trackWidgetCreationValue = project.property('track-widget-creation') @@ -302,6 +310,8 @@ class FlutterPlugin implements Plugin { localEngineSrcPath this.localEngineSrcPath targetPath target previewDart2 previewDart2Value + fileSystemRoots fileSystemRootsValue + fileSystemScheme fileSystemSchemeValue trackWidgetCreation trackWidgetCreationValue preferSharedLibrary preferSharedLibraryValue targetPlatform targetPlatformValue @@ -320,6 +330,8 @@ class FlutterPlugin implements Plugin { localEngineSrcPath this.localEngineSrcPath targetPath target previewDart2 previewDart2Value + fileSystemRoots fileSystemRootsValue + fileSystemScheme fileSystemSchemeValue trackWidgetCreation trackWidgetCreationValue preferSharedLibrary preferSharedLibraryValue targetPlatform targetPlatformValue @@ -357,6 +369,10 @@ abstract class BaseFlutterTask extends DefaultTask { @Optional @Input Boolean previewDart2 @Optional @Input + String[] fileSystemRoots + @Optional @Input + String fileSystemScheme + @Optional @Input Boolean trackWidgetCreation @Optional @Input Boolean preferSharedLibrary @@ -401,8 +417,8 @@ abstract class BaseFlutterTask extends DefaultTask { if (previewDart2) { args "--preview-dart-2" } else { - args "--no-preview-dart-2" - } + args "--no-preview-dart-2" + } if (trackWidgetCreation) { args "--track-widget-creation" } @@ -436,7 +452,15 @@ abstract class BaseFlutterTask extends DefaultTask { args "--preview-dart-2" } else { args "--no-preview-dart-2" - } + } + if (fileSystemRoots != null) { + for (root in fileSystemRoots) { + args "--filesystem-root", root + } + } + if (fileSystemScheme != null) { + args "--filesystem-scheme", fileSystemScheme + } if (trackWidgetCreation) { args "--track-widget-creation" } diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart index 4d2d883d34..4f450e1212 100644 --- a/packages/flutter_tools/lib/src/android/gradle.dart +++ b/packages/flutter_tools/lib/src/android/gradle.dart @@ -303,6 +303,10 @@ Future _buildGradleProjectV2(String gradle, BuildInfo buildInfo, String ta command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}'); if (buildInfo.extraGenSnapshotOptions != null) command.add('-Pextra-gen-snapshot-options=${buildInfo.extraGenSnapshotOptions}'); + if (buildInfo.fileSystemRoots != null && buildInfo.fileSystemRoots.isNotEmpty) + command.add('-Pfilesystem-roots=${buildInfo.fileSystemRoots.join('|')}'); + if (buildInfo.fileSystemScheme != null) + command.add('-Pfilesystem-scheme=${buildInfo.fileSystemScheme}'); } if (buildInfo.preferSharedLibrary && androidSdk.ndkCompiler != null) { command.add('-Pprefer-shared-library=true'); diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart index c86d5b73bd..2f9cabf891 100644 --- a/packages/flutter_tools/lib/src/build_info.dart +++ b/packages/flutter_tools/lib/src/build_info.dart @@ -17,6 +17,8 @@ class BuildInfo { this.extraGenSnapshotOptions, this.preferSharedLibrary, this.targetPlatform, + this.fileSystemRoots, + this.fileSystemScheme, }); final BuildMode mode; @@ -32,6 +34,9 @@ class BuildInfo { /// Whether build should be done using Dart2 Frontend parser. final bool previewDart2; + final List fileSystemRoots; + final String fileSystemScheme; + /// Whether the build should track widget creation locations. final bool trackWidgetCreation; diff --git a/packages/flutter_tools/lib/src/commands/build_flx.dart b/packages/flutter_tools/lib/src/commands/build_flx.dart index c763369cad..8a849cae92 100644 --- a/packages/flutter_tools/lib/src/commands/build_flx.dart +++ b/packages/flutter_tools/lib/src/commands/build_flx.dart @@ -35,7 +35,18 @@ class BuildFlxCommand extends BuildSubCommand { ..addFlag('report-licensed-packages', help: 'Whether to report the names of all the packages that are included ' 'in the application\'s LICENSE file.', - defaultsTo: false); + defaultsTo: false) + ..addMultiOption('filesystem-root', + hide: !verboseHelp, + help: 'Specify the path, that is used as root in a virtual file system\n' + 'for compilation. Input file name should be specified as Uri in\n' + 'filesystem-scheme scheme. Use only in Dart 2 mode.\n' + 'Requires --output-dill option to be explicitly specified.\n') + ..addOption('filesystem-scheme', + defaultsTo: 'org-dartlang-root', + hide: !verboseHelp, + help: 'Specify the scheme that is used for virtual file system used in\n' + 'compilation. See more details on filesystem-root option.\n'); usesPubOption(); } @@ -67,6 +78,8 @@ class BuildFlxCommand extends BuildSubCommand { precompiledSnapshot: argResults['precompiled'], reportLicensedPackages: argResults['report-licensed-packages'], trackWidgetCreation: argResults['track-widget-creation'], + fileSystemScheme: argResults['filesystem-scheme'], + fileSystemRoots: argResults['filesystem-root'], ); } } diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index f4eebbdec1..cb817a4dc8 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -172,7 +172,18 @@ class RunCommand extends RunCommandBase { help: 'Specify the path to frontend server output kernel file.', ) ..addOption(FlutterOptions.kExtraFrontEndOptions, hide: true) - ..addOption(FlutterOptions.kExtraGenSnapshotOptions, hide: true); + ..addOption(FlutterOptions.kExtraGenSnapshotOptions, hide: true) + ..addMultiOption('filesystem-root', + hide: !verboseHelp, + help: 'Specify the path, that is used as root in a virtual file system\n' + 'for compilation. Input file name should be specified as Uri in\n' + 'filesystem-scheme scheme. Use only in Dart 2 mode.\n' + 'Requires --output-dill option to be explicitly specified.\n') + ..addOption('filesystem-scheme', + defaultsTo: 'org-dartlang-root', + hide: !verboseHelp, + help: 'Specify the scheme that is used for virtual file system used in\n' + 'compilation. See more details on filesystem-root option.\n'); } List devices; @@ -345,6 +356,8 @@ class RunCommand extends RunCommandBase { previewDart2: argResults['preview-dart-2'], trackWidgetCreation: argResults['track-widget-creation'], dillOutputPath: argResults['output-dill'], + fileSystemRoots: argResults['filesystem-root'], + fileSystemScheme: argResults['filesystem-scheme'], ); }).toList(); diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart index 7c15e91f68..be6623441b 100644 --- a/packages/flutter_tools/lib/src/compile.dart +++ b/packages/flutter_tools/lib/src/compile.dart @@ -55,7 +55,9 @@ Future compile( bool trackWidgetCreation: false, List extraFrontEndOptions, String incrementalCompilerByteStorePath, - String packagesPath}) async { + String packagesPath, + List fileSystemRoots, + String fileSystemScheme}) async { final String frontendServer = artifacts.getArtifactPath( Artifact.frontendServerSnapshotForEngineDartSdk ); @@ -93,9 +95,17 @@ Future compile( if (outputFilePath != null) { command.addAll(['--output-dill', outputFilePath]); } - if (depFilePath != null) { + if (depFilePath != null && (fileSystemRoots == null || fileSystemRoots.isEmpty)) { command.addAll(['--depfile', depFilePath]); } + if (fileSystemRoots != null) { + for (String root in fileSystemRoots) { + command.addAll(['--filesystem-root', root]); + } + } + if (fileSystemScheme != null) { + command.addAll(['--filesystem-scheme', fileSystemScheme]); + } if (extraFrontEndOptions != null) command.addAll(extraFrontEndOptions); @@ -127,10 +137,13 @@ Future compile( /// restarts the Flutter app. class ResidentCompiler { ResidentCompiler(this._sdkRoot, {bool trackWidgetCreation: false, - String packagesPath, CompilerMessageConsumer compilerMessageConsumer: printError}) + String packagesPath, List fileSystemRoots, String fileSystemScheme , + CompilerMessageConsumer compilerMessageConsumer: printError}) : assert(_sdkRoot != null), _trackWidgetCreation = trackWidgetCreation, _packagesPath = packagesPath, + _fileSystemRoots = fileSystemRoots, + _fileSystemScheme = fileSystemScheme, stdoutHandler = new _StdoutHandler(consumer: compilerMessageConsumer) { // This is a URI, not a file path, so the forward slash is correct even on Windows. if (!_sdkRoot.endsWith('/')) @@ -139,6 +152,8 @@ class ResidentCompiler { final bool _trackWidgetCreation; final String _packagesPath; + final List _fileSystemRoots; + final String _fileSystemScheme; String _sdkRoot; Process _server; final _StdoutHandler stdoutHandler; @@ -157,11 +172,13 @@ class ResidentCompiler { // First time recompile is called we actually have to compile the app from // scratch ignoring list of invalidated files. if (_server == null) - return _compile(mainPath, outputPath, packagesFilePath); + return _compile(_mapFilename(mainPath), outputPath, _mapFilename(packagesFilePath)); final String inputKey = new Uuid().generateV4(); - _server.stdin.writeln('recompile ${mainPath != null ? mainPath + " ": ""}$inputKey'); - invalidatedFiles.forEach(_server.stdin.writeln); + _server.stdin.writeln('recompile ${mainPath != null ? _mapFilename(mainPath) + " ": ""}$inputKey'); + for (String filePath in invalidatedFiles) { + _server.stdin.writeln(_mapFilename(filePath)); + } _server.stdin.writeln(inputKey); return stdoutHandler.outputFilename.future; @@ -192,6 +209,14 @@ class ResidentCompiler { if (_packagesPath != null) { args.addAll(['--packages', _packagesPath]); } + if (_fileSystemRoots != null) { + for (String root in _fileSystemRoots) { + args.addAll(['--filesystem-root', root]); + } + } + if (_fileSystemScheme != null) { + args.addAll(['--filesystem-scheme', _fileSystemScheme]); + } _server = await processManager.start(args); _server.stdout .transform(utf8.decoder) @@ -238,6 +263,19 @@ class ResidentCompiler { _server.stdin.writeln('reset'); } + String _mapFilename(String filename) { + if (_fileSystemRoots != null) { + for (String root in _fileSystemRoots) { + if (filename.startsWith(root)) { + return new Uri( + scheme: _fileSystemScheme, path: filename.substring(root.length)) + .toString(); + } + } + } + return filename; + } + Future shutdown() { _server.kill(); return _server.exitCode; diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart index 4af38acc05..40446d1717 100644 --- a/packages/flutter_tools/lib/src/devfs.dart +++ b/packages/flutter_tools/lib/src/devfs.dart @@ -487,7 +487,7 @@ class DevFS { final DevFSContent content = dirtyEntries[uri]; if (content is DevFSFileContent) { filesUris.add(uri); - invalidatedFiles.add(content.file.uri.toString()); + invalidatedFiles.add(content.file.path); numBytes -= content.size; } } diff --git a/packages/flutter_tools/lib/src/flx.dart b/packages/flutter_tools/lib/src/flx.dart index b7b8236e88..f02ad9a4ab 100644 --- a/packages/flutter_tools/lib/src/flx.dart +++ b/packages/flutter_tools/lib/src/flx.dart @@ -44,6 +44,8 @@ Future build({ bool precompiledSnapshot: false, bool reportLicensedPackages: false, bool trackWidgetCreation: false, + List fileSystemRoots, + String fileSystemScheme, }) async { outputPath ??= defaultFlxOutputPath; snapshotPath ??= defaultSnapshotPath; @@ -82,6 +84,9 @@ Future build({ outputFilePath: applicationKernelFilePath, depFilePath: depfilePath, trackWidgetCreation: trackWidgetCreation, + fileSystemRoots: fileSystemRoots, + fileSystemScheme: fileSystemScheme, + packagesPath: packagesPath, ); if (kernelBinaryFilename == null) { throwToolExit('Compiler terminated unexpectedly on $mainPath'); diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 3abc1525ad..835fe22761 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -36,6 +36,8 @@ class FlutterDevice { ApplicationPackage package; ResidentCompiler generator; String dillOutputPath; + List fileSystemRoots; + String fileSystemScheme; StreamSubscription _loggingSubscription; @@ -43,11 +45,14 @@ class FlutterDevice { @required bool previewDart2, @required bool trackWidgetCreation, this.dillOutputPath, + this.fileSystemRoots, + this.fileSystemScheme, }) { if (previewDart2) { generator = new ResidentCompiler( artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath), trackWidgetCreation: trackWidgetCreation, + fileSystemRoots: fileSystemRoots, fileSystemScheme: fileSystemScheme ); } } diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index db0e1193ac..a84708c8b5 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -392,7 +392,7 @@ class HotRunner extends ResidentRunner { // We are now running from source. _runningFromSnapshot = false; final String launchPath = debuggingOptions.buildInfo.previewDart2 - ? dillOutputPath ?? mainPath + '.dill' + ? mainPath + '.dill' : mainPath; await _launchFromDevFS(launchPath); restartTimer.stop(); diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index cd50e616d2..c65e9a7ac0 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -61,6 +61,8 @@ class FlutterCommandResult { class FlutterOptions { static const String kExtraFrontEndOptions = 'extra-front-end-options'; static const String kExtraGenSnapshotOptions = 'extra-gen-snapshot-options'; + static const String kFileSystemRoot = 'filesystem-root'; + static const String kFileSystemScheme = 'filesystem-scheme'; } abstract class FlutterCommand extends Command { @@ -194,7 +196,12 @@ abstract class FlutterCommand extends Command { preferSharedLibrary: argParser.options.containsKey('prefer-shared-library') ? argResults['prefer-shared-library'] : false, - targetPlatform: targetPlatform); + targetPlatform: targetPlatform, + fileSystemRoots: argParser.options.containsKey(FlutterOptions.kFileSystemRoot) + ? argResults[FlutterOptions.kFileSystemRoot] : null, + fileSystemScheme: argParser.options.containsKey(FlutterOptions.kFileSystemScheme) + ? argResults[FlutterOptions.kFileSystemScheme] : null, + ); } void setupApplicationPackages() { diff --git a/packages/flutter_tools/test/compile_test.dart b/packages/flutter_tools/test/compile_test.dart index 45e0bb9e67..3eb6c4d19b 100644 --- a/packages/flutter_tools/test/compile_test.dart +++ b/packages/flutter_tools/test/compile_test.dart @@ -227,7 +227,7 @@ Future _recompile(StreamController> streamController, final String output = await generator.recompile(null /* mainPath */, ['/path/to/main.dart']); expect(output, equals('/path/to/main.dart.dill')); final String commands = mockFrontendServerStdIn.getAndClear(); - final RegExp re = new RegExp(r'^recompile (.*)\n/path/to/main.dart\n(.*)\n$'); + final RegExp re = new RegExp('^recompile (.*)\\n/path/to/main.dart\\n(.*)\\n\$'); expect(commands, matches(re)); final Match match = re.firstMatch(commands); expect(match[1] == match[2], isTrue);