mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Add basic codegen app to be used for integration testing and benchmarks (#27257)
This commit is contained in:
parent
3205736fcf
commit
67cf21577f
20
dev/devicelab/bin/tasks/codegen_integration_test.dart
Normal file
20
dev/devicelab/bin/tasks/codegen_integration_test.dart
Normal file
@ -0,0 +1,20 @@
|
||||
// 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 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'package:flutter_devicelab/framework/adb.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/framework/utils.dart';
|
||||
import 'package:flutter_devicelab/tasks/integration_tests.dart';
|
||||
|
||||
final Directory codegenAppPath = dir(path.join(flutterDirectory.path, 'dev/integration_tests/codegen'));
|
||||
|
||||
Future<void> main() async {
|
||||
deviceOperatingSystem = DeviceOperatingSystem.android;
|
||||
await task(createCodegenerationIntegrationTest());
|
||||
}
|
@ -61,6 +61,16 @@ TaskFunction createAndroidSemanticsIntegrationTest() {
|
||||
);
|
||||
}
|
||||
|
||||
TaskFunction createCodegenerationIntegrationTest() {
|
||||
return DriverTest(
|
||||
'${flutterDirectory.path}/dev/integration_tests/codegen',
|
||||
'lib/main.dart',
|
||||
environment: <String, String>{
|
||||
'FLUTTER_EXPERIMENTAL_BUILD': 'true'
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
TaskFunction createFlutterCreateOfflineTest() {
|
||||
return () async {
|
||||
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_create_test.');
|
||||
@ -83,12 +93,14 @@ class DriverTest {
|
||||
this.testDirectory,
|
||||
this.testTarget, {
|
||||
this.extraOptions = const <String>[],
|
||||
this.environment = const <String, String>{},
|
||||
}
|
||||
);
|
||||
|
||||
final String testDirectory;
|
||||
final String testTarget;
|
||||
final List<String> extraOptions;
|
||||
final Map<String, String> environment;
|
||||
|
||||
Future<TaskResult> call() {
|
||||
return inDirectory<TaskResult>(testDirectory, () async {
|
||||
@ -107,7 +119,7 @@ class DriverTest {
|
||||
deviceId,
|
||||
];
|
||||
options.addAll(extraOptions);
|
||||
await flutter('drive', options: options);
|
||||
await flutter('drive', options: options, environment: Map<String, String>.from(environment));
|
||||
|
||||
return TaskResult.success(null);
|
||||
});
|
||||
|
@ -76,6 +76,14 @@ tasks:
|
||||
stage: devicelab_win
|
||||
required_agent_capabilities: ["windows/android"]
|
||||
|
||||
codegen_integration_test:
|
||||
description: >
|
||||
Runs codegeneration and verifies that it can execute
|
||||
correctly.
|
||||
stage: devicelab_win
|
||||
required_agent_capabilities: ["windows/android"]
|
||||
flaky: true
|
||||
|
||||
flutter_gallery_android__compile:
|
||||
description: >
|
||||
Collects various performance metrics of compiling the Flutter
|
||||
|
3
dev/integration_tests/codegen/README.md
Normal file
3
dev/integration_tests/codegen/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# codegen
|
||||
|
||||
A Flutter project for testing code generation.
|
17
dev/integration_tests/codegen/android/.project
Normal file
17
dev/integration_tests/codegen/android/.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>android_____</name>
|
||||
<comment>Project android_____ created by Buildship.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -0,0 +1,2 @@
|
||||
connection.project.dir=
|
||||
eclipse.preferences.version=1
|
57
dev/integration_tests/codegen/android/app/build.gradle
Normal file
57
dev/integration_tests/codegen/android/app/build.gradle
Normal file
@ -0,0 +1,57 @@
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withInputStream { stream ->
|
||||
localProperties.load(stream)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "0.0.1"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
|
||||
aaptOptions {
|
||||
// TODO(goderbauer): remove when https://github.com/flutter/flutter/issues/8986 is resolved.
|
||||
if(System.getenv("FLUTTER_CI_WIN")) {
|
||||
println "AAPT cruncher disabled when running on Win CI."
|
||||
cruncherEnabled false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source '../..'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.yourcompany.platforminteraction">
|
||||
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
In most cases you can leave this as-is, but you if you want to provide
|
||||
additional functionality it is fine to subclass or reimplement
|
||||
FlutterApplication and put your custom class here. -->
|
||||
<application android:name="io.flutter.app.FlutterApplication" android:label="Platform Interaction" android:icon="@mipmap/ic_launcher">
|
||||
<activity android:name="com.yourcompany.platforminteraction.MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
package com.yourcompany.platforminteraction;
|
||||
|
||||
import android.os.Bundle;
|
||||
import io.flutter.app.FlutterActivity;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
|
||||
public class MainActivity extends FlutterActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
GeneratedPluginRegistrant.registerWith(this);
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 544 B |
Binary file not shown.
After Width: | Height: | Size: 442 B |
Binary file not shown.
After Width: | Height: | Size: 721 B |
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
29
dev/integration_tests/codegen/android/build.gradle
Normal file
29
dev/integration_tests/codegen/android/build.gradle
Normal file
@ -0,0 +1,29 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.buildDir = '../build'
|
||||
subprojects {
|
||||
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
1
dev/integration_tests/codegen/android/gradle.properties
Normal file
1
dev/integration_tests/codegen/android/gradle.properties
Normal file
@ -0,0 +1 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
6
dev/integration_tests/codegen/android/gradle/wrapper/gradle-wrapper.properties
vendored
Executable file
6
dev/integration_tests/codegen/android/gradle/wrapper/gradle-wrapper.properties
vendored
Executable file
@ -0,0 +1,6 @@
|
||||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
15
dev/integration_tests/codegen/android/settings.gradle
Normal file
15
dev/integration_tests/codegen/android/settings.gradle
Normal file
@ -0,0 +1,15 @@
|
||||
include ':app'
|
||||
|
||||
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||
|
||||
def plugins = new Properties()
|
||||
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||
if (pluginsFile.exists()) {
|
||||
pluginsFile.withInputStream { stream -> plugins.load(stream) }
|
||||
}
|
||||
|
||||
plugins.each { name, path ->
|
||||
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||
include ":$name"
|
||||
project(":$name").projectDir = pluginDirectory
|
||||
}
|
58
dev/integration_tests/codegen/lib/coffee_app.dart
Normal file
58
dev/integration_tests/codegen/lib/coffee_app.dart
Normal file
@ -0,0 +1,58 @@
|
||||
// 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:inject/inject.dart';
|
||||
|
||||
// This is a compile-time generated file and does not exist in source.
|
||||
import 'coffee_app.inject.dart' as generated; // ignore: uri_does_not_exist
|
||||
import 'src/coffee.dart';
|
||||
|
||||
@module
|
||||
class PourOverCoffeeModule {
|
||||
@provide
|
||||
@brandName
|
||||
String provideBrand() => 'Coffee by Flutter Inc.';
|
||||
|
||||
@provide
|
||||
@modelName
|
||||
String provideModel() => 'PourOverSupremeFiesta';
|
||||
|
||||
@provide
|
||||
@asynchronous
|
||||
Future<Heater> provideHeater() async => Stove();
|
||||
|
||||
@provide
|
||||
Pump providePump(Heater heater) => NoOpPump();
|
||||
}
|
||||
|
||||
class NoOpPump extends Pump {
|
||||
@override
|
||||
void pump() {
|
||||
print('nothing to pump...');
|
||||
}
|
||||
}
|
||||
|
||||
class Stove extends Heater {
|
||||
@override
|
||||
bool get isHot => _isHot;
|
||||
bool _isHot = false;
|
||||
|
||||
@override
|
||||
void off() {
|
||||
_isHot = true;
|
||||
}
|
||||
|
||||
@override
|
||||
void on() {
|
||||
_isHot = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Injector(<Type>[PourOverCoffeeModule])
|
||||
abstract class CoffeeApp {
|
||||
static final Future<CoffeeApp> Function(PourOverCoffeeModule) create = generated.CoffeeApp$Injector.create;
|
||||
|
||||
@provide
|
||||
CoffeeMaker getCoffeeMaker();
|
||||
}
|
49
dev/integration_tests/codegen/lib/main.dart
Normal file
49
dev/integration_tests/codegen/lib/main.dart
Normal file
@ -0,0 +1,49 @@
|
||||
// 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:flutter/material.dart';
|
||||
import 'package:flutter_driver/driver_extension.dart';
|
||||
|
||||
import 'coffee_app.dart';
|
||||
import 'src/coffee.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
enableFlutterDriverExtension();
|
||||
coffeeApp = await CoffeeApp.create(PourOverCoffeeModule());
|
||||
runApp(ExampleWidget());
|
||||
}
|
||||
|
||||
CoffeeApp coffeeApp;
|
||||
|
||||
class ExampleWidget extends StatefulWidget {
|
||||
@override
|
||||
_ExampleWidgetState createState() => _ExampleWidgetState();
|
||||
}
|
||||
|
||||
class _ExampleWidgetState extends State<ExampleWidget> {
|
||||
String _message = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
RaisedButton(
|
||||
child: const Text('Press Button, Get Coffee'),
|
||||
onPressed: () async {
|
||||
final CoffeeMaker coffeeMaker = coffeeApp.getCoffeeMaker();
|
||||
setState(() {
|
||||
_message = coffeeMaker.brew();
|
||||
});
|
||||
},
|
||||
),
|
||||
Text(_message),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
41
dev/integration_tests/codegen/lib/src/coffee.dart
Normal file
41
dev/integration_tests/codegen/lib/src/coffee.dart
Normal file
@ -0,0 +1,41 @@
|
||||
// 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:inject/inject.dart';
|
||||
|
||||
const Qualifier brandName = Qualifier(#brandName);
|
||||
const Qualifier modelName = Qualifier(#modelName);
|
||||
|
||||
class CoffeeMaker {
|
||||
@provide
|
||||
CoffeeMaker(this._heater, this._pump, this._brand, this._model);
|
||||
|
||||
final Heater _heater;
|
||||
final Pump _pump;
|
||||
|
||||
@modelName
|
||||
final String _model;
|
||||
|
||||
@brandName
|
||||
final String _brand;
|
||||
|
||||
String brew() {
|
||||
_heater.on();
|
||||
_pump.pump();
|
||||
print(' [_]P coffee! [_]P');
|
||||
final String message = 'Thanks for using $_model by $_brand';
|
||||
_heater.off();
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Heater {
|
||||
void on();
|
||||
void off();
|
||||
bool get isHot;
|
||||
}
|
||||
|
||||
abstract class Pump {
|
||||
void pump();
|
||||
}
|
88
dev/integration_tests/codegen/pubspec.yaml
Normal file
88
dev/integration_tests/codegen/pubspec.yaml
Normal file
@ -0,0 +1,88 @@
|
||||
name: codegen
|
||||
description: A test of Flutter integrating code generation.
|
||||
|
||||
environment:
|
||||
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
|
||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_driver:
|
||||
sdk: flutter
|
||||
# TODO(jonahwilliams): replace with pub version when everything is compatible
|
||||
inject:
|
||||
git:
|
||||
url: https://github.com/jonahwilliams/inject.dart
|
||||
path: package/inject
|
||||
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
collection: 1.14.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
convert: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
file: 5.0.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
intl: 0.15.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
typed_data: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
vector_math: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
vm_service_client: 0.2.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
|
||||
dev_dependencies:
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf_web_socket: 0.2.2+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
test_api: 0.2.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
test_core: 0.2.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
utf: 0.9.0+5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
watcher: 0.9.7+10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
|
||||
builders:
|
||||
# TODO(jonahwilliams): replace with pub version when everything is compatible
|
||||
inject_generator:
|
||||
git:
|
||||
url: https://github.com/jonahwilliams/inject.dart
|
||||
path: package/inject_generator
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# PUBSPEC CHECKSUM: c26c
|
23
dev/integration_tests/codegen/test_driver/main_test.dart
Normal file
23
dev/integration_tests/codegen/test_driver/main_test.dart
Normal file
@ -0,0 +1,23 @@
|
||||
// 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:flutter_driver/flutter_driver.dart';
|
||||
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
|
||||
|
||||
void main() {
|
||||
FlutterDriver driver;
|
||||
|
||||
setUpAll(() async {
|
||||
driver = await FlutterDriver.connect();
|
||||
});
|
||||
|
||||
test('Can execute generated code', () async {
|
||||
const String button = 'Press Button, Get Coffee';
|
||||
await driver.tap(find.text(button));
|
||||
|
||||
const String message = 'Thanks for using PourOverSupremeFiesta by Coffee by Flutter Inc.';
|
||||
final String fullMessage = await driver.getText(find.text(message));
|
||||
expect(fullMessage, message);
|
||||
});
|
||||
}
|
@ -84,6 +84,11 @@ class FlutterKernelBuilder implements Builder {
|
||||
|
||||
@override
|
||||
Future<void> build(BuildStep buildStep) async {
|
||||
// Do not resolve dependencies if this does not correspond to the main
|
||||
// entrypoint.
|
||||
if (!mainPath.contains(buildStep.inputId.path)) {
|
||||
return;
|
||||
}
|
||||
final AssetId outputId = buildStep.inputId.changeExtension(_kFlutterDillOutputExtension);
|
||||
final AssetId packagesOutputId = buildStep.inputId.changeExtension(_kPackagesExtension);
|
||||
|
||||
@ -97,9 +102,8 @@ class FlutterKernelBuilder implements Builder {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not generate kernel if it has been disabled or if this asset does not
|
||||
// correspond to the current entrypoint.
|
||||
if (disabled || !mainPath.contains(buildStep.inputId.path)) {
|
||||
// Do not generate kernel if it has been disabled.
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -118,8 +122,14 @@ class FlutterKernelBuilder implements Builder {
|
||||
// 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:$multiRootScheme:///lib/');
|
||||
final String newPackagesContents = oldPackagesContents.replaceFirst('$packageName:lib/', '$packageName:$multiRootScheme:/');
|
||||
await packagesFile.writeAsString(newPackagesContents);
|
||||
String absoluteMainPath;
|
||||
if (path.isAbsolute(mainPath)) {
|
||||
absoluteMainPath = mainPath;
|
||||
} else {
|
||||
absoluteMainPath = path.join(projectDir.absolute.path, mainPath);
|
||||
}
|
||||
|
||||
// start up the frontend server with configuration.
|
||||
final List<String> arguments = <String>[
|
||||
@ -145,14 +155,15 @@ class FlutterKernelBuilder implements Builder {
|
||||
if (incrementalCompilerByteStorePath != null) {
|
||||
arguments.add('--incremental');
|
||||
}
|
||||
final String generatedRoot = path.join(projectDir.absolute.path, '.dart_tool', 'build', 'generated', '$packageName');
|
||||
final String generatedRoot = path.join(projectDir.absolute.path, '.dart_tool', 'build', 'generated', '$packageName', 'lib');
|
||||
final String normalRoot = path.join(projectDir.absolute.path, 'lib');
|
||||
arguments.addAll(<String>[
|
||||
'--packages',
|
||||
packagesFile.path,
|
||||
'--output-dill',
|
||||
outputFile.path,
|
||||
'--filesystem-root',
|
||||
projectDir.absolute.path,
|
||||
normalRoot,
|
||||
'--filesystem-root',
|
||||
generatedRoot,
|
||||
'--filesystem-scheme',
|
||||
@ -162,12 +173,12 @@ class FlutterKernelBuilder implements Builder {
|
||||
arguments.addAll(extraFrontEndOptions);
|
||||
}
|
||||
final Uri mainUri = _PackageUriMapper.findUri(
|
||||
mainPath,
|
||||
absoluteMainPath,
|
||||
packagesFile.path,
|
||||
multiRootScheme,
|
||||
<String>[projectDir.absolute.path, generatedRoot],
|
||||
<String>[normalRoot, generatedRoot],
|
||||
);
|
||||
arguments.add(mainUri.toString());
|
||||
arguments.add(mainUri?.toString() ?? absoluteMainPath);
|
||||
// Invoke the frontend server and copy the dill back to the output
|
||||
// directory.
|
||||
try {
|
||||
@ -202,7 +213,6 @@ class _StdoutHandler {
|
||||
bool _suppressCompilerMessages;
|
||||
|
||||
void handler(String message) {
|
||||
log.info(message);
|
||||
const String kResultPrefix = 'result ';
|
||||
if (boundaryKey == null) {
|
||||
if (message.startsWith(kResultPrefix))
|
||||
@ -256,7 +266,7 @@ class _PackageUriMapper {
|
||||
if (fileSystemScheme != null && fileSystemRoots != null && prefix.contains(fileSystemScheme)) {
|
||||
_packageName = packageName;
|
||||
_uriPrefixes = fileSystemRoots
|
||||
.map((String name) => Uri.file('$name/lib/', windows: Platform.isWindows).toString())
|
||||
.map((String name) => Uri.file(name, windows: Platform.isWindows).toString())
|
||||
.toList();
|
||||
return;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ environment:
|
||||
dependencies:
|
||||
# To update these, use "flutter update-packages --force-upgrade".
|
||||
build: 1.1.1
|
||||
build_modules: 1.0.7
|
||||
build_modules: 1.0.7+2
|
||||
package_config: 1.0.5
|
||||
path: 1.6.2
|
||||
|
||||
@ -50,4 +50,4 @@ dartdoc:
|
||||
# Exclude this package from the hosted API docs.
|
||||
nodoc: true
|
||||
|
||||
# PUBSPEC CHECKSUM: 0361
|
||||
# PUBSPEC CHECKSUM: dcbe
|
||||
|
@ -18,6 +18,7 @@ dart_library("flutter_tools") {
|
||||
"//third_party/dart/third_party/pkg/linter",
|
||||
"//third_party/dart-pkg/pub/archive",
|
||||
"//third_party/dart-pkg/pub/args",
|
||||
"//third_party/dart-pkg/pub/build_daemon",
|
||||
"//third_party/dart-pkg/pub/build_runner_core",
|
||||
"//third_party/dart-pkg/pub/collection",
|
||||
"//third_party/dart-pkg/pub/completion",
|
||||
|
@ -5,6 +5,12 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'runner.dart' as runner;
|
||||
import 'src/base/context.dart';
|
||||
// The build_runner code generation is provided here to make it easier to
|
||||
// avoid introducing the dependency into google3. Not all build* packages
|
||||
// are synced internally.
|
||||
import 'src/build_runner/build_runner.dart';
|
||||
import 'src/codegen.dart';
|
||||
import 'src/commands/analyze.dart';
|
||||
import 'src/commands/attach.dart';
|
||||
import 'src/commands/build.dart';
|
||||
@ -18,6 +24,7 @@ import 'src/commands/doctor.dart';
|
||||
import 'src/commands/drive.dart';
|
||||
import 'src/commands/emulators.dart';
|
||||
import 'src/commands/format.dart';
|
||||
import 'src/commands/generate.dart';
|
||||
import 'src/commands/ide_config.dart';
|
||||
import 'src/commands/inject_plugins.dart';
|
||||
import 'src/commands/install.dart';
|
||||
@ -63,6 +70,7 @@ Future<void> main(List<String> args) async {
|
||||
DriveCommand(),
|
||||
EmulatorsCommand(),
|
||||
FormatCommand(),
|
||||
GenerateCommand(),
|
||||
IdeConfigCommand(hidden: !verboseHelp),
|
||||
InjectPluginsCommand(hidden: !verboseHelp),
|
||||
InstallCommand(),
|
||||
@ -81,5 +89,10 @@ Future<void> main(List<String> args) async {
|
||||
VersionCommand(),
|
||||
], verbose: verbose,
|
||||
muteCommandLogging: muteCommandLogging,
|
||||
verboseHelp: verboseHelp);
|
||||
verboseHelp: verboseHelp,
|
||||
overrides: <Type, Generator>{
|
||||
// The build runner instance is not supported in google3 because
|
||||
// the build runner packages are not synced internally.
|
||||
CodeGenerator: () => experimentalBuildEnabled ? const BuildRunner() : const UnsupportedCodeGenerator(),
|
||||
});
|
||||
}
|
||||
|
@ -302,7 +302,6 @@ class AOTSnapshotter {
|
||||
printTrace('Extra front-end options: $extraFrontEndOptions');
|
||||
|
||||
final String depfilePath = fs.path.join(outputPath, 'kernel_compile.d');
|
||||
final KernelCompiler kernelCompiler = await kernelCompilerFactory.create();
|
||||
final CompilerOutput compilerOutput = await kernelCompiler.compile(
|
||||
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
mainPath: mainPath,
|
||||
|
@ -1,64 +0,0 @@
|
||||
// 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 '../compile.dart';
|
||||
import '../globals.dart';
|
||||
import 'build_runner.dart';
|
||||
|
||||
/// An implementation of the [KernelCompiler] which delegates to build_runner.
|
||||
///
|
||||
/// Only a subset of the arguments provided to the [KernelCompiler] are
|
||||
/// supported here. Using the build pipeline implies a fixed multiroot
|
||||
/// filesystem and requires a pubspec.
|
||||
///
|
||||
/// This is only safe to use if [experimentalBuildEnabled] is true.
|
||||
class BuildKernelCompiler implements KernelCompiler {
|
||||
const BuildKernelCompiler();
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> compile({
|
||||
String mainPath,
|
||||
String outputFilePath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool aot = false,
|
||||
bool trackWidgetCreation,
|
||||
List<String> extraFrontEndOptions,
|
||||
String incrementalCompilerByteStorePath,
|
||||
bool targetProductVm = false,
|
||||
// These arguments are currently unused.
|
||||
String sdkRoot,
|
||||
String packagesPath,
|
||||
List<String> fileSystemRoots,
|
||||
String fileSystemScheme,
|
||||
String depFilePath,
|
||||
TargetModel targetModel = TargetModel.flutter,
|
||||
}) async {
|
||||
if (fileSystemRoots != null || fileSystemScheme != null || depFilePath != null || targetModel != null || sdkRoot != null || packagesPath != null) {
|
||||
printTrace('fileSystemRoots, fileSystemScheme, depFilePath, targetModel,'
|
||||
'sdkRoot, packagesPath are not supported when using the experimental '
|
||||
'build* pipeline');
|
||||
}
|
||||
final BuildRunner buildRunner = buildRunnerFactory.create();
|
||||
try {
|
||||
final BuildResult buildResult = await buildRunner.build(
|
||||
aot: aot,
|
||||
linkPlatformKernelIn: linkPlatformKernelIn,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
mainPath: mainPath,
|
||||
targetProductVm: targetProductVm,
|
||||
extraFrontEndOptions: extraFrontEndOptions
|
||||
);
|
||||
final File outputFile = fs.file(outputFilePath);
|
||||
if (!await outputFile.exists()) {
|
||||
await outputFile.create();
|
||||
}
|
||||
await outputFile.writeAsBytes(await buildResult.dillFile.readAsBytes());
|
||||
return CompilerOutput(outputFilePath, 0);
|
||||
} on Exception catch (err) {
|
||||
printError('Compilation Failed: $err');
|
||||
return const CompilerOutput(null, 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,69 +4,45 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:build_daemon/data/build_target.dart';
|
||||
import 'package:build_runner_core/build_runner_core.dart';
|
||||
import 'package:build_daemon/data/server_log.dart';
|
||||
import 'package:build_daemon/data/build_status.dart' as build;
|
||||
import 'package:build_daemon/client.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
import '../artifacts.dart';
|
||||
import '../base/context.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
import '../base/logger.dart';
|
||||
import '../base/platform.dart';
|
||||
import '../base/process_manager.dart';
|
||||
import '../cache.dart';
|
||||
import '../codegen.dart';
|
||||
import '../convert.dart';
|
||||
import '../dart/pub.dart';
|
||||
import '../globals.dart';
|
||||
import '../project.dart';
|
||||
import '../resident_runner.dart';
|
||||
import 'build_script_generator.dart';
|
||||
|
||||
/// The [BuildRunnerFactory] instance.
|
||||
BuildRunnerFactory get buildRunnerFactory => context[BuildRunnerFactory];
|
||||
|
||||
/// Whether to attempt to build a flutter project using build* libraries.
|
||||
///
|
||||
/// This requires both an experimental opt in via the environment variable
|
||||
/// 'FLUTTER_EXPERIMENTAL_BUILD' and that the project itself has a
|
||||
/// dependency on the package 'flutter_build' and 'build_runner.'
|
||||
bool get experimentalBuildEnabled {
|
||||
return _experimentalBuildEnabled ??= platform.environment['FLUTTER_EXPERIMENTAL_BUILD']?.toLowerCase() == 'true';
|
||||
}
|
||||
bool _experimentalBuildEnabled;
|
||||
|
||||
@visibleForTesting
|
||||
set experimentalBuildEnabled(bool value) {
|
||||
_experimentalBuildEnabled = value;
|
||||
}
|
||||
|
||||
/// An injectable factory to create instances of [BuildRunner].
|
||||
class BuildRunnerFactory {
|
||||
const BuildRunnerFactory();
|
||||
|
||||
/// Creates a new [BuildRunner] instance.
|
||||
BuildRunner create() {
|
||||
return BuildRunner();
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper for a build_runner process which delegates to a generated
|
||||
/// build script.
|
||||
///
|
||||
/// This is only enabled if [experimentalBuildEnabled] is true, and only for
|
||||
/// external flutter users.
|
||||
class BuildRunner {
|
||||
class BuildRunner extends CodeGenerator {
|
||||
const BuildRunner();
|
||||
|
||||
/// Run a build_runner build and return the resulting .packages and dill file.
|
||||
///
|
||||
/// The defines of the build command are the arguments required in the
|
||||
/// flutter_build kernel builder.
|
||||
Future<BuildResult> build({
|
||||
@override
|
||||
Future<CodeGenerationResult> build({
|
||||
@required String mainPath,
|
||||
@required bool aot,
|
||||
@required bool linkPlatformKernelIn,
|
||||
@required bool trackWidgetCreation,
|
||||
@required bool targetProductVm,
|
||||
@required String mainPath,
|
||||
@required List<String> extraFrontEndOptions,
|
||||
List<String> extraFrontEndOptions = const <String>[],
|
||||
bool disableKernelGeneration = false,
|
||||
}) async {
|
||||
await generateBuildScript();
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
@ -95,7 +71,7 @@ class BuildRunner {
|
||||
'--packages=$scriptPackagesPath',
|
||||
buildScript,
|
||||
'build',
|
||||
'--define', 'flutter_build|kernel=disabled=false',
|
||||
'--define', 'flutter_build|kernel=disabled=$disableKernelGeneration',
|
||||
'--define', 'flutter_build|kernel=aot=$aot',
|
||||
'--define', 'flutter_build|kernel=linkPlatformKernelIn=$linkPlatformKernelIn',
|
||||
'--define', 'flutter_build|kernel=trackWidgetCreation=$trackWidgetCreation',
|
||||
@ -121,6 +97,9 @@ class BuildRunner {
|
||||
} finally {
|
||||
status.stop();
|
||||
}
|
||||
if (disableKernelGeneration) {
|
||||
return const CodeGenerationResult(null, null);
|
||||
}
|
||||
/// We don't check for this above because it might be generated for the
|
||||
/// first time by invoking the build.
|
||||
final Directory dartTool = flutterProject.dartTool;
|
||||
@ -143,13 +122,10 @@ class BuildRunner {
|
||||
if (!packagesFile.existsSync() || !dillFile.existsSync()) {
|
||||
throw Exception('build_runner did not produce output at expected location: ${dillFile.path} missing');
|
||||
}
|
||||
return BuildResult(packagesFile, dillFile);
|
||||
return CodeGenerationResult(packagesFile, dillFile);
|
||||
}
|
||||
|
||||
/// Invalidates a generated build script by deleting it.
|
||||
///
|
||||
/// Must be called any time a pubspec file update triggers a corresponding change
|
||||
/// in .packages.
|
||||
@override
|
||||
Future<void> invalidateBuildScript() async {
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
final File buildScript = flutterProject.dartTool
|
||||
@ -162,8 +138,7 @@ class BuildRunner {
|
||||
await buildScript.delete();
|
||||
}
|
||||
|
||||
// Generates a synthetic package under .dart_tool/flutter_tool which is in turn
|
||||
// used to generate a build script.
|
||||
@override
|
||||
Future<void> generateBuildScript() async {
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
final String generatedDirectory = fs.path.join(flutterProject.dartTool.path, 'flutter_tool');
|
||||
@ -180,8 +155,10 @@ class BuildRunner {
|
||||
|
||||
stringBuffer.writeln('name: synthetic_example');
|
||||
stringBuffer.writeln('dependencies:');
|
||||
for (String builder in await flutterProject.builders) {
|
||||
stringBuffer.writeln(' $builder: any');
|
||||
final YamlMap builders = await flutterProject.builders;
|
||||
for (String name in builders.keys) {
|
||||
final YamlNode node = builders[name];
|
||||
stringBuffer.writeln(' $name: $node');
|
||||
}
|
||||
stringBuffer.writeln(' build_runner: any');
|
||||
stringBuffer.writeln(' flutter_build:');
|
||||
@ -195,17 +172,92 @@ class BuildRunner {
|
||||
checkLastModified: false,
|
||||
);
|
||||
final PackageGraph packageGraph = PackageGraph.forPath(syntheticPubspec.parent.path);
|
||||
final BuildScriptGenerator buildScriptGenerator = buildScriptGeneratorFactory.create(flutterProject, packageGraph);
|
||||
final BuildScriptGenerator buildScriptGenerator = const BuildScriptGeneratorFactory().create(flutterProject, packageGraph);
|
||||
await buildScriptGenerator.generateBuildScript();
|
||||
} finally {
|
||||
status.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CodegenDaemon> daemon({
|
||||
String mainPath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool targetProductVm = false,
|
||||
bool trackWidgetCreation = false,
|
||||
List<String> extraFrontEndOptions = const <String> [],
|
||||
}) async {
|
||||
mainPath ??= findMainDartFile();
|
||||
await generateBuildScript();
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
final String frontendServerPath = artifacts.getArtifactPath(
|
||||
Artifact.frontendServerSnapshotForEngineDartSdk
|
||||
);
|
||||
final String sdkRoot = artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath);
|
||||
final String engineDartBinaryPath = artifacts.getArtifactPath(Artifact.engineDartBinary);
|
||||
final String packagesPath = flutterProject.packagesFile.absolute.path;
|
||||
final String buildScript = flutterProject
|
||||
.dartTool
|
||||
.childDirectory('build')
|
||||
.childDirectory('entrypoint')
|
||||
.childFile('build.dart')
|
||||
.path;
|
||||
final String scriptPackagesPath = flutterProject
|
||||
.dartTool
|
||||
.childDirectory('flutter_tool')
|
||||
.childFile('.packages')
|
||||
.path;
|
||||
final String dartPath = fs.path.join(Cache.flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', 'dart');
|
||||
final Status status = logger.startProgress('starting build daemon...', timeout: null);
|
||||
BuildDaemonClient buildDaemonClient;
|
||||
try {
|
||||
final List<String> command = <String>[
|
||||
dartPath,
|
||||
'--packages=$scriptPackagesPath',
|
||||
buildScript,
|
||||
'daemon',
|
||||
'--define', 'flutter_build|kernel=disabled=false',
|
||||
'--define', 'flutter_build|kernel=aot=false',
|
||||
'--define', 'flutter_build|kernel=linkPlatformKernelIn=$linkPlatformKernelIn',
|
||||
'--define', 'flutter_build|kernel=trackWidgetCreation=$trackWidgetCreation',
|
||||
'--define', 'flutter_build|kernel=targetProductVm=$targetProductVm',
|
||||
'--define', 'flutter_build|kernel=mainPath=$mainPath',
|
||||
'--define', 'flutter_build|kernel=packagesPath=$packagesPath',
|
||||
'--define', 'flutter_build|kernel=sdkRoot=$sdkRoot',
|
||||
'--define', 'flutter_build|kernel=frontendServerPath=$frontendServerPath',
|
||||
'--define', 'flutter_build|kernel=engineDartBinaryPath=$engineDartBinaryPath',
|
||||
'--define', 'flutter_build|kernel=extraFrontEndOptions=${extraFrontEndOptions ?? const <String>[]}',
|
||||
];
|
||||
buildDaemonClient = await BuildDaemonClient.connect(flutterProject.directory.path, command, logHandler: (ServerLog log) => printTrace(log.toString()));
|
||||
} finally {
|
||||
status.stop();
|
||||
}
|
||||
buildDaemonClient.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder builder) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
class BuildResult {
|
||||
const BuildResult(this.packagesFile, this.dillFile);
|
||||
class _BuildRunnerCodegenDaemon implements CodegenDaemon {
|
||||
_BuildRunnerCodegenDaemon(this.buildDaemonClient, this.packagesFile, this.dillFile);
|
||||
|
||||
final BuildDaemonClient buildDaemonClient;
|
||||
@override
|
||||
final File packagesFile;
|
||||
@override
|
||||
final File dillFile;
|
||||
|
||||
@override
|
||||
Stream<bool> get buildResults => buildDaemonClient.buildResults.map((build.BuildResults results) {
|
||||
return results.results.first.status == build.BuildStatus.succeeded;
|
||||
});
|
||||
|
||||
@override
|
||||
void startBuild() {
|
||||
buildDaemonClient.startBuild();
|
||||
}
|
||||
}
|
||||
|
@ -12,12 +12,9 @@ import 'package:dart_style/dart_style.dart';
|
||||
import 'package:graphs/graphs.dart';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/context.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../project.dart';
|
||||
|
||||
BuildScriptGeneratorFactory get buildScriptGeneratorFactory => context[BuildScriptGeneratorFactory];
|
||||
|
||||
class BuildScriptGeneratorFactory {
|
||||
const BuildScriptGeneratorFactory();
|
||||
|
||||
@ -227,14 +224,16 @@ class BuildScriptGenerator {
|
||||
return refer('toNoneByDefault',
|
||||
'package:build_runner_core/build_runner_core.dart')
|
||||
.call(<Expression>[]);
|
||||
case AutoApply.dependents:
|
||||
return refer('toDependentsOf',
|
||||
'package:build_runner_core/build_runner_core.dart')
|
||||
.call(<Expression>[literalString(definition.package)]);
|
||||
// TODO(jonahwilliams): re-enabled when we have the builders strategy fleshed out.
|
||||
// case AutoApply.dependents:
|
||||
// return refer('toDependentsOf',
|
||||
// 'package:build_runner_core/build_runner_core.dart')
|
||||
// .call(<Expression>[literalString(definition.package)]);
|
||||
case AutoApply.allPackages:
|
||||
return refer('toAllPackages',
|
||||
'package:build_runner_core/build_runner_core.dart')
|
||||
.call(<Expression>[]);
|
||||
case AutoApply.dependents:
|
||||
case AutoApply.rootPackage:
|
||||
return refer('toRoot', 'package:build_runner_core/build_runner_core.dart')
|
||||
.call(<Expression>[]);
|
||||
|
@ -99,7 +99,6 @@ Future<void> build({
|
||||
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
|
||||
printTrace('Extra front-end options: $extraFrontEndOptions');
|
||||
ensureDirectoryExists(applicationKernelFilePath);
|
||||
final KernelCompiler kernelCompiler = await kernelCompilerFactory.create();
|
||||
final CompilerOutput compilerOutput = await kernelCompiler.compile(
|
||||
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
incrementalCompilerByteStorePath: compilationTraceFilePath != null ? null :
|
||||
|
293
packages/flutter_tools/lib/src/codegen.dart
Normal file
293
packages/flutter_tools/lib/src/codegen.dart
Normal file
@ -0,0 +1,293 @@
|
||||
// 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:meta/meta.dart';
|
||||
|
||||
import 'artifacts.dart';
|
||||
import 'base/context.dart';
|
||||
import 'base/file_system.dart';
|
||||
import 'base/platform.dart';
|
||||
import 'compile.dart';
|
||||
import 'globals.dart';
|
||||
import 'project.dart';
|
||||
|
||||
const String _kMultiRootScheme = 'org-dartlang-app';
|
||||
|
||||
/// The [CodeGenerator] instance.
|
||||
///
|
||||
/// If [experimentalBuildEnabled] is false, this will contain an unsupported
|
||||
/// implementation.
|
||||
CodeGenerator get codeGenerator => context[CodeGenerator];
|
||||
|
||||
/// Whether to attempt to build a flutter project using build* libraries.
|
||||
///
|
||||
/// This requires both an experimental opt in via the environment variable
|
||||
/// 'FLUTTER_EXPERIMENTAL_BUILD' and that the project itself has a
|
||||
/// dependency on the package 'flutter_build' and 'build_runner.'
|
||||
bool get experimentalBuildEnabled {
|
||||
return _experimentalBuildEnabled ??= platform.environment['FLUTTER_EXPERIMENTAL_BUILD']?.toLowerCase() == 'true';
|
||||
}
|
||||
bool _experimentalBuildEnabled;
|
||||
|
||||
@visibleForTesting
|
||||
set experimentalBuildEnabled(bool value) {
|
||||
_experimentalBuildEnabled = value;
|
||||
}
|
||||
|
||||
/// A wrapper for a build_runner process which delegates to a generated
|
||||
/// build script.
|
||||
///
|
||||
/// This is only enabled if [experimentalBuildEnabled] is true, and only for
|
||||
/// external flutter users.
|
||||
abstract class CodeGenerator {
|
||||
const CodeGenerator();
|
||||
|
||||
/// Run a partial build include code generators but not kernel.
|
||||
Future<void> generate({@required String mainPath}) async {
|
||||
await build(
|
||||
mainPath: mainPath,
|
||||
aot: false,
|
||||
linkPlatformKernelIn: false,
|
||||
trackWidgetCreation: false,
|
||||
targetProductVm: false,
|
||||
disableKernelGeneration: true,
|
||||
);
|
||||
}
|
||||
|
||||
/// Run a full build and return the resulting .packages and dill file.
|
||||
///
|
||||
/// The defines of the build command are the arguments required in the
|
||||
/// flutter_build kernel builder.
|
||||
Future<CodeGenerationResult> build({
|
||||
@required String mainPath,
|
||||
@required bool aot,
|
||||
@required bool linkPlatformKernelIn,
|
||||
@required bool trackWidgetCreation,
|
||||
@required bool targetProductVm,
|
||||
List<String> extraFrontEndOptions = const <String>[],
|
||||
bool disableKernelGeneration = false,
|
||||
});
|
||||
|
||||
/// Starts a persistent code generting daemon.
|
||||
///
|
||||
/// The defines of the daemon command are the arguments required in the
|
||||
/// flutter_build kernel builder.
|
||||
Future<CodegenDaemon> daemon({
|
||||
@required String mainPath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool targetProductVm = false,
|
||||
bool trackWidgetCreation = false,
|
||||
List<String> extraFrontEndOptions = const <String>[],
|
||||
});
|
||||
|
||||
/// Invalidates a generated build script by deleting it.
|
||||
///
|
||||
/// Must be called any time a pubspec file update triggers a corresponding change
|
||||
/// in .packages.
|
||||
Future<void> invalidateBuildScript();
|
||||
|
||||
// Generates a synthetic package under .dart_tool/flutter_tool which is in turn
|
||||
// used to generate a build script.
|
||||
Future<void> generateBuildScript();
|
||||
}
|
||||
|
||||
class UnsupportedCodeGenerator extends CodeGenerator {
|
||||
const UnsupportedCodeGenerator();
|
||||
|
||||
@override
|
||||
Future<CodeGenerationResult> build({
|
||||
String mainPath,
|
||||
bool aot,
|
||||
bool linkPlatformKernelIn,
|
||||
bool trackWidgetCreation,
|
||||
bool targetProductVm,
|
||||
List<String> extraFrontEndOptions = const <String> [],
|
||||
bool disableKernelGeneration = false,
|
||||
}) {
|
||||
throw UnsupportedError('build_runner is not currently supported.');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> generateBuildScript() {
|
||||
throw UnsupportedError('build_runner is not currently supported.');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> invalidateBuildScript() {
|
||||
throw UnsupportedError('build_runner is not currently supported.');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CodegenDaemon> daemon({
|
||||
String mainPath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool targetProductVm = false,
|
||||
bool trackWidgetCreation = false,
|
||||
List<String> extraFrontEndOptions = const <String> [],
|
||||
}) {
|
||||
throw UnsupportedError('build_runner is not currently supported.');
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CodegenDaemon {
|
||||
/// Whether the previously enqueued build was successful.
|
||||
Stream<bool> get buildResults;
|
||||
|
||||
/// Starts a new build.
|
||||
void startBuild();
|
||||
|
||||
File get packagesFile;
|
||||
|
||||
File get dillFile;
|
||||
}
|
||||
|
||||
/// The result of running a build through a [CodeGenerator].
|
||||
///
|
||||
/// If no dill or packages file is generated, they will be null.
|
||||
class CodeGenerationResult {
|
||||
const CodeGenerationResult(this.packagesFile, this.dillFile);
|
||||
|
||||
final File packagesFile;
|
||||
final File dillFile;
|
||||
}
|
||||
|
||||
/// An implementation of the [KernelCompiler] which delegates to build_runner.
|
||||
///
|
||||
/// Only a subset of the arguments provided to the [KernelCompiler] are
|
||||
/// supported here. Using the build pipeline implies a fixed multiroot
|
||||
/// filesystem and requires a pubspec.
|
||||
///
|
||||
/// This is only safe to use if [experimentalBuildEnabled] is true.
|
||||
class CodeGeneratingKernelCompiler implements KernelCompiler {
|
||||
const CodeGeneratingKernelCompiler();
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> compile({
|
||||
String mainPath,
|
||||
String outputFilePath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool aot = false,
|
||||
bool trackWidgetCreation,
|
||||
List<String> extraFrontEndOptions,
|
||||
String incrementalCompilerByteStorePath,
|
||||
bool targetProductVm = false,
|
||||
// These arguments are currently unused.
|
||||
String sdkRoot,
|
||||
String packagesPath,
|
||||
List<String> fileSystemRoots,
|
||||
String fileSystemScheme,
|
||||
String depFilePath,
|
||||
TargetModel targetModel = TargetModel.flutter,
|
||||
}) async {
|
||||
if (fileSystemRoots != null || fileSystemScheme != null || depFilePath != null || targetModel != null || sdkRoot != null || packagesPath != null) {
|
||||
printTrace('fileSystemRoots, fileSystemScheme, depFilePath, targetModel,'
|
||||
'sdkRoot, packagesPath are not supported when using the experimental '
|
||||
'build* pipeline');
|
||||
}
|
||||
try {
|
||||
final CodeGenerationResult buildResult = await codeGenerator.build(
|
||||
aot: aot,
|
||||
linkPlatformKernelIn: linkPlatformKernelIn,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
mainPath: mainPath,
|
||||
targetProductVm: targetProductVm,
|
||||
extraFrontEndOptions: extraFrontEndOptions
|
||||
);
|
||||
final File outputFile = fs.file(outputFilePath);
|
||||
if (!await outputFile.exists()) {
|
||||
await outputFile.create();
|
||||
}
|
||||
await outputFile.writeAsBytes(await buildResult.dillFile.readAsBytes());
|
||||
return CompilerOutput(outputFilePath, 0);
|
||||
} on Exception catch (err) {
|
||||
printError('Compilation Failed: $err');
|
||||
return const CompilerOutput(null, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An implementation of a [ResidentCompiler] which runs a [BuildRunner] before
|
||||
/// talking to the CFE.
|
||||
class CodeGeneratingResidentCompiler implements ResidentCompiler {
|
||||
CodeGeneratingResidentCompiler._(this._residentCompiler, this._codegenDaemon);
|
||||
|
||||
/// Creates a new [ResidentCompiler] and configures a [BuildDaemonClient] to
|
||||
/// run builds.
|
||||
static Future<CodeGeneratingResidentCompiler> create({
|
||||
@required String mainPath,
|
||||
bool trackWidgetCreation = false,
|
||||
CompilerMessageConsumer compilerMessageConsumer = printError,
|
||||
bool unsafePackageSerialization = false,
|
||||
}) async {
|
||||
final FlutterProject flutterProject = await FlutterProject.current();
|
||||
final CodegenDaemon codegenDaemon = await codeGenerator.daemon(
|
||||
extraFrontEndOptions: <String>[],
|
||||
linkPlatformKernelIn: false,
|
||||
mainPath: mainPath,
|
||||
targetProductVm: false,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
);
|
||||
codegenDaemon.startBuild();
|
||||
await codegenDaemon.buildResults.firstWhere((bool result) => result);
|
||||
final ResidentCompiler residentCompiler = ResidentCompiler(
|
||||
artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
packagesPath: codegenDaemon.packagesFile.path,
|
||||
fileSystemRoots: <String>[
|
||||
flutterProject.generated.absolute.path,
|
||||
flutterProject.directory.path,
|
||||
],
|
||||
fileSystemScheme: _kMultiRootScheme,
|
||||
targetModel: TargetModel.flutter,
|
||||
unsafePackageSerialization: unsafePackageSerialization,
|
||||
);
|
||||
return CodeGeneratingResidentCompiler._(residentCompiler, codegenDaemon);
|
||||
}
|
||||
|
||||
final ResidentCompiler _residentCompiler;
|
||||
final CodegenDaemon _codegenDaemon;
|
||||
|
||||
@override
|
||||
void accept() {
|
||||
_residentCompiler.accept();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> compileExpression(String expression, List<String> definitions, List<String> typeDefinitions, String libraryUri, String klass, bool isStatic) {
|
||||
return _residentCompiler.compileExpression(expression, definitions, typeDefinitions, libraryUri, klass, isStatic);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> recompile(String mainPath, List<String> invalidatedFiles, {String outputPath, String packagesFilePath}) async {
|
||||
_codegenDaemon.startBuild();
|
||||
await _codegenDaemon.buildResults.first;
|
||||
// Delete this file so that the frontend_server can handle multi-root.
|
||||
// TODO(jonahwilliams): investigate frontend_server behavior in the presence
|
||||
// of multi-root and initialize from dill.
|
||||
if (await fs.file(outputPath).exists()) {
|
||||
await fs.file(outputPath).delete();
|
||||
}
|
||||
return _residentCompiler.recompile(
|
||||
mainPath,
|
||||
invalidatedFiles,
|
||||
outputPath: outputPath,
|
||||
packagesFilePath: _codegenDaemon.packagesFile.path,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> reject() {
|
||||
return _residentCompiler.reject();
|
||||
}
|
||||
|
||||
@override
|
||||
void reset() {
|
||||
_residentCompiler.reset();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> shutdown() {
|
||||
return _residentCompiler.shutdown();
|
||||
}
|
||||
}
|
30
packages/flutter_tools/lib/src/commands/generate.dart
Normal file
30
packages/flutter_tools/lib/src/commands/generate.dart
Normal file
@ -0,0 +1,30 @@
|
||||
// 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/common.dart';
|
||||
import '../codegen.dart';
|
||||
import '../runner/flutter_command.dart';
|
||||
|
||||
class GenerateCommand extends FlutterCommand {
|
||||
GenerateCommand() {
|
||||
usesTargetOption();
|
||||
}
|
||||
@override
|
||||
String get description => 'run code generators.';
|
||||
|
||||
@override
|
||||
String get name => 'generate';
|
||||
|
||||
@override
|
||||
bool get hidden => true;
|
||||
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
if (!experimentalBuildEnabled) {
|
||||
throwToolExit('FLUTTER_EXPERIMENTAL_BUILD is not enabled, codegen is unsupported.');
|
||||
}
|
||||
await codeGenerator.generate(mainPath: argResults['target']);
|
||||
return null;
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ 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';
|
||||
@ -345,6 +347,10 @@ class RunCommand extends RunCommandBase {
|
||||
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(
|
||||
device,
|
||||
@ -354,6 +360,7 @@ class RunCommand extends RunCommandBase {
|
||||
fileSystemScheme: argResults['filesystem-scheme'],
|
||||
viewFilter: argResults['isolate-filter'],
|
||||
experimentalFlags: expFlags,
|
||||
generator: residentCompiler,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
|
@ -390,7 +390,7 @@ class _DependencyLink {
|
||||
/// "dependency_overrides" sections, as well as the "name" and "version" fields
|
||||
/// in the pubspec header bucketed into [header]. The others are all bucketed
|
||||
/// into [other].
|
||||
enum Section { header, dependencies, devDependencies, dependencyOverrides, other }
|
||||
enum Section { header, dependencies, devDependencies, dependencyOverrides, builders, other }
|
||||
|
||||
/// The various kinds of dependencies we know and care about.
|
||||
enum DependencyKind {
|
||||
@ -504,6 +504,11 @@ class PubspecYaml {
|
||||
seenDev = true;
|
||||
}
|
||||
result.add(header);
|
||||
} else if (section == Section.builders) {
|
||||
// Do nothing.
|
||||
// This line isn't a section header, and we're not in a section we care about.
|
||||
// We just stick the line into the output unmodified.
|
||||
result.add(PubspecLine(line));
|
||||
} else if (section == Section.other) {
|
||||
if (line.contains(kDependencyChecksum)) {
|
||||
// This is the pubspec checksum. After computing it, we remove it from the output data
|
||||
@ -878,6 +883,8 @@ class PubspecHeader extends PubspecLine {
|
||||
return PubspecHeader(line, Section.devDependencies);
|
||||
case 'dependency_overrides':
|
||||
return PubspecHeader(line, Section.dependencyOverrides);
|
||||
case 'builders':
|
||||
return PubspecHeader(line, Section.builders);
|
||||
case 'name':
|
||||
case 'version':
|
||||
return PubspecHeader(line, Section.header, name: sectionName, value: value);
|
||||
|
@ -20,21 +20,10 @@ import 'convert.dart';
|
||||
import 'dart/package_map.dart';
|
||||
import 'globals.dart';
|
||||
|
||||
KernelCompilerFactory get kernelCompilerFactory => context[KernelCompilerFactory];
|
||||
KernelCompiler get kernelCompiler => context[KernelCompiler];
|
||||
|
||||
typedef CompilerMessageConsumer = void Function(String message, {bool emphasis, TerminalColor color});
|
||||
|
||||
/// Injectable factory to allow async construction of a [KernelCompiler].
|
||||
class KernelCompilerFactory {
|
||||
const KernelCompilerFactory();
|
||||
|
||||
/// Return the correct [KernelCompiler] instance for the given project
|
||||
/// configuration.
|
||||
FutureOr<KernelCompiler> create() async {
|
||||
return const KernelCompiler();
|
||||
}
|
||||
}
|
||||
|
||||
/// The target model describes the set of core libraries that are availible within
|
||||
/// the SDK.
|
||||
class TargetModel {
|
||||
|
@ -22,6 +22,7 @@ import 'base/time.dart';
|
||||
import 'base/user_messages.dart';
|
||||
import 'base/utils.dart';
|
||||
import 'cache.dart';
|
||||
import 'codegen.dart';
|
||||
import 'compile.dart';
|
||||
import 'devfs.dart';
|
||||
import 'device.dart';
|
||||
@ -80,7 +81,7 @@ Future<T> runInContext<T>(
|
||||
IOSSimulatorUtils: () => IOSSimulatorUtils(),
|
||||
IOSWorkflow: () => const IOSWorkflow(),
|
||||
IOSValidator: () => const IOSValidator(),
|
||||
KernelCompilerFactory: () => const KernelCompilerFactory(),
|
||||
KernelCompiler: () => experimentalBuildEnabled ? const CodeGeneratingKernelCompiler() : const KernelCompiler(),
|
||||
LinuxWorkflow: () => const LinuxWorkflow(),
|
||||
Logger: () => platform.isWindows ? WindowsStdoutLogger() : StdoutLogger(),
|
||||
MacOSWorkflow: () => const MacOSWorkflow(),
|
||||
|
@ -107,6 +107,13 @@ class FlutterProject {
|
||||
/// The `.dart-tool` directory of this project.
|
||||
Directory get dartTool => directory.childDirectory('.dart_tool');
|
||||
|
||||
/// The directory containing the generated code for this project.
|
||||
Directory get generated => directory
|
||||
.childDirectory('.dart_tool')
|
||||
.childDirectory('build')
|
||||
.childDirectory('generated')
|
||||
.childDirectory(manifest.appName);
|
||||
|
||||
/// The example sub-project of this project.
|
||||
FlutterProject get example => FlutterProject(
|
||||
_exampleDirectory(directory),
|
||||
@ -147,15 +154,9 @@ class FlutterProject {
|
||||
}
|
||||
|
||||
/// Return the set of builders used by this package.
|
||||
Future<List<String>> get builders async {
|
||||
Future<YamlMap> get builders async {
|
||||
final YamlMap pubspec = loadYaml(await pubspecFile.readAsString());
|
||||
final YamlList builders = pubspec['builders'];
|
||||
if (builders == null) {
|
||||
return <String>[];
|
||||
}
|
||||
return builders.map<String>((Object node) {
|
||||
return node.toString();
|
||||
}).toList();
|
||||
return pubspec['builders'];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ import 'base/logger.dart';
|
||||
import 'base/terminal.dart';
|
||||
import 'base/utils.dart';
|
||||
import 'build_info.dart';
|
||||
import 'codegen.dart';
|
||||
import 'compile.dart';
|
||||
import 'dart/dependencies.dart';
|
||||
import 'dart/package_map.dart';
|
||||
@ -895,6 +896,11 @@ abstract class ResidentRunner {
|
||||
}
|
||||
|
||||
bool hasDirtyDependencies(FlutterDevice device) {
|
||||
/// When using the build system, dependency analysis is handled by build
|
||||
/// runner instead.
|
||||
if (experimentalBuildEnabled) {
|
||||
return false;
|
||||
}
|
||||
final DartDependencySetBuilder dartDependencySetBuilder =
|
||||
DartDependencySetBuilder(mainPath, packagesFilePath);
|
||||
final DependencyChecker dependencyChecker =
|
||||
|
@ -15,6 +15,7 @@ import 'base/logger.dart';
|
||||
import 'base/terminal.dart';
|
||||
import 'base/utils.dart';
|
||||
import 'build_info.dart';
|
||||
import 'codegen.dart';
|
||||
import 'compile.dart';
|
||||
import 'convert.dart';
|
||||
import 'dart/dependencies.dart';
|
||||
@ -122,8 +123,12 @@ class HotRunner extends ResidentRunner {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DartDependencySetBuilder dartDependencySetBuilder =
|
||||
DartDependencySetBuilder(mainPath, packagesFilePath);
|
||||
/// When using the build system, dependency analysis is handled by build
|
||||
/// runner instead.
|
||||
if (experimentalBuildEnabled) {
|
||||
return true;
|
||||
}
|
||||
final DartDependencySetBuilder dartDependencySetBuilder = DartDependencySetBuilder(mainPath, packagesFilePath);
|
||||
try {
|
||||
_dartDependencies = Set<String>.from(dartDependencySetBuilder.build());
|
||||
} on DartDependencyException catch (error) {
|
||||
|
@ -39,10 +39,6 @@ dependencies:
|
||||
flutter_goldens_client:
|
||||
path: ../flutter_goldens_client
|
||||
|
||||
# build_runner depenencies needed for codegen.
|
||||
build: 1.1.1
|
||||
build_modules: 1.0.7
|
||||
|
||||
# We depend on very specific internal implementation details of the
|
||||
# 'test' package, which change between versions, so when upgrading
|
||||
# this, make sure the tests are still running correctly.
|
||||
@ -53,6 +49,9 @@ dependencies:
|
||||
build_runner_core: 2.0.3
|
||||
dart_style: 1.2.3
|
||||
code_builder: 3.2.0
|
||||
build: 1.1.1
|
||||
build_modules: 1.0.7+2
|
||||
build_daemon: 0.4.0
|
||||
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
bazel_worker: 0.1.20 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@ -85,9 +84,12 @@ dependencies:
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pubspec_parse: 0.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
scratch_space: 0.0.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf_web_socket: 0.2.2+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_transform: 0.0.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
timing: 0.1.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@ -106,14 +108,12 @@ dev_dependencies:
|
||||
mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf_web_socket: 0.2.2+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
test: 1.5.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
|
||||
dartdoc:
|
||||
# Exclude this package from the hosted API docs.
|
||||
nodoc: true
|
||||
|
||||
# PUBSPEC CHECKSUM: c962
|
||||
# PUBSPEC CHECKSUM: 6c3e
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/build_runner/build_runner.dart';
|
||||
import 'package:flutter_tools/src/codegen.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
|
@ -3,8 +3,8 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/build_runner/build_kernel_compiler.dart';
|
||||
import 'package:flutter_tools/src/build_runner/build_runner.dart';
|
||||
import 'package:flutter_tools/src/codegen.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
@ -12,8 +12,7 @@ import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
|
||||
void main() {
|
||||
group(BuildKernelCompiler, () {
|
||||
final MockBuildRunnerFactory mockBuildRunnerFactory = MockBuildRunnerFactory();
|
||||
group(CodeGeneratingKernelCompiler, () {
|
||||
final MockBuildRunner mockBuildRunner = MockBuildRunner();
|
||||
final MockFileSystem mockFileSystem = MockFileSystem();
|
||||
final MockFile packagesFile = MockFile();
|
||||
@ -26,11 +25,10 @@ void main() {
|
||||
when(packagesFile.exists()).thenAnswer((Invocation invocation) async => true);
|
||||
when(dillFile.exists()).thenAnswer((Invocation invocation) async => true);
|
||||
when(outputFile.exists()).thenAnswer((Invocation invocation) async => true);
|
||||
when(mockBuildRunnerFactory.create()).thenReturn(mockBuildRunner);
|
||||
when(dillFile.readAsBytes()).thenAnswer((Invocation invocation) async => <int>[0, 1, 2, 3]);
|
||||
|
||||
testUsingContext('delegates to build_runner', () async {
|
||||
const BuildKernelCompiler kernelCompiler = BuildKernelCompiler();
|
||||
const CodeGeneratingKernelCompiler kernelCompiler = CodeGeneratingKernelCompiler();
|
||||
when(mockBuildRunner.build(
|
||||
aot: anyNamed('aot'),
|
||||
extraFrontEndOptions: anyNamed('extraFrontEndOptions'),
|
||||
@ -39,7 +37,7 @@ void main() {
|
||||
targetProductVm: anyNamed('targetProductVm'),
|
||||
trackWidgetCreation: anyNamed('trackWidgetCreation')
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
return BuildResult(fs.file('.packages'), fs.file('main.app.dill'));
|
||||
return CodeGenerationResult(fs.file('.packages'), fs.file('main.app.dill'));
|
||||
});
|
||||
final CompilerOutput buildResult = await kernelCompiler.compile(
|
||||
outputFilePath: 'output.app.dill',
|
||||
@ -48,13 +46,12 @@ void main() {
|
||||
expect(buildResult.errorCount, 0);
|
||||
verify(outputFile.writeAsBytes(<int>[0, 1, 2, 3])).called(1);
|
||||
}, overrides: <Type, Generator>{
|
||||
BuildRunnerFactory: () => mockBuildRunnerFactory,
|
||||
CodeGenerator: () => mockBuildRunner,
|
||||
FileSystem: () => mockFileSystem,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class MockBuildRunnerFactory extends Mock implements BuildRunnerFactory {}
|
||||
class MockBuildRunner extends Mock implements BuildRunner {}
|
||||
class MockFileSystem extends Mock implements FileSystem {}
|
||||
class MockFile extends Mock implements File {}
|
@ -118,7 +118,6 @@ example:org-dartlang-app:/
|
||||
'result abc\nline1\nline2\nabc /path/to/main.dart.dill 0'
|
||||
))
|
||||
));
|
||||
final KernelCompiler kernelCompiler = await kernelCompilerFactory.create();
|
||||
final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
|
||||
mainPath: '/path/to/main.dart',
|
||||
trackWidgetCreation: false,
|
||||
@ -142,7 +141,6 @@ example:org-dartlang-app:/
|
||||
'result abc\nline1\nline2\nabc'
|
||||
))
|
||||
));
|
||||
final KernelCompiler kernelCompiler = await kernelCompilerFactory.create();
|
||||
final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
|
||||
mainPath: '/path/to/main.dart',
|
||||
trackWidgetCreation: false,
|
||||
@ -168,7 +166,6 @@ example:org-dartlang-app:/
|
||||
'result abc\nline1\nline2\nabc'
|
||||
))
|
||||
));
|
||||
final KernelCompiler kernelCompiler = await kernelCompilerFactory.create();
|
||||
final CompilerOutput output = await kernelCompiler.compile(
|
||||
sdkRoot: '/path/to/sdkroot',
|
||||
mainPath: '/path/to/main.dart',
|
||||
|
@ -78,6 +78,34 @@ void main() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('no unauthorized imports of build_runner', () {
|
||||
final List<String> whitelistedPaths = <String>[
|
||||
fs.path.join(flutterTools, 'test', 'src', 'build_runner'),
|
||||
fs.path.join(flutterTools, 'lib', 'src', 'build_runner'),
|
||||
fs.path.join(flutterTools, 'lib', 'executable.dart')
|
||||
];
|
||||
bool _isNotWhitelisted(FileSystemEntity entity) => whitelistedPaths.every((String path) => !entity.path.contains(path));
|
||||
|
||||
for (String dirName in <String>['lib']) {
|
||||
final Iterable<File> files = fs.directory(fs.path.join(flutterTools, dirName))
|
||||
.listSync(recursive: true)
|
||||
.where(_isDartFile)
|
||||
.where(_isNotWhitelisted)
|
||||
.map(_asFile);
|
||||
for (File file in files) {
|
||||
for (String line in file.readAsLinesSync()) {
|
||||
if (line.startsWith(RegExp(r'import.*package:build_runner_core/build_runner_core.dart')) ||
|
||||
line.startsWith(RegExp(r'import.*package:build_runner/build_runner.dart')) ||
|
||||
line.startsWith(RegExp(r'import.*package:build_config/build_config.dart')) ||
|
||||
line.startsWith(RegExp(r'import.*build_runner/.*.dart'))) {
|
||||
final String relativePath = fs.path.relative(file.path, from:flutterTools);
|
||||
fail('$relativePath imports a build_runner package');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool _isDartFile(FileSystemEntity entity) => entity is File && entity.path.endsWith('.dart');
|
||||
|
@ -102,7 +102,6 @@ void main() {
|
||||
MockArtifacts mockArtifacts;
|
||||
MockKernelCompiler mockKernelCompiler;
|
||||
MockProcessManager mockProcessManager;
|
||||
MockKernelCompilerFactory mockKernelCompilerFactory;
|
||||
MockProcess mockProcess;
|
||||
|
||||
final Map<Type, Generator> startOverrides = <Type, Generator>{
|
||||
@ -110,7 +109,7 @@ void main() {
|
||||
FileSystem: () => fs,
|
||||
Cache: () => Cache(rootOverride: fs.directory(flutterRoot)),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
KernelCompilerFactory: () => mockKernelCompilerFactory,
|
||||
KernelCompiler: () => mockKernelCompiler,
|
||||
Artifacts: () => mockArtifacts,
|
||||
};
|
||||
|
||||
@ -136,10 +135,6 @@ void main() {
|
||||
when(mockArtifacts.getArtifactPath(any)).thenReturn(artifactPath);
|
||||
|
||||
mockKernelCompiler = MockKernelCompiler();
|
||||
mockKernelCompilerFactory = MockKernelCompilerFactory();
|
||||
when(mockKernelCompilerFactory.create()).thenAnswer((Invocation invocation) async {
|
||||
return mockKernelCompiler;
|
||||
});
|
||||
});
|
||||
|
||||
testUsingContext('not debug', () async {
|
||||
@ -199,4 +194,3 @@ Hello!
|
||||
|
||||
class MockArtifacts extends Mock implements Artifacts {}
|
||||
class MockKernelCompiler extends Mock implements KernelCompiler {}
|
||||
class MockKernelCompilerFactory extends Mock implements KernelCompilerFactory {}
|
||||
|
Loading…
Reference in New Issue
Block a user