mirror of
https://github.com/flutter/flutter
synced 2024-08-27 03:50:33 +00:00
select ResidentCompiler during FlutterDevice initialization (#28603)
This commit is contained in:
parent
df465c7718
commit
a2d349c4c1
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -32,6 +32,9 @@
|
|||
/packages/flutter/coverage/
|
||||
version
|
||||
|
||||
# packages file containing multi-root paths
|
||||
.packages.generated
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
|
|
|
@ -17,7 +17,7 @@ class ExampleWidget extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _ExampleWidgetState extends State<ExampleWidget> {
|
||||
String _message = '';
|
||||
bool _pressed = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -30,14 +30,21 @@ class _ExampleWidgetState extends State<ExampleWidget> {
|
|||
child: const Text('Press Button, Get Coffee'),
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
_message = generated.message;
|
||||
_pressed = true;
|
||||
});
|
||||
},
|
||||
),
|
||||
Text(_message),
|
||||
_pressed ? GeneratedWidget() : const SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GeneratedWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(generated.message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
final String message = 'Thanks for using PourOverSupremeFiesta by Coffee by Flutter Inc.';
|
||||
String get message => 'Thanks for using PourOverSupremeFiesta by Coffee by Flutter Inc.';
|
||||
|
|
11
dev/integration_tests/codegen/test/example_test.dart
Normal file
11
dev/integration_tests/codegen/test/example_test.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
import 'package:codegen/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('can reference generated code', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(MaterialApp(home: GeneratedWidget()));
|
||||
|
||||
expect(find.text('Thanks for using PourOverSupremeFiesta by Coffee by Flutter Inc.'), findsOneWidget);
|
||||
});
|
||||
}
|
|
@ -24,4 +24,4 @@ void main() {
|
|||
final String fullMessage = await driver.getText(find.text(message));
|
||||
expect(fullMessage, message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,25 +89,18 @@ class FlutterKernelBuilder implements Builder {
|
|||
return;
|
||||
}
|
||||
final AssetId outputId = buildStep.inputId.changeExtension(_kFlutterDillOutputExtension);
|
||||
final AssetId packagesOutputId = buildStep.inputId.changeExtension(_kPackagesExtension);
|
||||
|
||||
// Create a scratch space file that can be read/written by the frontend server.
|
||||
// It is okay to hard-code these file names because we will copy them back
|
||||
// from the temp directory at the end of the build step.
|
||||
final Directory tempDirecory = await Directory.systemTemp.createTemp('_flutter_build');
|
||||
final File packagesFile = File(path.join(tempDirecory.path, _kPackagesExtension));
|
||||
final Directory projectDir = File(packagesPath).parent;
|
||||
final String packagesFilePath = path.join(projectDir.path, '.packages.generated');
|
||||
final File outputFile = File(path.join(tempDirecory.path, 'main.app.dill'));
|
||||
await outputFile.create();
|
||||
await packagesFile.create();
|
||||
|
||||
final Directory projectDir = File(packagesPath).parent;
|
||||
final String packageName = buildStep.inputId.package;
|
||||
final String oldPackagesContents = await File(packagesPath).readAsString();
|
||||
// Note: currently we only replace the root package with a multiroot
|
||||
// scheme. To support codegen on arbitrary packages we will need to do
|
||||
// this for each dependency.
|
||||
final String newPackagesContents = oldPackagesContents.replaceFirst('$packageName:lib/', '$packageName:$_kMultirootScheme:/');
|
||||
await packagesFile.writeAsString(newPackagesContents);
|
||||
|
||||
String absoluteMainPath;
|
||||
if (path.isAbsolute(mainPath)) {
|
||||
absoluteMainPath = mainPath;
|
||||
|
@ -143,7 +136,7 @@ class FlutterKernelBuilder implements Builder {
|
|||
final String normalRoot = path.join(projectDir.absolute.path, 'lib${Platform.pathSeparator}');
|
||||
arguments.addAll(<String>[
|
||||
'--packages',
|
||||
Uri.file(packagesFile.path).toString(),
|
||||
packagesFilePath,
|
||||
'--output-dill',
|
||||
outputFile.path,
|
||||
'--filesystem-root',
|
||||
|
@ -158,7 +151,7 @@ class FlutterKernelBuilder implements Builder {
|
|||
}
|
||||
final Uri mainUri = _PackageUriMapper.findUri(
|
||||
absoluteMainPath,
|
||||
packagesFile.path,
|
||||
packagesFilePath,
|
||||
_kMultirootScheme,
|
||||
<String>[normalRoot, generatedRoot],
|
||||
);
|
||||
|
@ -178,7 +171,6 @@ class FlutterKernelBuilder implements Builder {
|
|||
await server.exitCode;
|
||||
await _stdoutHandler.compilerOutput.future;
|
||||
await buildStep.writeAsBytes(outputId, await outputFile.readAsBytes());
|
||||
await buildStep.writeAsBytes(packagesOutputId, await packagesFile.readAsBytes());
|
||||
} catch (err, stackTrace) {
|
||||
log.shout('frontend server failed to start: $err, $stackTrace');
|
||||
}
|
||||
|
|
|
@ -22,12 +22,18 @@ import '../base/logger.dart';
|
|||
import '../base/process_manager.dart';
|
||||
import '../codegen.dart';
|
||||
import '../convert.dart';
|
||||
import '../dart/package_map.dart';
|
||||
import '../dart/pub.dart';
|
||||
import '../globals.dart';
|
||||
import '../project.dart';
|
||||
import '../resident_runner.dart';
|
||||
import 'build_script_generator.dart';
|
||||
|
||||
// Arbitrarily choosen multi-root file scheme. This is used to configure the
|
||||
// frontend_server to resolve a package uri to multiple filesystem directories.
|
||||
// In this case, the source directory and a generated directory.
|
||||
const String _kMultirootScheme = 'org-dartlang-app';
|
||||
|
||||
/// A wrapper for a build_runner process which delegates to a generated
|
||||
/// build script.
|
||||
///
|
||||
|
@ -37,7 +43,7 @@ class BuildRunner extends CodeGenerator {
|
|||
const BuildRunner();
|
||||
|
||||
@override
|
||||
Future<CodeGenerationResult> build({
|
||||
Future<CodeGenerationResult> build(FlutterProject flutterProject, {
|
||||
@required String mainPath,
|
||||
@required bool aot,
|
||||
@required bool linkPlatformKernelIn,
|
||||
|
@ -46,8 +52,7 @@ class BuildRunner extends CodeGenerator {
|
|||
List<String> extraFrontEndOptions = const <String>[],
|
||||
bool disableKernelGeneration = false,
|
||||
}) async {
|
||||
await generateBuildScript();
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
await generateBuildScript(flutterProject);
|
||||
final String frontendServerPath = artifacts.getArtifactPath(
|
||||
Artifact.frontendServerSnapshotForEngineDartSdk
|
||||
);
|
||||
|
@ -99,7 +104,7 @@ class BuildRunner extends CodeGenerator {
|
|||
status.stop();
|
||||
}
|
||||
if (disableKernelGeneration) {
|
||||
return const CodeGenerationResult(null, null);
|
||||
return const CodeGenerationResult(null);
|
||||
}
|
||||
/// We don't check for this above because it might be generated for the
|
||||
/// first time by invoking the build.
|
||||
|
@ -114,21 +119,17 @@ class BuildRunner extends CodeGenerator {
|
|||
throw Exception('build_runner cannot find generated directory');
|
||||
}
|
||||
final String relativeMain = fs.path.relative(mainPath, from: flutterProject.directory.path);
|
||||
final File packagesFile = fs.file(
|
||||
fs.path.join(generatedDirectory.path, fs.path.setExtension(relativeMain, '.packages'))
|
||||
);
|
||||
final File dillFile = fs.file(
|
||||
fs.path.join(generatedDirectory.path, fs.path.setExtension(relativeMain, '.app.dill'))
|
||||
);
|
||||
if (!packagesFile.existsSync() || !dillFile.existsSync()) {
|
||||
if (!dillFile.existsSync()) {
|
||||
throw Exception('build_runner did not produce output at expected location: ${dillFile.path} missing');
|
||||
}
|
||||
return CodeGenerationResult(packagesFile, dillFile);
|
||||
return CodeGenerationResult(dillFile);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> generateBuildScript() async {
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
Future<void> generateBuildScript(FlutterProject flutterProject) async {
|
||||
final Directory entrypointDirectory = fs.directory(fs.path.join(flutterProject.dartTool.path, 'build', 'entrypoint'));
|
||||
final Directory generatedDirectory = fs.directory(fs.path.join(flutterProject.dartTool.path, 'flutter_tool'));
|
||||
final File buildScript = entrypointDirectory.childFile('build.dart');
|
||||
|
@ -180,7 +181,6 @@ class BuildRunner extends CodeGenerator {
|
|||
stringBuffer.writeln(' flutter_build:');
|
||||
stringBuffer.writeln(' sdk: flutter');
|
||||
syntheticPubspec.writeAsStringSync(stringBuffer.toString());
|
||||
|
||||
await pubGet(
|
||||
context: PubContext.pubGet,
|
||||
directory: generatedDirectory.path,
|
||||
|
@ -210,7 +210,7 @@ class BuildRunner extends CodeGenerator {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<CodegenDaemon> daemon({
|
||||
Future<CodegenDaemon> daemon(FlutterProject flutterProject, {
|
||||
String mainPath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool targetProductVm = false,
|
||||
|
@ -218,8 +218,8 @@ class BuildRunner extends CodeGenerator {
|
|||
List<String> extraFrontEndOptions = const <String> [],
|
||||
}) async {
|
||||
mainPath ??= findMainDartFile();
|
||||
await generateBuildScript();
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
await generateBuildScript(flutterProject);
|
||||
_generatePackages(flutterProject);
|
||||
final String frontendServerPath = artifacts.getArtifactPath(
|
||||
Artifact.frontendServerSnapshotForEngineDartSdk
|
||||
);
|
||||
|
@ -265,19 +265,28 @@ class BuildRunner extends CodeGenerator {
|
|||
builder.target = flutterProject.manifest.appName;
|
||||
}));
|
||||
final String relativeMain = fs.path.relative(mainPath, from: flutterProject.directory.path);
|
||||
final File generatedPackagesFile = fs.file(fs.path.join(flutterProject.generated.path, fs.path.setExtension(relativeMain, '.packages')));
|
||||
final File generatedDillFile = fs.file(fs.path.join(flutterProject.generated.path, fs.path.setExtension(relativeMain, '.app.dill')));
|
||||
return _BuildRunnerCodegenDaemon(buildDaemonClient, generatedPackagesFile, generatedDillFile);
|
||||
return _BuildRunnerCodegenDaemon(buildDaemonClient, generatedDillFile);
|
||||
}
|
||||
|
||||
// Create generated packages file which adds a multi-root scheme to the user's
|
||||
// project directory. Currently we only replace the root package with a multiroot
|
||||
// scheme. To support codegen on arbitrary packages we would need to do
|
||||
// this for each dependency.
|
||||
void _generatePackages(FlutterProject flutterProject) {
|
||||
final String oldPackagesContents = fs.file(PackageMap.globalPackagesPath).readAsStringSync();
|
||||
final String appName = flutterProject.manifest.appName;
|
||||
final String newPackagesContents = oldPackagesContents.replaceFirst('$appName:lib/', '$appName:$_kMultirootScheme:/');
|
||||
final String generatedPackagesPath = fs.path.setExtension(PackageMap.globalPackagesPath, '.generated');
|
||||
fs.file(generatedPackagesPath).writeAsStringSync(newPackagesContents);
|
||||
}
|
||||
}
|
||||
|
||||
class _BuildRunnerCodegenDaemon implements CodegenDaemon {
|
||||
_BuildRunnerCodegenDaemon(this.buildDaemonClient, this.packagesFile, this.dillFile);
|
||||
_BuildRunnerCodegenDaemon(this.buildDaemonClient, this.dillFile);
|
||||
|
||||
final BuildDaemonClient buildDaemonClient;
|
||||
@override
|
||||
final File packagesFile;
|
||||
@override
|
||||
final File dillFile;
|
||||
@override
|
||||
CodegenStatus get lastStatus => _lastStatus;
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'base/context.dart';
|
|||
import 'base/file_system.dart';
|
||||
import 'base/platform.dart';
|
||||
import 'compile.dart';
|
||||
import 'dart/package_map.dart';
|
||||
import 'globals.dart';
|
||||
import 'project.dart';
|
||||
|
||||
|
@ -44,8 +45,9 @@ abstract class CodeGenerator {
|
|||
const CodeGenerator();
|
||||
|
||||
/// Run a partial build include code generators but not kernel.
|
||||
Future<void> generate({@required String mainPath}) async {
|
||||
Future<void> generate(FlutterProject flutterProject, {@required String mainPath}) async {
|
||||
await build(
|
||||
flutterProject,
|
||||
mainPath: mainPath,
|
||||
aot: false,
|
||||
linkPlatformKernelIn: false,
|
||||
|
@ -59,7 +61,7 @@ abstract class CodeGenerator {
|
|||
///
|
||||
/// The defines of the build command are the arguments required in the
|
||||
/// flutter_build kernel builder.
|
||||
Future<CodeGenerationResult> build({
|
||||
Future<CodeGenerationResult> build(FlutterProject flutterProject, {
|
||||
@required String mainPath,
|
||||
@required bool aot,
|
||||
@required bool linkPlatformKernelIn,
|
||||
|
@ -73,7 +75,7 @@ abstract class CodeGenerator {
|
|||
///
|
||||
/// The defines of the daemon command are the arguments required in the
|
||||
/// flutter_build kernel builder.
|
||||
Future<CodegenDaemon> daemon({
|
||||
Future<CodegenDaemon> daemon(FlutterProject flutterProject, {
|
||||
@required String mainPath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool targetProductVm = false,
|
||||
|
@ -83,14 +85,14 @@ abstract class CodeGenerator {
|
|||
|
||||
// Generates a synthetic package under .dart_tool/flutter_tool which is in turn
|
||||
// used to generate a build script.
|
||||
Future<void> generateBuildScript();
|
||||
Future<void> generateBuildScript(FlutterProject flutterProject);
|
||||
}
|
||||
|
||||
class UnsupportedCodeGenerator extends CodeGenerator {
|
||||
const UnsupportedCodeGenerator();
|
||||
|
||||
@override
|
||||
Future<CodeGenerationResult> build({
|
||||
Future<CodeGenerationResult> build(FlutterProject flutterProject, {
|
||||
String mainPath,
|
||||
bool aot,
|
||||
bool linkPlatformKernelIn,
|
||||
|
@ -103,12 +105,12 @@ class UnsupportedCodeGenerator extends CodeGenerator {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> generateBuildScript() {
|
||||
Future<void> generateBuildScript(FlutterProject flutterProject) {
|
||||
throw UnsupportedError('build_runner is not currently supported.');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CodegenDaemon> daemon({
|
||||
Future<CodegenDaemon> daemon(FlutterProject flutterProject, {
|
||||
String mainPath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool targetProductVm = false,
|
||||
|
@ -128,8 +130,6 @@ abstract class CodegenDaemon {
|
|||
/// Starts a new build.
|
||||
void startBuild();
|
||||
|
||||
File get packagesFile;
|
||||
|
||||
File get dillFile;
|
||||
}
|
||||
|
||||
|
@ -137,9 +137,8 @@ abstract class CodegenDaemon {
|
|||
///
|
||||
/// If no dill or packages file is generated, they will be null.
|
||||
class CodeGenerationResult {
|
||||
const CodeGenerationResult(this.packagesFile, this.dillFile);
|
||||
const CodeGenerationResult(this.dillFile);
|
||||
|
||||
final File packagesFile;
|
||||
final File dillFile;
|
||||
}
|
||||
|
||||
|
@ -176,8 +175,10 @@ class CodeGeneratingKernelCompiler implements KernelCompiler {
|
|||
'sdkRoot, packagesPath are not supported when using the experimental '
|
||||
'build* pipeline');
|
||||
}
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
try {
|
||||
final CodeGenerationResult buildResult = await codeGenerator.build(
|
||||
flutterProject,
|
||||
aot: aot,
|
||||
linkPlatformKernelIn: linkPlatformKernelIn,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
|
@ -206,13 +207,16 @@ class CodeGeneratingResidentCompiler implements ResidentCompiler {
|
|||
/// Creates a new [ResidentCompiler] and configures a [BuildDaemonClient] to
|
||||
/// run builds.
|
||||
static Future<CodeGeneratingResidentCompiler> create({
|
||||
@required String mainPath,
|
||||
@required FlutterProject flutterProject,
|
||||
String mainPath,
|
||||
bool trackWidgetCreation = false,
|
||||
CompilerMessageConsumer compilerMessageConsumer = printError,
|
||||
bool unsafePackageSerialization = false,
|
||||
String outputPath,
|
||||
String initializeFromDill,
|
||||
}) async {
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
final CodegenDaemon codegenDaemon = await codeGenerator.daemon(
|
||||
flutterProject,
|
||||
extraFrontEndOptions: <String>[],
|
||||
linkPlatformKernelIn: false,
|
||||
mainPath: mainPath,
|
||||
|
@ -221,22 +225,23 @@ class CodeGeneratingResidentCompiler implements ResidentCompiler {
|
|||
);
|
||||
codegenDaemon.startBuild();
|
||||
final CodegenStatus status = await codegenDaemon.buildResults.firstWhere((CodegenStatus status) {
|
||||
return status ==CodegenStatus.Succeeded || status == CodegenStatus.Failed;
|
||||
return status == CodegenStatus.Succeeded || status == CodegenStatus.Failed;
|
||||
});
|
||||
if (status == CodegenStatus.Failed) {
|
||||
printError('Codegeneration failed, halting build.');
|
||||
printError('Code generation failed, build may have compile errors');
|
||||
}
|
||||
final ResidentCompiler residentCompiler = ResidentCompiler(
|
||||
artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
packagesPath: codegenDaemon.packagesFile.path,
|
||||
packagesPath: PackageMap.globalGeneratedPackagesPath,
|
||||
fileSystemRoots: <String>[
|
||||
fs.path.join(flutterProject.generated.absolute.path, 'lib${platform.pathSeparator}'),
|
||||
fs.path.join(flutterProject.generated.path, 'lib${platform.pathSeparator}'),
|
||||
fs.path.join(flutterProject.directory.path, 'lib${platform.pathSeparator}'),
|
||||
],
|
||||
fileSystemScheme: _kMultiRootScheme,
|
||||
targetModel: TargetModel.flutter,
|
||||
unsafePackageSerialization: unsafePackageSerialization,
|
||||
initializeFromDill: initializeFromDill,
|
||||
);
|
||||
return CodeGeneratingResidentCompiler._(residentCompiler, codegenDaemon);
|
||||
}
|
||||
|
@ -274,7 +279,7 @@ class CodeGeneratingResidentCompiler implements ResidentCompiler {
|
|||
mainPath,
|
||||
invalidatedFiles,
|
||||
outputPath: outputPath,
|
||||
packagesFilePath: _codegenDaemon.packagesFile.path,
|
||||
packagesFilePath: PackageMap.globalGeneratedPackagesPath,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -205,13 +205,14 @@ class AttachCommand extends FlutterCommand {
|
|||
}
|
||||
try {
|
||||
final bool useHot = getBuildInfo().isDebug;
|
||||
final FlutterDevice flutterDevice = FlutterDevice(
|
||||
final FlutterDevice flutterDevice = await FlutterDevice.create(
|
||||
device,
|
||||
trackWidgetCreation: false,
|
||||
dillOutputPath: argResults['output-dill'],
|
||||
fileSystemRoots: argResults['filesystem-root'],
|
||||
fileSystemScheme: argResults['filesystem-scheme'],
|
||||
viewFilter: argResults['isolate-filter'],
|
||||
target: argResults['target'],
|
||||
targetModel: TargetModel(argResults['target-model']),
|
||||
);
|
||||
flutterDevice.observatoryUris = <Uri>[ observatoryUri ];
|
||||
|
|
|
@ -346,11 +346,12 @@ class AppDomain extends Domain {
|
|||
final Directory cwd = fs.currentDirectory;
|
||||
fs.currentDirectory = fs.directory(projectDirectory);
|
||||
|
||||
final FlutterDevice flutterDevice = FlutterDevice(
|
||||
final FlutterDevice flutterDevice = await FlutterDevice.create(
|
||||
device,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
dillOutputPath: dillOutputPath,
|
||||
viewFilter: isolateFilter,
|
||||
target: target,
|
||||
);
|
||||
|
||||
ResidentRunner runner;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import '../base/common.dart';
|
||||
import '../codegen.dart';
|
||||
import '../project.dart';
|
||||
import '../runner/flutter_command.dart';
|
||||
|
||||
class GenerateCommand extends FlutterCommand {
|
||||
|
@ -24,7 +25,8 @@ class GenerateCommand extends FlutterCommand {
|
|||
if (!experimentalBuildEnabled) {
|
||||
throwToolExit('FLUTTER_EXPERIMENTAL_BUILD is not enabled, codegen is unsupported.');
|
||||
}
|
||||
await codeGenerator.generate(mainPath: argResults['target']);
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
await codeGenerator.generate(flutterProject, mainPath: argResults['target']);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ import '../base/time.dart';
|
|||
import '../base/utils.dart';
|
||||
import '../build_info.dart';
|
||||
import '../cache.dart';
|
||||
import '../codegen.dart';
|
||||
import '../compile.dart';
|
||||
import '../device.dart';
|
||||
import '../globals.dart';
|
||||
import '../ios/mac.dart';
|
||||
|
@ -346,13 +344,9 @@ class RunCommand extends RunCommandBase {
|
|||
argResults[FlutterOptions.kEnableExperiment].isNotEmpty) {
|
||||
expFlags = argResults[FlutterOptions.kEnableExperiment];
|
||||
}
|
||||
|
||||
ResidentCompiler residentCompiler;
|
||||
if (experimentalBuildEnabled) {
|
||||
residentCompiler = await CodeGeneratingResidentCompiler.create(mainPath: argResults['target']);
|
||||
}
|
||||
final List<FlutterDevice> flutterDevices = devices.map<FlutterDevice>((Device device) {
|
||||
return FlutterDevice(
|
||||
final List<FlutterDevice> flutterDevices = <FlutterDevice>[];
|
||||
for (Device device in devices) {
|
||||
final FlutterDevice flutterDevice = await FlutterDevice.create(
|
||||
device,
|
||||
trackWidgetCreation: argResults['track-widget-creation'],
|
||||
dillOutputPath: argResults['output-dill'],
|
||||
|
@ -360,9 +354,10 @@ class RunCommand extends RunCommandBase {
|
|||
fileSystemScheme: argResults['filesystem-scheme'],
|
||||
viewFilter: argResults['isolate-filter'],
|
||||
experimentalFlags: expFlags,
|
||||
generator: residentCompiler,
|
||||
target: argResults['target'],
|
||||
);
|
||||
}).toList();
|
||||
flutterDevices.add(flutterDevice);
|
||||
}
|
||||
|
||||
ResidentRunner runner;
|
||||
final String applicationBinaryPath = argResults['use-application-binary'];
|
||||
|
|
|
@ -9,6 +9,7 @@ import '../base/common.dart';
|
|||
import '../base/file_system.dart';
|
||||
import '../base/platform.dart';
|
||||
import '../cache.dart';
|
||||
import '../project.dart';
|
||||
import '../runner/flutter_command.dart';
|
||||
import '../test/coverage_collector.dart';
|
||||
import '../test/event_printer.dart';
|
||||
|
@ -104,6 +105,7 @@ class TestCommand extends FlutterCommand {
|
|||
Future<FlutterCommandResult> runCommand() async {
|
||||
final List<String> names = argResults['name'];
|
||||
final List<String> plainNames = argResults['plain-name'];
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
|
||||
Iterable<String> files = argResults.rest.map<String>((String testPath) => fs.path.absolute(testPath)).toList();
|
||||
|
||||
|
@ -170,6 +172,7 @@ class TestCommand extends FlutterCommand {
|
|||
trackWidgetCreation: argResults['track-widget-creation'],
|
||||
updateGoldens: argResults['update-goldens'],
|
||||
concurrency: jobs,
|
||||
flutterProject: flutterProject,
|
||||
);
|
||||
|
||||
if (collector != null) {
|
||||
|
|
|
@ -661,7 +661,11 @@ class ResidentCompiler {
|
|||
return null;
|
||||
}
|
||||
|
||||
Future<dynamic> shutdown() {
|
||||
Future<dynamic> shutdown() async {
|
||||
// Server was never sucessfully created.
|
||||
if (_server == null) {
|
||||
return 0;
|
||||
}
|
||||
_server.kill();
|
||||
return _server.exitCode;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ class PackageMap {
|
|||
|
||||
static String get globalPackagesPath => _globalPackagesPath ?? kPackagesFileName;
|
||||
|
||||
static String get globalGeneratedPackagesPath => fs.path.setExtension(globalPackagesPath, '.generated');
|
||||
|
||||
static set globalPackagesPath(String value) {
|
||||
_globalPackagesPath = value;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ class FlutterProject {
|
|||
|
||||
/// The directory containing the generated code for this project.
|
||||
Directory get generated => directory
|
||||
.absolute
|
||||
.childDirectory('.dart_tool')
|
||||
.childDirectory('build')
|
||||
.childDirectory('generated')
|
||||
|
@ -165,6 +166,12 @@ class FlutterProject {
|
|||
final YamlMap pubspec = loadYaml(await pubspecFile.readAsString());
|
||||
return pubspec['builders'];
|
||||
}
|
||||
|
||||
/// Whether there are any builders used by this package.
|
||||
Future<bool> get hasBuilders async {
|
||||
final YamlMap result = await builders;
|
||||
return result != null && result.isNotEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the iOS sub-project of a Flutter project.
|
||||
|
|
|
@ -49,6 +49,45 @@ class FlutterDevice {
|
|||
experimentalFlags: experimentalFlags,
|
||||
);
|
||||
|
||||
/// Create a [FlutterDevice] with optional code generation enabled.
|
||||
static Future<FlutterDevice> create(Device device, {
|
||||
@required bool trackWidgetCreation,
|
||||
String dillOutputPath,
|
||||
List<String> fileSystemRoots,
|
||||
String fileSystemScheme,
|
||||
String viewFilter,
|
||||
@required String target,
|
||||
TargetModel targetModel = TargetModel.flutter,
|
||||
List<String> experimentalFlags,
|
||||
ResidentCompiler generator,
|
||||
}) async {
|
||||
ResidentCompiler generator;
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
if (experimentalBuildEnabled && await flutterProject.hasBuilders) {
|
||||
generator = await CodeGeneratingResidentCompiler.create(flutterProject: flutterProject, mainPath: target);
|
||||
} else {
|
||||
generator = ResidentCompiler(
|
||||
artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
fileSystemRoots: fileSystemRoots,
|
||||
fileSystemScheme: fileSystemScheme,
|
||||
targetModel: targetModel,
|
||||
experimentalFlags: experimentalFlags,
|
||||
);
|
||||
}
|
||||
return FlutterDevice(
|
||||
device,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
dillOutputPath: dillOutputPath,
|
||||
fileSystemRoots: fileSystemRoots,
|
||||
fileSystemScheme:fileSystemScheme,
|
||||
viewFilter: viewFilter,
|
||||
experimentalFlags: experimentalFlags,
|
||||
targetModel: targetModel,
|
||||
generator: generator,
|
||||
);
|
||||
}
|
||||
|
||||
final Device device;
|
||||
final ResidentCompiler generator;
|
||||
List<Uri> observatoryUris;
|
||||
|
|
|
@ -24,10 +24,12 @@ import '../base/process_manager.dart';
|
|||
import '../base/terminal.dart';
|
||||
import '../build_info.dart';
|
||||
import '../bundle.dart';
|
||||
import '../codegen.dart';
|
||||
import '../compile.dart';
|
||||
import '../convert.dart';
|
||||
import '../dart/package_map.dart';
|
||||
import '../globals.dart';
|
||||
import '../project.dart';
|
||||
import '../vmservice.dart';
|
||||
import 'watcher.dart';
|
||||
|
||||
|
@ -89,6 +91,7 @@ void installHook({
|
|||
int observatoryPort,
|
||||
InternetAddressType serverType = InternetAddressType.IPv4,
|
||||
Uri projectRootDirectory,
|
||||
FlutterProject flutterProject,
|
||||
}) {
|
||||
assert(enableObservatory || (!startPaused && observatoryPort == null));
|
||||
hack.registerPlatformPlugin(
|
||||
|
@ -107,6 +110,7 @@ void installHook({
|
|||
trackWidgetCreation: trackWidgetCreation,
|
||||
updateGoldens: updateGoldens,
|
||||
projectRootDirectory: projectRootDirectory,
|
||||
flutterProject: flutterProject,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -232,7 +236,7 @@ class _CompilationRequest {
|
|||
// This class is a wrapper around compiler that allows multiple isolates to
|
||||
// enqueue compilation requests, but ensures only one compilation at a time.
|
||||
class _Compiler {
|
||||
_Compiler(bool trackWidgetCreation, Uri projectRootDirectory) {
|
||||
_Compiler(bool trackWidgetCreation, Uri projectRootDirectory, FlutterProject flutterProject) {
|
||||
// Compiler maintains and updates single incremental dill file.
|
||||
// Incremental compilation requests done for each test copy that file away
|
||||
// for independent execution.
|
||||
|
@ -265,7 +269,16 @@ class _Compiler {
|
|||
trackWidgetCreation: trackWidgetCreation,
|
||||
);
|
||||
|
||||
ResidentCompiler createCompiler() {
|
||||
Future<ResidentCompiler> createCompiler() async {
|
||||
if (experimentalBuildEnabled && await flutterProject.hasBuilders) {
|
||||
return CodeGeneratingResidentCompiler.create(
|
||||
flutterProject: flutterProject,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
initializeFromDill: null, // TODO(jonahwilliams): investigate multi-root support in init from dill.
|
||||
unsafePackageSerialization: false,
|
||||
compilerMessageConsumer: reportCompilerMessage,
|
||||
);
|
||||
}
|
||||
return ResidentCompiler(
|
||||
artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
packagesPath: PackageMap.globalPackagesPath,
|
||||
|
@ -290,7 +303,7 @@ class _Compiler {
|
|||
final Stopwatch compilerTime = Stopwatch()..start();
|
||||
bool firstCompile = false;
|
||||
if (compiler == null) {
|
||||
compiler = createCompiler();
|
||||
compiler = await createCompiler();
|
||||
firstCompile = true;
|
||||
}
|
||||
suppressOutput = false;
|
||||
|
@ -374,6 +387,7 @@ class _FlutterPlatform extends PlatformPlugin {
|
|||
this.trackWidgetCreation,
|
||||
this.updateGoldens,
|
||||
this.projectRootDirectory,
|
||||
this.flutterProject,
|
||||
}) : assert(shellPath != null);
|
||||
|
||||
final String shellPath;
|
||||
|
@ -389,6 +403,7 @@ class _FlutterPlatform extends PlatformPlugin {
|
|||
final bool trackWidgetCreation;
|
||||
final bool updateGoldens;
|
||||
final Uri projectRootDirectory;
|
||||
final FlutterProject flutterProject;
|
||||
|
||||
Directory fontsDirectory;
|
||||
_Compiler compiler;
|
||||
|
@ -545,7 +560,7 @@ class _FlutterPlatform extends PlatformPlugin {
|
|||
|
||||
if (precompiledDillPath == null && precompiledDillFiles == null) {
|
||||
// Lazily instantiate compiler so it is built only if it is actually used.
|
||||
compiler ??= _Compiler(trackWidgetCreation, projectRootDirectory);
|
||||
compiler ??= _Compiler(trackWidgetCreation, projectRootDirectory, flutterProject);
|
||||
mainDart = await compiler.compile(mainDart);
|
||||
|
||||
if (mainDart == null) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import '../base/process_manager.dart';
|
|||
import '../base/terminal.dart';
|
||||
import '../dart/package_map.dart';
|
||||
import '../globals.dart';
|
||||
import '../project.dart';
|
||||
import 'flutter_platform.dart' as loader;
|
||||
import 'watcher.dart';
|
||||
|
||||
|
@ -34,6 +35,7 @@ Future<int> runTests(
|
|||
bool updateGoldens = false,
|
||||
TestWatcher watcher,
|
||||
@required int concurrency,
|
||||
FlutterProject flutterProject,
|
||||
}) async {
|
||||
// Compute the command-line arguments for package:test.
|
||||
final List<String> testArgs = <String>[];
|
||||
|
@ -80,6 +82,7 @@ Future<int> runTests(
|
|||
trackWidgetCreation: trackWidgetCreation,
|
||||
updateGoldens: updateGoldens,
|
||||
projectRootDirectory: fs.currentDirectory.uri,
|
||||
flutterProject: flutterProject,
|
||||
);
|
||||
|
||||
// Make the global packages path absolute.
|
||||
|
|
|
@ -30,6 +30,7 @@ void main() {
|
|||
testUsingContext('delegates to build_runner', () async {
|
||||
const CodeGeneratingKernelCompiler kernelCompiler = CodeGeneratingKernelCompiler();
|
||||
when(mockBuildRunner.build(
|
||||
any,
|
||||
aot: anyNamed('aot'),
|
||||
extraFrontEndOptions: anyNamed('extraFrontEndOptions'),
|
||||
linkPlatformKernelIn: anyNamed('linkPlatformKernelIn'),
|
||||
|
@ -37,7 +38,7 @@ void main() {
|
|||
targetProductVm: anyNamed('targetProductVm'),
|
||||
trackWidgetCreation: anyNamed('trackWidgetCreation'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
return CodeGenerationResult(fs.file('.packages'), fs.file('main.app.dill'));
|
||||
return CodeGenerationResult(fs.file('main.app.dill'));
|
||||
});
|
||||
final CompilerOutput buildResult = await kernelCompiler.compile(
|
||||
outputFilePath: 'output.app.dill',
|
||||
|
|
Loading…
Reference in a new issue