Use new Maven artifacts from Gradle (#39157)
This commit is contained in:
parent
d30e4228af
commit
b63cb44105
@ -52,7 +52,6 @@ Future<void> main() async {
|
|||||||
'assets/flutter_assets/isolate_snapshot_data',
|
'assets/flutter_assets/isolate_snapshot_data',
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
'assets/flutter_assets/kernel_blob.bin',
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
'assets/flutter_assets/vm_snapshot_data',
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
|
||||||
// Debug mode intentionally includes `x86` and `x86_64`.
|
// Debug mode intentionally includes `x86` and `x86_64`.
|
||||||
'lib/x86/libflutter.so',
|
'lib/x86/libflutter.so',
|
||||||
'lib/x86_64/libflutter.so',
|
'lib/x86_64/libflutter.so',
|
||||||
@ -79,7 +78,6 @@ Future<void> main() async {
|
|||||||
'assets/flutter_assets/isolate_snapshot_data',
|
'assets/flutter_assets/isolate_snapshot_data',
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
'assets/flutter_assets/kernel_blob.bin',
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
'assets/flutter_assets/vm_snapshot_data',
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
|
||||||
// Debug mode intentionally includes `x86` and `x86_64`.
|
// Debug mode intentionally includes `x86` and `x86_64`.
|
||||||
'lib/x86/libflutter.so',
|
'lib/x86/libflutter.so',
|
||||||
'lib/x86_64/libflutter.so',
|
'lib/x86_64/libflutter.so',
|
||||||
|
@ -57,6 +57,6 @@ dependencies {
|
|||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||||
implementation 'com.android.support:appcompat-v7:26.1.0'
|
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||||
implementation 'com.android.support:design:26.1.0'
|
implementation 'com.android.support:design:28.0.0'
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
classpath "com.android.tools.build:gradle:3.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +42,8 @@ android {
|
|||||||
apply plugin: FlutterPlugin
|
apply plugin: FlutterPlugin
|
||||||
|
|
||||||
class FlutterPlugin implements Plugin<Project> {
|
class FlutterPlugin implements Plugin<Project> {
|
||||||
|
private static final String MAVEN_REPO = "http://download.flutter.io";
|
||||||
|
|
||||||
// The platforms that can be passed to the `--Ptarget-platform` flag.
|
// The platforms that can be passed to the `--Ptarget-platform` flag.
|
||||||
private static final String PLATFORM_ARM32 = "android-arm";
|
private static final String PLATFORM_ARM32 = "android-arm";
|
||||||
private static final String PLATFORM_ARM64 = "android-arm64";
|
private static final String PLATFORM_ARM64 = "android-arm64";
|
||||||
@ -85,6 +87,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
// to match.
|
// to match.
|
||||||
static final String FLUTTER_BUILD_PREFIX = "flutterBuild"
|
static final String FLUTTER_BUILD_PREFIX = "flutterBuild"
|
||||||
|
|
||||||
|
private Project project
|
||||||
private Map baseJar = [:]
|
private Map baseJar = [:]
|
||||||
private File flutterRoot
|
private File flutterRoot
|
||||||
private File flutterExecutable
|
private File flutterExecutable
|
||||||
@ -92,16 +95,18 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
private String localEngineSrcPath
|
private String localEngineSrcPath
|
||||||
private Properties localProperties
|
private Properties localProperties
|
||||||
private File flutterJar
|
private File flutterJar
|
||||||
|
private String engineVersion
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void apply(Project project) {
|
void apply(Project project) {
|
||||||
|
this.project = project
|
||||||
|
|
||||||
project.extensions.create("flutter", FlutterExtension)
|
project.extensions.create("flutter", FlutterExtension)
|
||||||
project.afterEvaluate this.&addFlutterTasks
|
project.afterEvaluate this.&addFlutterTasks
|
||||||
|
|
||||||
// By default, assembling APKs generates fat APKs if multiple platforms are passed.
|
// By default, assembling APKs generates fat APKs if multiple platforms are passed.
|
||||||
// Configuring split per ABI allows to generate separate APKs for each abi.
|
// Configuring split per ABI allows to generate separate APKs for each abi.
|
||||||
// This is a noop when building a bundle.
|
// This is a noop when building a bundle.
|
||||||
if (splitPerAbi(project)) {
|
if (shouldSplitPerAbi()) {
|
||||||
project.android {
|
project.android {
|
||||||
splits {
|
splits {
|
||||||
abi {
|
abi {
|
||||||
@ -115,14 +120,10 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getTargetPlatforms(project).each { targetArch ->
|
getTargetPlatforms().each { targetArch ->
|
||||||
String abiValue = PLATFORM_ARCH_MAP[targetArch]
|
String abiValue = PLATFORM_ARCH_MAP[targetArch]
|
||||||
project.android {
|
project.android {
|
||||||
packagingOptions {
|
if (shouldSplitPerAbi()) {
|
||||||
// Prevent the ELF library from getting corrupted.
|
|
||||||
doNotStrip "*/${abiValue}/libapp.so"
|
|
||||||
}
|
|
||||||
if (splitPerAbi(project)) {
|
|
||||||
splits {
|
splits {
|
||||||
abi {
|
abi {
|
||||||
include abiValue
|
include abiValue
|
||||||
@ -131,7 +132,6 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add custom build types
|
// Add custom build types
|
||||||
project.android.buildTypes {
|
project.android.buildTypes {
|
||||||
profile {
|
profile {
|
||||||
@ -141,8 +141,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
String flutterRootPath = resolveProperty("flutter.sdk", System.env.FLUTTER_ROOT)
|
||||||
String flutterRootPath = resolveProperty(project, "flutter.sdk", System.env.FLUTTER_ROOT)
|
|
||||||
if (flutterRootPath == null) {
|
if (flutterRootPath == null) {
|
||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file or with a FLUTTER_ROOT environment variable.")
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file or with a FLUTTER_ROOT environment variable.")
|
||||||
}
|
}
|
||||||
@ -151,12 +150,14 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
throw new GradleException("flutter.sdk must point to the Flutter SDK directory")
|
throw new GradleException("flutter.sdk must point to the Flutter SDK directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engineVersion = Paths.get(flutterRoot.absolutePath, "bin", "internal", "engine.version")
|
||||||
|
.toFile().text.trim()
|
||||||
|
|
||||||
String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter"
|
String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter"
|
||||||
flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile();
|
flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile();
|
||||||
|
|
||||||
if (useLocalEngine(project)) {
|
if (useLocalEngine()) {
|
||||||
String engineOutPath = project.property('localEngineOut')
|
File engineOut = project.file(project.property('localEngineOut'))
|
||||||
File engineOut = project.file(engineOutPath)
|
|
||||||
if (!engineOut.isDirectory()) {
|
if (!engineOut.isDirectory()) {
|
||||||
throw new GradleException('localEngineOut must point to a local engine build')
|
throw new GradleException('localEngineOut must point to a local engine build')
|
||||||
}
|
}
|
||||||
@ -175,45 +176,48 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String basePlatformArch = getBasePlatform(project)
|
project.android.buildTypes.each this.&addFlutterDependencies
|
||||||
// This is meant to include the compiled classes only, however it will include `libflutter.so` as well.
|
project.android.buildTypes.whenObjectAdded this.&addFlutterDependencies
|
||||||
Path baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine")
|
|
||||||
File debugJar = baseEnginePath.resolve("${basePlatformArch}").resolve("flutter.jar").toFile()
|
|
||||||
baseJar["debug"] = debugJar
|
|
||||||
if (!debugJar.isFile()) {
|
|
||||||
project.exec {
|
|
||||||
executable flutterExecutable.absolutePath
|
|
||||||
args "--suppress-analytics"
|
|
||||||
args "precache"
|
|
||||||
}
|
|
||||||
if (!debugJar.isFile()) {
|
|
||||||
throw new GradleException("Unable to find flutter.jar in SDK: ${debugJar}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
baseJar["profile"] = baseEnginePath.resolve("${basePlatformArch}-profile").resolve("flutter.jar").toFile()
|
|
||||||
baseJar["release"] = baseEnginePath.resolve("${basePlatformArch}-release").resolve("flutter.jar").toFile()
|
|
||||||
|
|
||||||
// Add flutter.jar dependencies to all <buildType>Api configurations, including custom ones
|
/**
|
||||||
// added after applying the Flutter plugin.
|
* Adds the dependencies required by the Flutter project.
|
||||||
project.android.buildTypes.each {
|
* This includes:
|
||||||
def buildMode = buildModeFor(it)
|
* 1. The embedding
|
||||||
addApiDependencies(project, it.name, project.files {
|
* 2. libflutter.so
|
||||||
baseJar[buildMode]
|
*/
|
||||||
})
|
void addFlutterDependencies(buildType) {
|
||||||
|
project.rootProject.allprojects {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url MAVEN_REPO
|
||||||
}
|
}
|
||||||
project.android.buildTypes.whenObjectAdded {
|
|
||||||
def buildMode = buildModeFor(it)
|
|
||||||
addApiDependencies(project, it.name, project.files {
|
|
||||||
baseJar[buildMode]
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
String flutterBuildMode = buildModeFor(buildType)
|
||||||
|
// Add the embedding dependency.
|
||||||
|
addApiDependencies(project, buildType.name,
|
||||||
|
"io.flutter:flutter_embedding_$flutterBuildMode:1.0.0-$engineVersion")
|
||||||
|
|
||||||
|
List<String> platforms = getTargetPlatforms().collect()
|
||||||
|
// Debug mode includes x86 and x64, which are commonly used in emulators.
|
||||||
|
if (flutterBuildMode == "debug") {
|
||||||
|
platforms.add("android-x86")
|
||||||
|
platforms.add("android-x64")
|
||||||
|
}
|
||||||
|
platforms.each { platform ->
|
||||||
|
String arch = PLATFORM_ARCH_MAP[platform].replace("-", "_")
|
||||||
|
// Add the `libflutter.so` dependency.
|
||||||
|
addApiDependencies(project, buildType.name,
|
||||||
|
"io.flutter:${arch}_$flutterBuildMode:1.0.0-$engineVersion")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the directory where the plugins are built.
|
* Returns the directory where the plugins are built.
|
||||||
*/
|
*/
|
||||||
private File getPluginBuildDir(Project project) {
|
private File getPluginBuildDir() {
|
||||||
// Module projects specify this flag to include plugins in the same repo as the module project.
|
// Module projects specify this flag to include plugins in the same repo as the module project.
|
||||||
if (project.ext.has("pluginBuildDir")) {
|
if (project.ext.has("pluginBuildDir")) {
|
||||||
return project.ext.get("pluginBuildDir")
|
return project.ext.get("pluginBuildDir")
|
||||||
@ -221,13 +225,75 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
return project.buildDir
|
return project.buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
private Properties getPluginList(Project project) {
|
/**
|
||||||
|
* Configures the Flutter plugin dependencies.
|
||||||
|
*
|
||||||
|
* The plugins are added to pubspec.yaml. Then, upon running `flutter pub get`,
|
||||||
|
* the tool generates a `.flutter-plugins` file, which contains a 1:1 map to each plugin location.
|
||||||
|
* Finally, the project's `settings.gradle` loads each plugin's android directory as a subproject.
|
||||||
|
*/
|
||||||
|
private void configurePlugins() {
|
||||||
|
if (!buildPluginAsAar()) {
|
||||||
|
getPluginList().each this.&configurePlugin
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addPluginTasks()
|
||||||
|
List<String> tasksToExecute = project.gradle.startParameter.taskNames
|
||||||
|
Set buildTypes = getBuildTypesForTasks(tasksToExecute)
|
||||||
|
if (tasksToExecute.contains("clean")) {
|
||||||
|
// Because the plugins are built during configuration, the task "clean"
|
||||||
|
// cannot run in conjunction with an assembly task.
|
||||||
|
if (!buildTypes.empty) {
|
||||||
|
throw new GradleException("Can't run the clean task along with other assemble tasks")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Build plugins when a task "assembly*" will be called later.
|
||||||
|
if (!buildTypes.empty) {
|
||||||
|
// Build the plugin during configuration.
|
||||||
|
// This is required when Jetifier is enabled, otherwise the implementation dependency
|
||||||
|
// cannot be added.
|
||||||
|
buildAarPlugins(buildTypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configurePlugin(String name, String _) {
|
||||||
|
Project pluginProject = project.rootProject.findProject(":$name")
|
||||||
|
if (pluginProject == null) {
|
||||||
|
project.logger.error("Plugin project :$name not found. Please update settings.gradle.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Add plugin dependency to the app project.
|
||||||
|
project.dependencies {
|
||||||
|
if (project.getConfigurations().findByName("implementation")) {
|
||||||
|
implementation pluginProject
|
||||||
|
} else {
|
||||||
|
compile pluginProject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Closure addEmbeddingCompileOnlyDependency = { buildType ->
|
||||||
|
String flutterBuildMode = buildModeFor(buildType)
|
||||||
|
// Add the embedding as a compile only dependency to the plugin.
|
||||||
|
addFlutterJarCompileOnlyDependency(pluginProject, buildType.name,
|
||||||
|
flutterJar ?: "io.flutter:flutter_embedding_$flutterBuildMode:1.0.0-$engineVersion")
|
||||||
|
}
|
||||||
|
pluginProject.afterEvaluate {
|
||||||
|
pluginProject.android.buildTypes {
|
||||||
|
profile {
|
||||||
|
initWith debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pluginProject.android.buildTypes.each addEmbeddingCompileOnlyDependency
|
||||||
|
pluginProject.android.buildTypes.whenObjectAdded addEmbeddingCompileOnlyDependency
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties getPluginList() {
|
||||||
File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins')
|
File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins')
|
||||||
return readPropertiesIfExist(pluginsFile)
|
return readPropertiesIfExist(pluginsFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPluginTasks(Project project) {
|
private void addPluginTasks() {
|
||||||
Properties plugins = getPluginList(project)
|
Properties plugins = getPluginList()
|
||||||
project.android.buildTypes.each { buildType ->
|
project.android.buildTypes.each { buildType ->
|
||||||
plugins.each { name, path ->
|
plugins.each { name, path ->
|
||||||
String buildModeValue = buildType.debuggable ? "debug" : "release"
|
String buildModeValue = buildType.debuggable ? "debug" : "release"
|
||||||
@ -240,17 +306,17 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
project.tasks.create(name: taskName, type: FlutterPluginTask) {
|
project.tasks.create(name: taskName, type: FlutterPluginTask) {
|
||||||
flutterExecutable this.flutterExecutable
|
flutterExecutable this.flutterExecutable
|
||||||
buildMode buildModeValue
|
buildMode buildModeValue
|
||||||
verbose isVerbose(project)
|
verbose isVerbose()
|
||||||
pluginDir project.file(path)
|
pluginDir project.file(path)
|
||||||
sourceDir project.file(project.flutter.source)
|
sourceDir project.file(project.flutter.source)
|
||||||
intermediateDir getPluginBuildDir(project)
|
intermediateDir getPluginBuildDir()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildPlugins(Project project, Set buildTypes) {
|
private void buildAarPlugins(Set buildTypes) {
|
||||||
List<Project> projects = [project]
|
List<Project> projects = [project]
|
||||||
// Module projects set the `hostProjects` extra property in `include_flutter.groovy`.
|
// Module projects set the `hostProjects` extra property in `include_flutter.groovy`.
|
||||||
// This is required to set the local repository in each host app project.
|
// This is required to set the local repository in each host app project.
|
||||||
@ -260,7 +326,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
projects.each { hostProject ->
|
projects.each { hostProject ->
|
||||||
hostProject.repositories {
|
hostProject.repositories {
|
||||||
maven {
|
maven {
|
||||||
url "${getPluginBuildDir(project)}/outputs/repo"
|
url "${getPluginBuildDir()}/outputs/repo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,7 +361,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
* Returns a set with the build type names that apply to the given list of tasks
|
* Returns a set with the build type names that apply to the given list of tasks
|
||||||
* required to configure the plugin dependencies.
|
* required to configure the plugin dependencies.
|
||||||
*/
|
*/
|
||||||
private Set getBuildTypesForTasks(Project project, List<String> tasksToExecute) {
|
private Set getBuildTypesForTasks(List<String> tasksToExecute) {
|
||||||
Set buildTypes = []
|
Set buildTypes = []
|
||||||
tasksToExecute.each { task ->
|
tasksToExecute.each { task ->
|
||||||
project.android.buildTypes.each { buildType ->
|
project.android.buildTypes.each { buildType ->
|
||||||
@ -320,7 +386,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
return "${parts[0]}${parts[1..-1].collect { it.capitalize() }.join('')}"
|
return "${parts[0]}${parts[1..-1].collect { it.capitalize() }.join('')}"
|
||||||
}
|
}
|
||||||
|
|
||||||
private String resolveProperty(Project project, String name, String defaultValue) {
|
private String resolveProperty(String name, String defaultValue) {
|
||||||
if (localProperties == null) {
|
if (localProperties == null) {
|
||||||
localProperties = readPropertiesIfExist(new File(project.projectDir.parentFile, "local.properties"))
|
localProperties = readPropertiesIfExist(new File(project.projectDir.parentFile, "local.properties"))
|
||||||
}
|
}
|
||||||
@ -345,7 +411,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> getTargetPlatforms(Project project) {
|
private List<String> getTargetPlatforms() {
|
||||||
if (!project.hasProperty('target-platform')) {
|
if (!project.hasProperty('target-platform')) {
|
||||||
return DEFAULT_PLATFORMS
|
return DEFAULT_PLATFORMS
|
||||||
}
|
}
|
||||||
@ -357,18 +423,18 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Boolean splitPerAbi(Project project) {
|
private Boolean shouldSplitPerAbi() {
|
||||||
if (project.hasProperty('split-per-abi')) {
|
if (project.hasProperty('split-per-abi')) {
|
||||||
return project.property('split-per-abi').toBoolean()
|
return project.property('split-per-abi').toBoolean()
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Boolean useLocalEngine(Project project) {
|
private Boolean useLocalEngine() {
|
||||||
return project.hasProperty('localEngineOut')
|
return project.hasProperty('localEngineOut')
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Boolean isVerbose(Project project) {
|
private Boolean isVerbose() {
|
||||||
if (project.hasProperty('verbose')) {
|
if (project.hasProperty('verbose')) {
|
||||||
return project.property('verbose').toBoolean()
|
return project.property('verbose').toBoolean()
|
||||||
}
|
}
|
||||||
@ -379,20 +445,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
return System.getProperty('build-plugins-as-aars') == 'true'
|
return System.getProperty('build-plugins-as-aars') == 'true'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void addFlutterJarCompileOnlyDependency(Project project, String variantName, Object dependency) {
|
||||||
* Returns the platform that is used to extract the `libflutter.so` and the .class files.
|
|
||||||
*
|
|
||||||
* Note: This is only needed to add the .class files.
|
|
||||||
* Unfortunately, the engine artifacts include the .class and libflutter.so files.
|
|
||||||
*/
|
|
||||||
private static String getBasePlatform(Project project) {
|
|
||||||
if (PLATFORM_ARM64 in getTargetPlatforms(project)) {
|
|
||||||
return PLATFORM_ARM64;
|
|
||||||
}
|
|
||||||
return PLATFORM_ARM32;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addFlutterJarCompileOnlyDependency(Project project, String variantName, FileCollection files) {
|
|
||||||
if (project.state.failure) {
|
if (project.state.failure) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -402,7 +455,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
} else {
|
} else {
|
||||||
configuration = "${variantName}Provided";
|
configuration = "${variantName}Provided";
|
||||||
}
|
}
|
||||||
project.dependencies.add(configuration, files)
|
project.dependencies.add(configuration, dependency)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addApiDependencies(Project project, String variantName, Object dependency, Closure config = null) {
|
private static void addApiDependencies(Project project, String variantName, Object dependency, Closure config = null) {
|
||||||
@ -455,7 +508,6 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
if (project.hasProperty('target')) {
|
if (project.hasProperty('target')) {
|
||||||
target = project.property('target')
|
target = project.property('target')
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] fileSystemRootsValue = null
|
String[] fileSystemRootsValue = null
|
||||||
if (project.hasProperty('filesystem-roots')) {
|
if (project.hasProperty('filesystem-roots')) {
|
||||||
fileSystemRootsValue = project.property('filesystem-roots').split('\\|')
|
fileSystemRootsValue = project.property('filesystem-roots').split('\\|')
|
||||||
@ -492,10 +544,9 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
if (project.hasProperty('extra-gen-snapshot-options')) {
|
if (project.hasProperty('extra-gen-snapshot-options')) {
|
||||||
extraGenSnapshotOptionsValue = project.property('extra-gen-snapshot-options')
|
extraGenSnapshotOptionsValue = project.property('extra-gen-snapshot-options')
|
||||||
}
|
}
|
||||||
|
def targetPlatforms = getTargetPlatforms()
|
||||||
def targetPlatforms = getTargetPlatforms(project)
|
|
||||||
def addFlutterDeps = { variant ->
|
def addFlutterDeps = { variant ->
|
||||||
if (splitPerAbi(project)) {
|
if (shouldSplitPerAbi()) {
|
||||||
variant.outputs.each { output ->
|
variant.outputs.each { output ->
|
||||||
// Assigns the new version code to versionCodeOverride, which changes the version code
|
// Assigns the new version code to versionCodeOverride, which changes the version code
|
||||||
// for only the output APK, not for the variant itself. Skipping this step simply
|
// for only the output APK, not for the variant itself. Skipping this step simply
|
||||||
@ -508,31 +559,17 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String flutterBuildMode = buildModeFor(variant.buildType)
|
|
||||||
if (flutterBuildMode == 'debug' && project.tasks.findByName("${FLUTTER_BUILD_PREFIX}X86Jar")) {
|
|
||||||
Task task = project.tasks.findByName("compile${variant.name.capitalize()}JavaWithJavac")
|
|
||||||
if (task) {
|
|
||||||
task.dependsOn project.flutterBuildX86Jar
|
|
||||||
}
|
|
||||||
task = project.tasks.findByName("compile${variant.name.capitalize()}Kotlin")
|
|
||||||
if (task) {
|
|
||||||
task.dependsOn project.flutterBuildX86Jar
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def compileTasks = targetPlatforms.collect { targetArch ->
|
def compileTasks = targetPlatforms.collect { targetArch ->
|
||||||
String abiValue = PLATFORM_ARCH_MAP[targetArch]
|
|
||||||
String taskName = toCammelCase(["compile", FLUTTER_BUILD_PREFIX, variant.name, targetArch.replace('android-', '')])
|
String taskName = toCammelCase(["compile", FLUTTER_BUILD_PREFIX, variant.name, targetArch.replace('android-', '')])
|
||||||
FlutterTask compileTask = project.tasks.create(name: taskName, type: FlutterTask) {
|
project.tasks.create(name: taskName, type: FlutterTask) {
|
||||||
flutterRoot this.flutterRoot
|
flutterRoot this.flutterRoot
|
||||||
flutterExecutable this.flutterExecutable
|
flutterExecutable this.flutterExecutable
|
||||||
buildMode flutterBuildMode
|
buildMode buildModeFor(variant.buildType)
|
||||||
localEngine this.localEngine
|
localEngine this.localEngine
|
||||||
localEngineSrcPath this.localEngineSrcPath
|
localEngineSrcPath this.localEngineSrcPath
|
||||||
abi abiValue
|
abi PLATFORM_ARCH_MAP[targetArch]
|
||||||
targetPath target
|
targetPath target
|
||||||
verbose isVerbose(project)
|
verbose isVerbose()
|
||||||
fileSystemRoots fileSystemRootsValue
|
fileSystemRoots fileSystemRootsValue
|
||||||
fileSystemScheme fileSystemSchemeValue
|
fileSystemScheme fileSystemSchemeValue
|
||||||
trackWidgetCreation trackWidgetCreationValue
|
trackWidgetCreation trackWidgetCreationValue
|
||||||
@ -547,51 +584,24 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
extraGenSnapshotOptions extraGenSnapshotOptionsValue
|
extraGenSnapshotOptions extraGenSnapshotOptionsValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def libJar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/libs.jar")
|
def libJar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/libs.jar")
|
||||||
def libFlutterPlatforms = targetPlatforms.collect()
|
Task packFlutterAppAotTask = project.tasks.create(name: "packLibs${FLUTTER_BUILD_PREFIX}${variant.name.capitalize()}", type: Jar) {
|
||||||
// x86/x86_64 native library used for debugging only, for now.
|
|
||||||
if (flutterBuildMode == 'debug') {
|
|
||||||
libFlutterPlatforms.add('android-x86')
|
|
||||||
libFlutterPlatforms.add('android-x64')
|
|
||||||
}
|
|
||||||
Task packFlutterSnapshotsAndLibsTask = project.tasks.create(name: "packLibs${FLUTTER_BUILD_PREFIX}${variant.name.capitalize()}", type: Jar) {
|
|
||||||
destinationDir libJar.parentFile
|
destinationDir libJar.parentFile
|
||||||
archiveName libJar.name
|
archiveName libJar.name
|
||||||
libFlutterPlatforms.each { targetArch ->
|
|
||||||
// This check prevents including `libflutter.so` twice, since it's included in the base platform jar.
|
|
||||||
// Unfortunately, the `pickFirst` setting in `packagingOptions` does not work when the project `:flutter`
|
|
||||||
// is included as an implementation dependency, which causes duplicated `libflutter.so`.
|
|
||||||
if (getBasePlatform(project) == targetArch) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Don't include `libflutter.so` for other architectures when a local engine is specified.
|
|
||||||
if (useLocalEngine(project)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
def engineArtifactSubdir = getEngineArtifactDirName(variant.buildType, targetArch);
|
|
||||||
// Include `libflutter.so`.
|
|
||||||
// TODO(blasten): The libs should be outside `flutter.jar` when the artifacts are downloaded.
|
|
||||||
from(project.zipTree("${flutterRoot}/bin/cache/artifacts/engine/${engineArtifactSubdir}/flutter.jar")) {
|
|
||||||
include 'lib/**'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dependsOn compileTasks
|
dependsOn compileTasks
|
||||||
// Add the ELF library.
|
|
||||||
compileTasks.each { compileTask ->
|
compileTasks.each { compileTask ->
|
||||||
from(compileTask.intermediateDir) {
|
from(compileTask.intermediateDir) {
|
||||||
include '*.so'
|
include '*.so'
|
||||||
|
// Move `app.so` to `lib/<abi>/libapp.so`
|
||||||
rename { String filename ->
|
rename { String filename ->
|
||||||
return "lib/${compileTask.abi}/lib${filename}"
|
return "lib/${compileTask.abi}/lib${filename}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Include the snapshots and libflutter.so in `lib/`.
|
|
||||||
addApiDependencies(project, variant.name, project.files {
|
addApiDependencies(project, variant.name, project.files {
|
||||||
packFlutterSnapshotsAndLibsTask
|
packFlutterAppAotTask
|
||||||
})
|
})
|
||||||
|
|
||||||
// We know that the flutter app is a subproject in another Android app when these tasks exist.
|
// We know that the flutter app is a subproject in another Android app when these tasks exist.
|
||||||
Task packageAssets = project.tasks.findByPath(":flutter:package${variant.name.capitalize()}Assets")
|
Task packageAssets = project.tasks.findByPath(":flutter:package${variant.name.capitalize()}Assets")
|
||||||
Task cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets")
|
Task cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets")
|
||||||
@ -618,57 +628,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
} else {
|
} else {
|
||||||
project.android.libraryVariants.all addFlutterDeps
|
project.android.libraryVariants.all addFlutterDeps
|
||||||
}
|
}
|
||||||
|
configurePlugins()
|
||||||
if (buildPluginAsAar()) {
|
|
||||||
addPluginTasks(project)
|
|
||||||
|
|
||||||
List<String> tasksToExecute = project.gradle.startParameter.taskNames
|
|
||||||
Set buildTypes = getBuildTypesForTasks(project, tasksToExecute)
|
|
||||||
if (tasksToExecute.contains("clean")) {
|
|
||||||
// Because the plugins are built during configuration, the task "clean"
|
|
||||||
// cannot run in conjunction with an assembly task.
|
|
||||||
if (!buildTypes.empty) {
|
|
||||||
throw new GradleException("Can't run the clean task along with other assemble tasks")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Build plugins when a task "assembly*" will be called later.
|
|
||||||
if (!buildTypes.empty) {
|
|
||||||
// Build the plugin during configuration.
|
|
||||||
// This is required when Jetifier is enabled, otherwise the implementation dependency
|
|
||||||
// cannot be added.
|
|
||||||
buildPlugins(project, buildTypes)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getPluginList(project).each { name, _ ->
|
|
||||||
def pluginProject = project.rootProject.findProject(":$name")
|
|
||||||
if (pluginProject != null) {
|
|
||||||
project.dependencies {
|
|
||||||
if (project.getConfigurations().findByName("implementation")) {
|
|
||||||
implementation pluginProject
|
|
||||||
} else {
|
|
||||||
compile pluginProject
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pluginProject.afterEvaluate {
|
|
||||||
pluginProject.android.buildTypes {
|
|
||||||
profile {
|
|
||||||
initWith debug
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pluginProject.android.buildTypes.each {
|
|
||||||
def buildMode = buildModeFor(it)
|
|
||||||
addFlutterJarCompileOnlyDependency(pluginProject, it.name, project.files( flutterJar ?: baseJar[buildMode] ))
|
|
||||||
}
|
|
||||||
pluginProject.android.buildTypes.whenObjectAdded {
|
|
||||||
def buildMode = buildModeFor(it)
|
|
||||||
addFlutterJarCompileOnlyDependency(pluginProject, it.name, project.files( flutterJar ?: baseJar[buildMode] ))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
project.logger.error("Plugin project :$name not found. Please update settings.gradle.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
packages/flutter_tools/gradle/resolve_dependencies.gradle
Normal file
64
packages/flutter_tools/gradle/resolve_dependencies.gradle
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// This script is used to warm the Gradle cache by downloading the Flutter dependencies
|
||||||
|
// used during the build. This script is invoked when `flutter precache` is run.
|
||||||
|
//
|
||||||
|
// Command:
|
||||||
|
// gradle -b <flutter-sdk>packages/flutter_tools/gradle/resolve_dependencies.gradle
|
||||||
|
// resolveDependencies
|
||||||
|
//
|
||||||
|
// This way, Gradle can run with the `--offline` flag later on to eliminate any
|
||||||
|
// network request during the build process.
|
||||||
|
//
|
||||||
|
// This includes:
|
||||||
|
// 1. The embedding
|
||||||
|
// 2. libflutter.so
|
||||||
|
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url "http://download.flutter.io"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File flutterRoot = projectDir.parentFile.parentFile.parentFile
|
||||||
|
|
||||||
|
assert flutterRoot.isDirectory()
|
||||||
|
String engineVersion = Paths.get(flutterRoot.absolutePath, "bin", "internal", "engine.version")
|
||||||
|
.toFile().text.trim()
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
flutterRelease.extendsFrom releaseImplementation
|
||||||
|
flutterDebug.extendsFrom debugImplementation
|
||||||
|
flutterProfile.extendsFrom debugImplementation
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
flutterRelease "io.flutter:flutter_embedding_release:1.0.0-$engineVersion"
|
||||||
|
flutterRelease "io.flutter:armeabi_v7a_release:1.0.0-$engineVersion"
|
||||||
|
flutterRelease "io.flutter:arm64_v8a_release:1.0.0-$engineVersion"
|
||||||
|
|
||||||
|
flutterProfile "io.flutter:flutter_embedding_profile:1.0.0-$engineVersion"
|
||||||
|
flutterProfile "io.flutter:armeabi_v7a_profile:1.0.0-$engineVersion"
|
||||||
|
flutterProfile "io.flutter:arm64_v8a_profile:1.0.0-$engineVersion"
|
||||||
|
|
||||||
|
flutterDebug "io.flutter:flutter_embedding_debug:1.0.0-$engineVersion"
|
||||||
|
flutterDebug "io.flutter:armeabi_v7a_debug:1.0.0-$engineVersion"
|
||||||
|
flutterDebug "io.flutter:arm64_v8a_debug:1.0.0-$engineVersion"
|
||||||
|
flutterDebug "io.flutter:x86_debug:1.0.0-$engineVersion"
|
||||||
|
flutterDebug "io.flutter:x86_64_debug:1.0.0-$engineVersion"
|
||||||
|
}
|
||||||
|
|
||||||
|
task resolveDependencies {
|
||||||
|
configurations.each { configuration ->
|
||||||
|
if (configuration.name.startsWith("flutter")) {
|
||||||
|
configuration.resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -84,7 +84,7 @@ Future<void> main(List<String> args) async {
|
|||||||
LogsCommand(),
|
LogsCommand(),
|
||||||
MakeHostAppEditableCommand(),
|
MakeHostAppEditableCommand(),
|
||||||
PackagesCommand(),
|
PackagesCommand(),
|
||||||
PrecacheCommand(),
|
PrecacheCommand(verboseHelp: verboseHelp),
|
||||||
RunCommand(verboseHelp: verboseHelp),
|
RunCommand(verboseHelp: verboseHelp),
|
||||||
ScreenshotCommand(),
|
ScreenshotCommand(),
|
||||||
ShellCompletionCommand(),
|
ShellCompletionCommand(),
|
||||||
|
@ -6,14 +6,16 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
import 'android/gradle.dart';
|
||||||
import 'base/common.dart';
|
import 'base/common.dart';
|
||||||
import 'base/context.dart';
|
import 'base/context.dart';
|
||||||
import 'base/file_system.dart';
|
import 'base/file_system.dart';
|
||||||
import 'base/io.dart' show SocketException;
|
import 'base/io.dart' show Process, SocketException;
|
||||||
import 'base/logger.dart';
|
import 'base/logger.dart';
|
||||||
import 'base/net.dart';
|
import 'base/net.dart';
|
||||||
import 'base/os.dart';
|
import 'base/os.dart';
|
||||||
import 'base/platform.dart';
|
import 'base/platform.dart';
|
||||||
|
import 'base/process.dart';
|
||||||
import 'globals.dart';
|
import 'globals.dart';
|
||||||
|
|
||||||
/// A tag for a set of development artifacts that need to be cached.
|
/// A tag for a set of development artifacts that need to be cached.
|
||||||
@ -30,7 +32,10 @@ class DevelopmentArtifact {
|
|||||||
final bool unstable;
|
final bool unstable;
|
||||||
|
|
||||||
/// Artifacts required for Android development.
|
/// Artifacts required for Android development.
|
||||||
static const DevelopmentArtifact android = DevelopmentArtifact._('android');
|
static const DevelopmentArtifact androidGenSnapshot = DevelopmentArtifact._('android_gen_snapshot');
|
||||||
|
static const DevelopmentArtifact androidMaven = DevelopmentArtifact._('android_maven');
|
||||||
|
// Artifacts used for internal builds.
|
||||||
|
static const DevelopmentArtifact androidInternalBuild = DevelopmentArtifact._('android_internal_build');
|
||||||
|
|
||||||
/// Artifacts required for iOS development.
|
/// Artifacts required for iOS development.
|
||||||
static const DevelopmentArtifact iOS = DevelopmentArtifact._('ios');
|
static const DevelopmentArtifact iOS = DevelopmentArtifact._('ios');
|
||||||
@ -58,7 +63,9 @@ class DevelopmentArtifact {
|
|||||||
|
|
||||||
/// The values of DevelopmentArtifacts.
|
/// The values of DevelopmentArtifacts.
|
||||||
static final List<DevelopmentArtifact> values = <DevelopmentArtifact>[
|
static final List<DevelopmentArtifact> values = <DevelopmentArtifact>[
|
||||||
android,
|
androidGenSnapshot,
|
||||||
|
androidMaven,
|
||||||
|
androidInternalBuild,
|
||||||
iOS,
|
iOS,
|
||||||
web,
|
web,
|
||||||
macOS,
|
macOS,
|
||||||
@ -74,12 +81,16 @@ class DevelopmentArtifact {
|
|||||||
class Cache {
|
class Cache {
|
||||||
/// [rootOverride] is configurable for testing.
|
/// [rootOverride] is configurable for testing.
|
||||||
/// [artifacts] is configurable for testing.
|
/// [artifacts] is configurable for testing.
|
||||||
Cache({ Directory rootOverride, List<CachedArtifact> artifacts }) : _rootOverride = rootOverride {
|
Cache({ Directory rootOverride, List<ArtifactSet> artifacts }) : _rootOverride = rootOverride {
|
||||||
if (artifacts == null) {
|
if (artifacts == null) {
|
||||||
_artifacts.add(MaterialFonts(this));
|
_artifacts.add(MaterialFonts(this));
|
||||||
_artifacts.add(AndroidEngineArtifacts(this));
|
|
||||||
_artifacts.add(IOSEngineArtifacts(this));
|
|
||||||
_artifacts.add(GradleWrapper(this));
|
_artifacts.add(GradleWrapper(this));
|
||||||
|
_artifacts.add(AndroidMavenArtifacts());
|
||||||
|
_artifacts.add(AndroidGenSnapshotArtifacts(this));
|
||||||
|
_artifacts.add(AndroidInternalBuildArtifacts(this));
|
||||||
|
|
||||||
|
_artifacts.add(IOSEngineArtifacts(this));
|
||||||
_artifacts.add(FlutterWebSdk(this));
|
_artifacts.add(FlutterWebSdk(this));
|
||||||
_artifacts.add(FlutterSdk(this));
|
_artifacts.add(FlutterSdk(this));
|
||||||
_artifacts.add(WindowsEngineArtifacts(this));
|
_artifacts.add(WindowsEngineArtifacts(this));
|
||||||
@ -101,7 +112,7 @@ class Cache {
|
|||||||
];
|
];
|
||||||
|
|
||||||
final Directory _rootOverride;
|
final Directory _rootOverride;
|
||||||
final List<CachedArtifact> _artifacts = <CachedArtifact>[];
|
final List<ArtifactSet> _artifacts = <ArtifactSet>[];
|
||||||
|
|
||||||
// Initialized by FlutterCommandRunner on startup.
|
// Initialized by FlutterCommandRunner on startup.
|
||||||
static String flutterRoot;
|
static String flutterRoot;
|
||||||
@ -245,11 +256,16 @@ class Cache {
|
|||||||
return _dyLdLibEntry;
|
return _dyLdLibEntry;
|
||||||
}
|
}
|
||||||
final List<String> paths = <String>[];
|
final List<String> paths = <String>[];
|
||||||
for (CachedArtifact artifact in _artifacts) {
|
for (ArtifactSet artifact in _artifacts) {
|
||||||
final String currentPath = artifact.dyLdLibPath;
|
final Map<String, String> env = artifact.environment;
|
||||||
if (currentPath.isNotEmpty) {
|
if (env == null || !env.containsKey('DYLD_LIBRARY_PATH')) {
|
||||||
paths.add(currentPath);
|
continue;
|
||||||
}
|
}
|
||||||
|
final String path = env['DYLD_LIBRARY_PATH'];
|
||||||
|
if (path.isEmpty) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
paths.add(path);
|
||||||
}
|
}
|
||||||
_dyLdLibEntry = MapEntry<String, String>('DYLD_LIBRARY_PATH', paths.join(':'));
|
_dyLdLibEntry = MapEntry<String, String>('DYLD_LIBRARY_PATH', paths.join(':'));
|
||||||
return _dyLdLibEntry;
|
return _dyLdLibEntry;
|
||||||
@ -289,7 +305,7 @@ class Cache {
|
|||||||
return isOlderThanReference(entity: entity, referenceFile: flutterToolsStamp);
|
return isOlderThanReference(entity: entity, referenceFile: flutterToolsStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isUpToDate() => _artifacts.every((CachedArtifact artifact) => artifact.isUpToDate());
|
bool isUpToDate() => _artifacts.every((ArtifactSet artifact) => artifact.isUpToDate());
|
||||||
|
|
||||||
Future<String> getThirdPartyFile(String urlStr, String serviceName) async {
|
Future<String> getThirdPartyFile(String urlStr, String serviceName) async {
|
||||||
final Uri url = Uri.parse(urlStr);
|
final Uri url = Uri.parse(urlStr);
|
||||||
@ -318,12 +334,16 @@ class Cache {
|
|||||||
if (!_lockEnabled) {
|
if (!_lockEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
for (ArtifactSet artifact in _artifacts) {
|
||||||
|
if (!requiredArtifacts.contains(artifact.developmentArtifact)) {
|
||||||
|
printTrace('Artifact $artifact is not required, skipping update.');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (artifact.isUpToDate()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
for (CachedArtifact artifact in _artifacts) {
|
await artifact.update();
|
||||||
if (!artifact.isUpToDate()) {
|
|
||||||
await artifact.update(requiredArtifacts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} on SocketException catch (e) {
|
} on SocketException catch (e) {
|
||||||
if (_hostsBlockedInChina.contains(e.address?.host)) {
|
if (_hostsBlockedInChina.contains(e.address?.host)) {
|
||||||
printError(
|
printError(
|
||||||
@ -336,6 +356,7 @@ class Cache {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> areRemoteArtifactsAvailable({
|
Future<bool> areRemoteArtifactsAvailable({
|
||||||
String engineVersion,
|
String engineVersion,
|
||||||
@ -354,23 +375,42 @@ class Cache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An artifact managed by the cache.
|
/// Representation of a set of artifacts used by the tool.
|
||||||
abstract class CachedArtifact {
|
abstract class ArtifactSet {
|
||||||
CachedArtifact(this.name, this.cache, this.developmentArtifacts);
|
ArtifactSet(this.developmentArtifact) : assert(developmentArtifact != null);
|
||||||
|
|
||||||
|
/// The development artifact.
|
||||||
|
final DevelopmentArtifact developmentArtifact;
|
||||||
|
|
||||||
|
/// [true] if the artifact is up to date.
|
||||||
|
bool isUpToDate();
|
||||||
|
|
||||||
|
/// The environment variables (if any) required to consume the artifacts.
|
||||||
|
Map<String, String> get environment {
|
||||||
|
return const <String, String>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the artifact.
|
||||||
|
Future<void> update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An artifact set managed by the cache.
|
||||||
|
abstract class CachedArtifact extends ArtifactSet {
|
||||||
|
CachedArtifact(
|
||||||
|
this.name,
|
||||||
|
this.cache,
|
||||||
|
DevelopmentArtifact developmentArtifact,
|
||||||
|
) : super(developmentArtifact);
|
||||||
|
|
||||||
final String name;
|
|
||||||
final Cache cache;
|
final Cache cache;
|
||||||
|
|
||||||
|
/// The canonical name of the artifact.
|
||||||
|
final String name;
|
||||||
|
|
||||||
// The name of the stamp file. Defaults to the same as the
|
// The name of the stamp file. Defaults to the same as the
|
||||||
// artifact name.
|
// artifact name.
|
||||||
String get stampName => name;
|
String get stampName => name;
|
||||||
|
|
||||||
/// Returns a string to be set as environment DYLD_LIBARY_PATH variable
|
|
||||||
String get dyLdLibPath => '';
|
|
||||||
|
|
||||||
/// All development artifacts this cache provides.
|
|
||||||
final Set<DevelopmentArtifact> developmentArtifacts;
|
|
||||||
|
|
||||||
Directory get location => cache.getArtifactDirectory(name);
|
Directory get location => cache.getArtifactDirectory(name);
|
||||||
String get version => cache.getVersionFor(name);
|
String get version => cache.getVersionFor(name);
|
||||||
|
|
||||||
@ -380,6 +420,7 @@ abstract class CachedArtifact {
|
|||||||
/// starting from scratch.
|
/// starting from scratch.
|
||||||
final List<File> _downloadedFiles = <File>[];
|
final List<File> _downloadedFiles = <File>[];
|
||||||
|
|
||||||
|
@override
|
||||||
bool isUpToDate() {
|
bool isUpToDate() {
|
||||||
if (!location.existsSync()) {
|
if (!location.existsSync()) {
|
||||||
return false;
|
return false;
|
||||||
@ -390,13 +431,8 @@ abstract class CachedArtifact {
|
|||||||
return isUpToDateInner();
|
return isUpToDateInner();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> update(Set<DevelopmentArtifact> requiredArtifacts) async {
|
@override
|
||||||
// If the set of required artifacts does not include any from this cache,
|
Future<void> update() async {
|
||||||
// then we can claim we are up to date to skip downloading.
|
|
||||||
if (!requiredArtifacts.any(developmentArtifacts.contains)) {
|
|
||||||
printTrace('Artifact $this is not required, skipping update.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!location.existsSync()) {
|
if (!location.existsSync()) {
|
||||||
try {
|
try {
|
||||||
location.createSync(recursive: true);
|
location.createSync(recursive: true);
|
||||||
@ -499,7 +535,7 @@ class MaterialFonts extends CachedArtifact {
|
|||||||
MaterialFonts(Cache cache) : super(
|
MaterialFonts(Cache cache) : super(
|
||||||
'material_fonts',
|
'material_fonts',
|
||||||
cache,
|
cache,
|
||||||
const <DevelopmentArtifact>{ DevelopmentArtifact.universal },
|
DevelopmentArtifact.universal,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -517,7 +553,7 @@ class FlutterWebSdk extends CachedArtifact {
|
|||||||
FlutterWebSdk(Cache cache) : super(
|
FlutterWebSdk(Cache cache) : super(
|
||||||
'flutter_web_sdk',
|
'flutter_web_sdk',
|
||||||
cache,
|
cache,
|
||||||
const <DevelopmentArtifact>{ DevelopmentArtifact.web },
|
DevelopmentArtifact.web,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -558,8 +594,8 @@ abstract class EngineCachedArtifact extends CachedArtifact {
|
|||||||
EngineCachedArtifact(
|
EngineCachedArtifact(
|
||||||
this.stampName,
|
this.stampName,
|
||||||
Cache cache,
|
Cache cache,
|
||||||
Set<DevelopmentArtifact> requiredArtifacts,
|
DevelopmentArtifact developmentArtifact,
|
||||||
) : super('engine', cache, requiredArtifacts);
|
) : super('engine', cache, developmentArtifact);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final String stampName;
|
final String stampName;
|
||||||
@ -680,7 +716,7 @@ class FlutterSdk extends EngineCachedArtifact {
|
|||||||
FlutterSdk(Cache cache) : super(
|
FlutterSdk(Cache cache) : super(
|
||||||
'flutter_sdk',
|
'flutter_sdk',
|
||||||
cache,
|
cache,
|
||||||
const <DevelopmentArtifact>{ DevelopmentArtifact.universal },
|
DevelopmentArtifact.universal,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -714,7 +750,7 @@ class MacOSEngineArtifacts extends EngineCachedArtifact {
|
|||||||
MacOSEngineArtifacts(Cache cache) : super(
|
MacOSEngineArtifacts(Cache cache) : super(
|
||||||
'macos-sdk',
|
'macos-sdk',
|
||||||
cache,
|
cache,
|
||||||
const <DevelopmentArtifact> { DevelopmentArtifact.macOS },
|
DevelopmentArtifact.macOS,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -736,7 +772,7 @@ class WindowsEngineArtifacts extends EngineCachedArtifact {
|
|||||||
WindowsEngineArtifacts(Cache cache) : super(
|
WindowsEngineArtifacts(Cache cache) : super(
|
||||||
'windows-sdk',
|
'windows-sdk',
|
||||||
cache,
|
cache,
|
||||||
const <DevelopmentArtifact> { DevelopmentArtifact.windows },
|
DevelopmentArtifact.windows,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -758,7 +794,7 @@ class LinuxEngineArtifacts extends EngineCachedArtifact {
|
|||||||
LinuxEngineArtifacts(Cache cache) : super(
|
LinuxEngineArtifacts(Cache cache) : super(
|
||||||
'linux-sdk',
|
'linux-sdk',
|
||||||
cache,
|
cache,
|
||||||
const <DevelopmentArtifact> { DevelopmentArtifact.linux },
|
DevelopmentArtifact.linux,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -776,11 +812,12 @@ class LinuxEngineArtifacts extends EngineCachedArtifact {
|
|||||||
List<String> getLicenseDirs() => const <String>[];
|
List<String> getLicenseDirs() => const <String>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
class AndroidEngineArtifacts extends EngineCachedArtifact {
|
/// The artifact used to generate snapshots for Android builds.
|
||||||
AndroidEngineArtifacts(Cache cache) : super(
|
class AndroidGenSnapshotArtifacts extends EngineCachedArtifact {
|
||||||
|
AndroidGenSnapshotArtifacts(Cache cache) : super(
|
||||||
'android-sdk',
|
'android-sdk',
|
||||||
cache,
|
cache,
|
||||||
const <DevelopmentArtifact>{ DevelopmentArtifact.android },
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -794,23 +831,19 @@ class AndroidEngineArtifacts extends EngineCachedArtifact {
|
|||||||
..._osxBinaryDirs,
|
..._osxBinaryDirs,
|
||||||
..._linuxBinaryDirs,
|
..._linuxBinaryDirs,
|
||||||
..._windowsBinaryDirs,
|
..._windowsBinaryDirs,
|
||||||
..._androidBinaryDirs,
|
|
||||||
..._dartSdks,
|
..._dartSdks,
|
||||||
]
|
]
|
||||||
else if (platform.isWindows)
|
else if (platform.isWindows)
|
||||||
...<List<String>>[
|
...<List<String>>[
|
||||||
..._windowsBinaryDirs,
|
..._windowsBinaryDirs,
|
||||||
..._androidBinaryDirs,
|
|
||||||
]
|
]
|
||||||
else if (platform.isMacOS)
|
else if (platform.isMacOS)
|
||||||
...<List<String>>[
|
...<List<String>>[
|
||||||
..._osxBinaryDirs,
|
..._osxBinaryDirs,
|
||||||
..._androidBinaryDirs,
|
|
||||||
]
|
]
|
||||||
else if (platform.isLinux)
|
else if (platform.isLinux)
|
||||||
...<List<String>>[
|
...<List<String>>[
|
||||||
..._linuxBinaryDirs,
|
..._linuxBinaryDirs,
|
||||||
..._androidBinaryDirs,
|
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -819,11 +852,79 @@ class AndroidEngineArtifacts extends EngineCachedArtifact {
|
|||||||
List<String> getLicenseDirs() { return <String>[]; }
|
List<String> getLicenseDirs() { return <String>[]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Artifacts used for internal builds. The flutter tool builds Android projects
|
||||||
|
/// using the artifacts cached by [AndroidMavenArtifacts].
|
||||||
|
class AndroidInternalBuildArtifacts extends EngineCachedArtifact {
|
||||||
|
AndroidInternalBuildArtifacts(Cache cache) : super(
|
||||||
|
'android-internal-build-artifacts',
|
||||||
|
cache,
|
||||||
|
DevelopmentArtifact.androidInternalBuild,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> getPackageDirs() => const <String>[];
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<List<String>> getBinaryDirs() {
|
||||||
|
return _androidBinaryDirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> getLicenseDirs() { return <String>[]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A cached artifact containing the Maven dependencies used to build Android projects.
|
||||||
|
class AndroidMavenArtifacts extends ArtifactSet {
|
||||||
|
AndroidMavenArtifacts() : super(DevelopmentArtifact.androidMaven);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> update() async {
|
||||||
|
final Directory tempDir =
|
||||||
|
fs.systemTempDirectory.createTempSync('gradle_wrapper.');
|
||||||
|
injectGradleWrapperIfNeeded(tempDir);
|
||||||
|
|
||||||
|
final Status status = logger.startProgress('Downloading Android Maven dependencies...',
|
||||||
|
timeout: timeoutConfiguration.slowOperation);
|
||||||
|
final File gradle = tempDir.childFile(
|
||||||
|
platform.isWindows ? 'gradlew.bat' : 'gradlew',
|
||||||
|
);
|
||||||
|
assert(gradle.existsSync());
|
||||||
|
os.makeExecutable(gradle);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final String gradleExecutable = gradle.absolute.path;
|
||||||
|
final String flutterSdk = escapePath(Cache.flutterRoot);
|
||||||
|
final Process process = await runCommand(
|
||||||
|
<String>[
|
||||||
|
gradleExecutable,
|
||||||
|
'-b', fs.path.join(flutterSdk, 'packages', 'flutter_tools', 'gradle', 'resolve_dependencies.gradle'),
|
||||||
|
'--project-cache-dir', tempDir.path,
|
||||||
|
'resolveDependencies',
|
||||||
|
]);
|
||||||
|
final int exitCode = await process.exitCode;
|
||||||
|
if (exitCode != 0) {
|
||||||
|
printError('Failed to download the Android dependencies');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
status.stop();
|
||||||
|
tempDir.deleteSync(recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isUpToDate() {
|
||||||
|
// The dependencies are downloaded and cached by Gradle.
|
||||||
|
// The tool doesn't know if the dependencies are already cached at this point.
|
||||||
|
// Therefore, call Gradle to figure this out.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class IOSEngineArtifacts extends EngineCachedArtifact {
|
class IOSEngineArtifacts extends EngineCachedArtifact {
|
||||||
IOSEngineArtifacts(Cache cache) : super(
|
IOSEngineArtifacts(Cache cache) : super(
|
||||||
'ios-sdk',
|
'ios-sdk',
|
||||||
cache,
|
cache,
|
||||||
<DevelopmentArtifact>{ DevelopmentArtifact.iOS },
|
DevelopmentArtifact.iOS,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -856,7 +957,7 @@ class GradleWrapper extends CachedArtifact {
|
|||||||
GradleWrapper(Cache cache) : super(
|
GradleWrapper(Cache cache) : super(
|
||||||
'gradle_wrapper',
|
'gradle_wrapper',
|
||||||
cache,
|
cache,
|
||||||
const <DevelopmentArtifact>{ DevelopmentArtifact.universal },
|
DevelopmentArtifact.universal,
|
||||||
);
|
);
|
||||||
|
|
||||||
List<String> get _gradleScripts => <String>['gradlew', 'gradlew.bat'];
|
List<String> get _gradleScripts => <String>['gradlew', 'gradlew.bat'];
|
||||||
@ -897,11 +998,13 @@ class GradleWrapper extends CachedArtifact {
|
|||||||
|
|
||||||
/// Common functionality for pulling Fuchsia SDKs.
|
/// Common functionality for pulling Fuchsia SDKs.
|
||||||
abstract class _FuchsiaSDKArtifacts extends CachedArtifact {
|
abstract class _FuchsiaSDKArtifacts extends CachedArtifact {
|
||||||
_FuchsiaSDKArtifacts(Cache cache, String platform)
|
_FuchsiaSDKArtifacts(Cache cache, String platform) :
|
||||||
:_path = 'fuchsia/sdk/core/$platform-amd64',
|
_path = 'fuchsia/sdk/core/$platform-amd64',
|
||||||
super('fuchsia-$platform', cache, const <DevelopmentArtifact> {
|
super(
|
||||||
|
'fuchsia-$platform',
|
||||||
|
cache,
|
||||||
DevelopmentArtifact.fuchsia,
|
DevelopmentArtifact.fuchsia,
|
||||||
});
|
);
|
||||||
|
|
||||||
final String _path;
|
final String _path;
|
||||||
|
|
||||||
@ -917,10 +1020,11 @@ abstract class _FuchsiaSDKArtifacts extends CachedArtifact {
|
|||||||
|
|
||||||
/// The pre-built flutter runner for Fuchsia development.
|
/// The pre-built flutter runner for Fuchsia development.
|
||||||
class FlutterRunnerSDKArtifacts extends CachedArtifact {
|
class FlutterRunnerSDKArtifacts extends CachedArtifact {
|
||||||
FlutterRunnerSDKArtifacts(Cache cache)
|
FlutterRunnerSDKArtifacts(Cache cache) : super(
|
||||||
: super('flutter_runner', cache, const <DevelopmentArtifact>{
|
'flutter_runner',
|
||||||
|
cache,
|
||||||
DevelopmentArtifact.flutterRunner,
|
DevelopmentArtifact.flutterRunner,
|
||||||
});
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Directory get location => cache.getArtifactDirectory('flutter_runner');
|
Directory get location => cache.getArtifactDirectory('flutter_runner');
|
||||||
@ -971,7 +1075,7 @@ class IosUsbArtifacts extends CachedArtifact {
|
|||||||
name,
|
name,
|
||||||
cache,
|
cache,
|
||||||
// This is universal to ensure every command checks for them first
|
// This is universal to ensure every command checks for them first
|
||||||
const <DevelopmentArtifact>{ DevelopmentArtifact.universal },
|
DevelopmentArtifact.universal,
|
||||||
);
|
);
|
||||||
|
|
||||||
static const List<String> artifactNames = <String>[
|
static const List<String> artifactNames = <String>[
|
||||||
@ -984,8 +1088,10 @@ class IosUsbArtifacts extends CachedArtifact {
|
|||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get dyLdLibPath {
|
Map<String, String> get environment {
|
||||||
return cache.getArtifactDirectory(name).path;
|
return <String, String>{
|
||||||
|
'DYLD_LIBRARY_PATH': cache.getArtifactDirectory(name).path,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -1093,6 +1199,12 @@ const List<List<String>> _windowsBinaryDirs = <List<String>>[
|
|||||||
<String>['android-arm64-release/windows-x64', 'android-arm64-release/windows-x64.zip'],
|
<String>['android-arm64-release/windows-x64', 'android-arm64-release/windows-x64.zip'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const List<List<String>> _iosBinaryDirs = <List<String>>[
|
||||||
|
<String>['ios', 'ios/artifacts.zip'],
|
||||||
|
<String>['ios-profile', 'ios-profile/artifacts.zip'],
|
||||||
|
<String>['ios-release', 'ios-release/artifacts.zip'],
|
||||||
|
];
|
||||||
|
|
||||||
const List<List<String>> _androidBinaryDirs = <List<String>>[
|
const List<List<String>> _androidBinaryDirs = <List<String>>[
|
||||||
<String>['android-x86', 'android-x86/artifacts.zip'],
|
<String>['android-x86', 'android-x86/artifacts.zip'],
|
||||||
<String>['android-x64', 'android-x64/artifacts.zip'],
|
<String>['android-x64', 'android-x64/artifacts.zip'],
|
||||||
@ -1104,12 +1216,6 @@ const List<List<String>> _androidBinaryDirs = <List<String>>[
|
|||||||
<String>['android-arm64-release', 'android-arm64-release/artifacts.zip'],
|
<String>['android-arm64-release', 'android-arm64-release/artifacts.zip'],
|
||||||
];
|
];
|
||||||
|
|
||||||
const List<List<String>> _iosBinaryDirs = <List<String>>[
|
|
||||||
<String>['ios', 'ios/artifacts.zip'],
|
|
||||||
<String>['ios-profile', 'ios-profile/artifacts.zip'],
|
|
||||||
<String>['ios-release', 'ios-release/artifacts.zip'],
|
|
||||||
];
|
|
||||||
|
|
||||||
const List<List<String>> _dartSdks = <List<String>> [
|
const List<List<String>> _dartSdks = <List<String>> [
|
||||||
<String>['darwin-x64', 'dart-sdk-darwin-x64.zip'],
|
<String>['darwin-x64', 'dart-sdk-darwin-x64.zip'],
|
||||||
<String>['linux-x64', 'dart-sdk-linux-x64.zip'],
|
<String>['linux-x64', 'dart-sdk-linux-x64.zip'],
|
||||||
|
@ -9,7 +9,7 @@ import '../base/os.dart';
|
|||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../reporting/reporting.dart';
|
import '../reporting/reporting.dart';
|
||||||
import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommandResult;
|
import '../runner/flutter_command.dart' show FlutterCommandResult;
|
||||||
import 'build.dart';
|
import 'build.dart';
|
||||||
|
|
||||||
class BuildAarCommand extends BuildSubCommand {
|
class BuildAarCommand extends BuildSubCommand {
|
||||||
@ -52,12 +52,6 @@ class BuildAarCommand extends BuildSubCommand {
|
|||||||
return usage;
|
return usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
|
|
||||||
DevelopmentArtifact.universal,
|
|
||||||
DevelopmentArtifact.android,
|
|
||||||
};
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final String description = 'Build a repository containing an AAR and a POM file.\n\n'
|
final String description = 'Build a repository containing an AAR and a POM file.\n\n'
|
||||||
'The POM file is used to include the dependencies that the AAR was compiled against.\n\n'
|
'The POM file is used to include the dependencies that the AAR was compiled against.\n\n'
|
||||||
|
@ -10,7 +10,7 @@ import '../build_info.dart';
|
|||||||
import '../globals.dart';
|
import '../globals.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../reporting/reporting.dart';
|
import '../reporting/reporting.dart';
|
||||||
import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommandResult;
|
import '../runner/flutter_command.dart' show FlutterCommandResult;
|
||||||
import 'build.dart';
|
import 'build.dart';
|
||||||
|
|
||||||
class BuildApkCommand extends BuildSubCommand {
|
class BuildApkCommand extends BuildSubCommand {
|
||||||
@ -68,12 +68,6 @@ class BuildApkCommand extends BuildSubCommand {
|
|||||||
return usage;
|
return usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
|
|
||||||
DevelopmentArtifact.universal,
|
|
||||||
DevelopmentArtifact.android,
|
|
||||||
};
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<FlutterCommandResult> runCommand() async {
|
Future<FlutterCommandResult> runCommand() async {
|
||||||
final BuildInfo buildInfo = getBuildInfo();
|
final BuildInfo buildInfo = getBuildInfo();
|
||||||
|
@ -37,7 +37,7 @@ class DoctorCommand extends FlutterCommand {
|
|||||||
// This is required because we use gen_snapshot to check if the host
|
// This is required because we use gen_snapshot to check if the host
|
||||||
// machine can execute the provided artifacts. See `_genSnapshotRuns`
|
// machine can execute the provided artifacts. See `_genSnapshotRuns`
|
||||||
// in `doctor.dart`.
|
// in `doctor.dart`.
|
||||||
DevelopmentArtifact.android,
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,13 +10,23 @@ import '../runner/flutter_command.dart';
|
|||||||
import '../version.dart';
|
import '../version.dart';
|
||||||
|
|
||||||
class PrecacheCommand extends FlutterCommand {
|
class PrecacheCommand extends FlutterCommand {
|
||||||
PrecacheCommand() {
|
PrecacheCommand({bool verboseHelp = false}) {
|
||||||
argParser.addFlag('all-platforms', abbr: 'a', negatable: false,
|
argParser.addFlag('all-platforms', abbr: 'a', negatable: false,
|
||||||
help: 'Precache artifacts for all host platforms.');
|
help: 'Precache artifacts for all host platforms.');
|
||||||
argParser.addFlag('force', abbr: 'f', negatable: false,
|
argParser.addFlag('force', abbr: 'f', negatable: false,
|
||||||
help: 'Force downloading of artifacts.');
|
help: 'Force downloading of artifacts.');
|
||||||
argParser.addFlag('android', negatable: true, defaultsTo: true,
|
argParser.addFlag('android', negatable: true, defaultsTo: true,
|
||||||
help: 'Precache artifacts for Android development.');
|
help: 'Precache artifacts for Android development.',
|
||||||
|
hide: verboseHelp);
|
||||||
|
argParser.addFlag('android_gen_snapshot', negatable: true, defaultsTo: true,
|
||||||
|
help: 'Precache gen_snapshot for Android development.',
|
||||||
|
hide: !verboseHelp);
|
||||||
|
argParser.addFlag('android_maven', negatable: true, defaultsTo: true,
|
||||||
|
help: 'Precache Gradle dependencies for Android development.',
|
||||||
|
hide: !verboseHelp);
|
||||||
|
argParser.addFlag('android_internal_build', negatable: true, defaultsTo: false,
|
||||||
|
help: 'Precache dependencies for internal Android development.',
|
||||||
|
hide: !verboseHelp);
|
||||||
argParser.addFlag('ios', negatable: true, defaultsTo: true,
|
argParser.addFlag('ios', negatable: true, defaultsTo: true,
|
||||||
help: 'Precache artifacts for iOS development.');
|
help: 'Precache artifacts for iOS development.');
|
||||||
argParser.addFlag('web', negatable: true, defaultsTo: false,
|
argParser.addFlag('web', negatable: true, defaultsTo: false,
|
||||||
@ -58,6 +68,10 @@ class PrecacheCommand extends FlutterCommand {
|
|||||||
if (argResults[artifact.name]) {
|
if (argResults[artifact.name]) {
|
||||||
requiredArtifacts.add(artifact);
|
requiredArtifacts.add(artifact);
|
||||||
}
|
}
|
||||||
|
// The `android` flag expands to android_gen_snapshot, android_maven, android_internal_build.
|
||||||
|
if (artifact.name.startsWith('android_') && argResults['android']) {
|
||||||
|
requiredArtifacts.add(artifact);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
final bool forceUpdate = argResults['force'];
|
final bool forceUpdate = argResults['force'];
|
||||||
if (forceUpdate || !cache.isUpToDate()) {
|
if (forceUpdate || !cache.isUpToDate()) {
|
||||||
|
@ -644,7 +644,7 @@ DevelopmentArtifact _artifactFromTargetPlatform(TargetPlatform targetPlatform) {
|
|||||||
case TargetPlatform.android_arm64:
|
case TargetPlatform.android_arm64:
|
||||||
case TargetPlatform.android_x64:
|
case TargetPlatform.android_x64:
|
||||||
case TargetPlatform.android_x86:
|
case TargetPlatform.android_x86:
|
||||||
return DevelopmentArtifact.android;
|
return DevelopmentArtifact.androidGenSnapshot;
|
||||||
case TargetPlatform.web_javascript:
|
case TargetPlatform.web_javascript:
|
||||||
return DevelopmentArtifact.web;
|
return DevelopmentArtifact.web;
|
||||||
case TargetPlatform.ios:
|
case TargetPlatform.ios:
|
||||||
|
@ -47,9 +47,9 @@ dependencies {
|
|||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||||
{{/androidX}}
|
{{/androidX}}
|
||||||
{{^androidX}}
|
{{^androidX}}
|
||||||
implementation 'com.android.support:appcompat-v7:27.1.1'
|
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||||
implementation 'com.android.support:design:27.1.1'
|
implementation 'com.android.support:design:28.0.0'
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||||
{{/androidX}}
|
{{/androidX}}
|
||||||
|
@ -8,8 +8,10 @@ import 'package:file_testing/file_testing.dart';
|
|||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
import 'package:platform/platform.dart';
|
import 'package:platform/platform.dart';
|
||||||
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
import 'package:flutter_tools/src/base/common.dart';
|
import 'package:flutter_tools/src/base/common.dart';
|
||||||
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
import 'package:flutter_tools/src/cache.dart';
|
import 'package:flutter_tools/src/cache.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/io.dart' show InternetAddress, SocketException;
|
import 'package:flutter_tools/src/base/io.dart' show InternetAddress, SocketException;
|
||||||
@ -136,18 +138,30 @@ void main() {
|
|||||||
when(artifact1.isUpToDate()).thenReturn(true);
|
when(artifact1.isUpToDate()).thenReturn(true);
|
||||||
when(artifact2.isUpToDate()).thenReturn(false);
|
when(artifact2.isUpToDate()).thenReturn(false);
|
||||||
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
|
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
|
||||||
await cache.updateAll(<DevelopmentArtifact>{});
|
await cache.updateAll(<DevelopmentArtifact>{
|
||||||
verifyNever(artifact1.update(<DevelopmentArtifact>{}));
|
null,
|
||||||
verify(artifact2.update(<DevelopmentArtifact>{}));
|
});
|
||||||
|
verifyNever(artifact1.update());
|
||||||
|
verify(artifact2.update());
|
||||||
});
|
});
|
||||||
testUsingContext('getter dyLdLibEntry concatenates the output of each artifact\'s dyLdLibEntry getter', () async {
|
testUsingContext('getter dyLdLibEntry concatenates the output of each artifact\'s dyLdLibEntry getter', () async {
|
||||||
final CachedArtifact artifact1 = MockCachedArtifact();
|
final IosUsbArtifacts artifact1 = MockIosUsbArtifacts();
|
||||||
final CachedArtifact artifact2 = MockCachedArtifact();
|
final IosUsbArtifacts artifact2 = MockIosUsbArtifacts();
|
||||||
final CachedArtifact artifact3 = MockCachedArtifact();
|
final IosUsbArtifacts artifact3 = MockIosUsbArtifacts();
|
||||||
when(artifact1.dyLdLibPath).thenReturn('/path/to/alpha:/path/to/beta');
|
when(artifact1.environment)
|
||||||
when(artifact2.dyLdLibPath).thenReturn('/path/to/gamma:/path/to/delta:/path/to/epsilon');
|
.thenReturn(<String, String>{
|
||||||
when(artifact3.dyLdLibPath).thenReturn(''); // Empty output
|
'DYLD_LIBRARY_PATH': '/path/to/alpha:/path/to/beta',
|
||||||
|
});
|
||||||
|
when(artifact2.environment)
|
||||||
|
.thenReturn(<String, String>{
|
||||||
|
'DYLD_LIBRARY_PATH': '/path/to/gamma:/path/to/delta:/path/to/epsilon',
|
||||||
|
});
|
||||||
|
when(artifact3.environment)
|
||||||
|
.thenReturn(<String, String>{
|
||||||
|
'DYLD_LIBRARY_PATH': '',
|
||||||
|
});
|
||||||
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2, artifact3]);
|
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2, artifact3]);
|
||||||
|
|
||||||
expect(cache.dyLdLibEntry.key, 'DYLD_LIBRARY_PATH');
|
expect(cache.dyLdLibEntry.key, 'DYLD_LIBRARY_PATH');
|
||||||
expect(
|
expect(
|
||||||
cache.dyLdLibEntry.value,
|
cache.dyLdLibEntry.value,
|
||||||
@ -163,18 +177,20 @@ void main() {
|
|||||||
when(artifact2.isUpToDate()).thenReturn(false);
|
when(artifact2.isUpToDate()).thenReturn(false);
|
||||||
final MockInternetAddress address = MockInternetAddress();
|
final MockInternetAddress address = MockInternetAddress();
|
||||||
when(address.host).thenReturn('storage.googleapis.com');
|
when(address.host).thenReturn('storage.googleapis.com');
|
||||||
when(artifact1.update(<DevelopmentArtifact>{})).thenThrow(SocketException(
|
when(artifact1.update()).thenThrow(SocketException(
|
||||||
'Connection reset by peer',
|
'Connection reset by peer',
|
||||||
address: address,
|
address: address,
|
||||||
));
|
));
|
||||||
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
|
final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
|
||||||
try {
|
try {
|
||||||
await cache.updateAll(<DevelopmentArtifact>{});
|
await cache.updateAll(<DevelopmentArtifact>{
|
||||||
|
null,
|
||||||
|
});
|
||||||
fail('Mock thrown exception expected');
|
fail('Mock thrown exception expected');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
verify(artifact1.update(<DevelopmentArtifact>{}));
|
verify(artifact1.update());
|
||||||
// Don't continue when retrieval fails.
|
// Don't continue when retrieval fails.
|
||||||
verifyNever(artifact2.update(<DevelopmentArtifact>{}));
|
verifyNever(artifact2.update());
|
||||||
expect(
|
expect(
|
||||||
testLogger.errorText,
|
testLogger.errorText,
|
||||||
contains('https://flutter.dev/community/china'),
|
contains('https://flutter.dev/community/china'),
|
||||||
@ -226,6 +242,7 @@ void main() {
|
|||||||
binaryDirs: <List<String>>[
|
binaryDirs: <List<String>>[
|
||||||
<String>['bin_dir', 'unused_url_path'],
|
<String>['bin_dir', 'unused_url_path'],
|
||||||
],
|
],
|
||||||
|
requiredArtifacts: DevelopmentArtifact.universal,
|
||||||
);
|
);
|
||||||
await artifact.updateInner();
|
await artifact.updateInner();
|
||||||
final Directory dir = memoryFileSystem.systemTempDirectory
|
final Directory dir = memoryFileSystem.systemTempDirectory
|
||||||
@ -244,25 +261,56 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('throws tool exit on fs exception', () async {
|
group('AndroidMavenArtifacts', () {
|
||||||
final FakeCachedArtifact fakeCachedArtifact = FakeCachedArtifact(
|
MemoryFileSystem memoryFileSystem;
|
||||||
cache: MockCache(),
|
MockProcessManager processManager;
|
||||||
requiredArtifacts: <DevelopmentArtifact>{
|
MockCache mockCache;
|
||||||
DevelopmentArtifact.android,
|
MockProcess mockProcess;
|
||||||
}
|
|
||||||
);
|
|
||||||
final Directory mockDirectory = MockDirectory();
|
|
||||||
when(fakeCachedArtifact.cache.getArtifactDirectory(any))
|
|
||||||
.thenReturn(mockDirectory);
|
|
||||||
when(mockDirectory.existsSync()).thenReturn(false);
|
|
||||||
when(mockDirectory.createSync(recursive: true))
|
|
||||||
.thenThrow(const FileSystemException());
|
|
||||||
|
|
||||||
expect(() => fakeCachedArtifact.update(<DevelopmentArtifact>{
|
setUp(() {
|
||||||
DevelopmentArtifact.android,
|
memoryFileSystem = MemoryFileSystem();
|
||||||
}), throwsA(isInstanceOf<ToolExit>()));
|
processManager = MockProcessManager();
|
||||||
|
mockCache = MockCache();
|
||||||
|
mockProcess = MockProcess();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('development artifact', () async {
|
||||||
|
final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts();
|
||||||
|
expect(mavenArtifacts.developmentArtifact, DevelopmentArtifact.androidMaven);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('update', () async {
|
||||||
|
final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts();
|
||||||
|
expect(mavenArtifacts.isUpToDate(), isFalse);
|
||||||
|
|
||||||
|
final Directory gradleWrapperDir = fs.systemTempDirectory.createTempSync('gradle_wrapper.');
|
||||||
|
when(mockCache.getArtifactDirectory('gradle_wrapper')).thenReturn(gradleWrapperDir);
|
||||||
|
|
||||||
|
fs.directory(gradleWrapperDir.childDirectory('gradle').childDirectory('wrapper'))
|
||||||
|
.createSync(recursive: true);
|
||||||
|
fs.file(fs.path.join(gradleWrapperDir.path, 'gradlew')).writeAsStringSync('irrelevant');
|
||||||
|
fs.file(fs.path.join(gradleWrapperDir.path, 'gradlew.bat')).writeAsStringSync('irrelevant');
|
||||||
|
|
||||||
|
when(processManager.start(any))
|
||||||
|
.thenAnswer((Invocation invocation){
|
||||||
|
final List<String> args = invocation.positionalArguments[0];
|
||||||
|
expect(args.length, 6);
|
||||||
|
expect(args[1], '-b');
|
||||||
|
expect(args[2].endsWith('resolve_dependencies.gradle'), isTrue);
|
||||||
|
expect(args[5], 'resolveDependencies');
|
||||||
|
|
||||||
|
return Future<Process>.value(mockProcess);
|
||||||
|
});
|
||||||
|
when(mockProcess.exitCode).thenAnswer((_) async => 0);
|
||||||
|
|
||||||
|
await mavenArtifacts.update();
|
||||||
|
|
||||||
|
expect(mavenArtifacts.isUpToDate(), isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
FileSystem: () => MemoryFileSystem(),
|
Cache: ()=> mockCache,
|
||||||
|
FileSystem: () => memoryFileSystem,
|
||||||
|
ProcessManager: () => processManager,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +318,7 @@ class FakeCachedArtifact extends EngineCachedArtifact {
|
|||||||
FakeCachedArtifact({
|
FakeCachedArtifact({
|
||||||
String stampName = 'STAMP',
|
String stampName = 'STAMP',
|
||||||
@required Cache cache,
|
@required Cache cache,
|
||||||
Set<DevelopmentArtifact> requiredArtifacts = const <DevelopmentArtifact>{},
|
DevelopmentArtifact requiredArtifacts,
|
||||||
this.binaryDirs = const <List<String>>[],
|
this.binaryDirs = const <List<String>>[],
|
||||||
this.licenseDirs = const <String>[],
|
this.licenseDirs = const <String>[],
|
||||||
this.packageDirs = const <String>[],
|
this.packageDirs = const <String>[],
|
||||||
@ -290,12 +338,15 @@ class FakeCachedArtifact extends EngineCachedArtifact {
|
|||||||
List<String> getPackageDirs() => packageDirs;
|
List<String> getPackageDirs() => packageDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockProcessManager extends Mock implements ProcessManager {}
|
||||||
|
class MockProcess extends Mock implements Process {}
|
||||||
class MockFileSystem extends Mock implements FileSystem {}
|
class MockFileSystem extends Mock implements FileSystem {}
|
||||||
class MockFile extends Mock implements File {}
|
class MockFile extends Mock implements File {}
|
||||||
class MockDirectory extends Mock implements Directory {}
|
class MockDirectory extends Mock implements Directory {}
|
||||||
|
|
||||||
class MockRandomAccessFile extends Mock implements RandomAccessFile {}
|
class MockRandomAccessFile extends Mock implements RandomAccessFile {}
|
||||||
class MockCachedArtifact extends Mock implements CachedArtifact {}
|
class MockCachedArtifact extends Mock implements CachedArtifact {}
|
||||||
|
class MockIosUsbArtifacts extends Mock implements IosUsbArtifacts {}
|
||||||
class MockInternetAddress extends Mock implements InternetAddress {}
|
class MockInternetAddress extends Mock implements InternetAddress {}
|
||||||
class MockCache extends Mock implements Cache {}
|
class MockCache extends Mock implements Cache {}
|
||||||
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
|
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
|
||||||
|
@ -27,12 +27,24 @@ void main() {
|
|||||||
final PrecacheCommand command = PrecacheCommand();
|
final PrecacheCommand command = PrecacheCommand();
|
||||||
applyMocksToCommand(command);
|
applyMocksToCommand(command);
|
||||||
await createTestCommandRunner(command).run(
|
await createTestCommandRunner(command).run(
|
||||||
const <String>['precache', '--ios', '--android', '--web', '--macos', '--linux', '--windows', '--fuchsia', '--flutter_runner']
|
const <String>[
|
||||||
|
'precache',
|
||||||
|
'--ios',
|
||||||
|
'--android',
|
||||||
|
'--web',
|
||||||
|
'--macos',
|
||||||
|
'--linux',
|
||||||
|
'--windows',
|
||||||
|
'--fuchsia',
|
||||||
|
'--flutter_runner',
|
||||||
|
]
|
||||||
);
|
);
|
||||||
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
|
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
|
||||||
DevelopmentArtifact.universal,
|
DevelopmentArtifact.universal,
|
||||||
DevelopmentArtifact.iOS,
|
DevelopmentArtifact.iOS,
|
||||||
DevelopmentArtifact.android,
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
|
DevelopmentArtifact.androidMaven,
|
||||||
|
DevelopmentArtifact.androidInternalBuild,
|
||||||
DevelopmentArtifact.web,
|
DevelopmentArtifact.web,
|
||||||
DevelopmentArtifact.macOS,
|
DevelopmentArtifact.macOS,
|
||||||
DevelopmentArtifact.linux,
|
DevelopmentArtifact.linux,
|
||||||
@ -44,6 +56,54 @@ void main() {
|
|||||||
Cache: () => cache,
|
Cache: () => cache,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testUsingContext('Expands android artifacts when the android flag is used', () async {
|
||||||
|
// Release lock between test cases.
|
||||||
|
Cache.releaseLockEarly();
|
||||||
|
|
||||||
|
final PrecacheCommand command = PrecacheCommand();
|
||||||
|
applyMocksToCommand(command);
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
const <String>[
|
||||||
|
'precache',
|
||||||
|
'--no-ios',
|
||||||
|
'--android',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
|
||||||
|
DevelopmentArtifact.universal,
|
||||||
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
|
DevelopmentArtifact.androidMaven,
|
||||||
|
DevelopmentArtifact.androidInternalBuild,
|
||||||
|
}));
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
Cache: () => cache,
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('Adds artifact flags to requested android artifacts', () async {
|
||||||
|
// Release lock between test cases.
|
||||||
|
Cache.releaseLockEarly();
|
||||||
|
|
||||||
|
final PrecacheCommand command = PrecacheCommand();
|
||||||
|
applyMocksToCommand(command);
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
const <String>[
|
||||||
|
'precache',
|
||||||
|
'--no-ios',
|
||||||
|
'--android_gen_snapshot',
|
||||||
|
'--android_maven',
|
||||||
|
'--android_internal_build',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
|
||||||
|
DevelopmentArtifact.universal,
|
||||||
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
|
DevelopmentArtifact.androidMaven,
|
||||||
|
DevelopmentArtifact.androidInternalBuild,
|
||||||
|
}));
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
Cache: () => cache,
|
||||||
|
});
|
||||||
|
|
||||||
final MockFlutterVersion flutterVersion = MockFlutterVersion();
|
final MockFlutterVersion flutterVersion = MockFlutterVersion();
|
||||||
when(flutterVersion.isMaster).thenReturn(false);
|
when(flutterVersion.isMaster).thenReturn(false);
|
||||||
|
|
||||||
@ -53,18 +113,31 @@ void main() {
|
|||||||
final PrecacheCommand command = PrecacheCommand();
|
final PrecacheCommand command = PrecacheCommand();
|
||||||
applyMocksToCommand(command);
|
applyMocksToCommand(command);
|
||||||
await createTestCommandRunner(command).run(
|
await createTestCommandRunner(command).run(
|
||||||
const <String>['precache', '--ios', '--android', '--web', '--macos', '--linux', '--windows', '--fuchsia', '--flutter_runner']
|
const <String>[
|
||||||
|
'precache',
|
||||||
|
'--ios',
|
||||||
|
'--android_gen_snapshot',
|
||||||
|
'--android_maven',
|
||||||
|
'--android_internal_build',
|
||||||
|
'--web',
|
||||||
|
'--macos',
|
||||||
|
'--linux',
|
||||||
|
'--windows',
|
||||||
|
'--fuchsia',
|
||||||
|
'--flutter_runner',
|
||||||
|
]
|
||||||
);
|
);
|
||||||
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
|
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
|
||||||
DevelopmentArtifact.universal,
|
DevelopmentArtifact.universal,
|
||||||
DevelopmentArtifact.iOS,
|
DevelopmentArtifact.iOS,
|
||||||
DevelopmentArtifact.android,
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
|
DevelopmentArtifact.androidMaven,
|
||||||
|
DevelopmentArtifact.androidInternalBuild,
|
||||||
}));
|
}));
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
Cache: () => cache,
|
Cache: () => cache,
|
||||||
FlutterVersion: () => flutterVersion,
|
FlutterVersion: () => flutterVersion,
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('Downloads artifacts when --force is provided', () async {
|
testUsingContext('Downloads artifacts when --force is provided', () async {
|
||||||
when(cache.isUpToDate()).thenReturn(true);
|
when(cache.isUpToDate()).thenReturn(true);
|
||||||
// Release lock between test cases.
|
// Release lock between test cases.
|
||||||
@ -75,7 +148,9 @@ void main() {
|
|||||||
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
|
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
|
||||||
DevelopmentArtifact.universal,
|
DevelopmentArtifact.universal,
|
||||||
DevelopmentArtifact.iOS,
|
DevelopmentArtifact.iOS,
|
||||||
DevelopmentArtifact.android,
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
|
DevelopmentArtifact.androidMaven,
|
||||||
|
DevelopmentArtifact.androidInternalBuild,
|
||||||
}));
|
}));
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
Cache: () => cache,
|
Cache: () => cache,
|
||||||
|
@ -138,7 +138,7 @@ void main() {
|
|||||||
|
|
||||||
expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{
|
expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{
|
||||||
DevelopmentArtifact.universal,
|
DevelopmentArtifact.universal,
|
||||||
DevelopmentArtifact.android,
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
|
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
|
||||||
@ -162,7 +162,7 @@ void main() {
|
|||||||
expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{
|
expect(await RunCommand().requiredArtifacts, unorderedEquals(<DevelopmentArtifact>{
|
||||||
DevelopmentArtifact.universal,
|
DevelopmentArtifact.universal,
|
||||||
DevelopmentArtifact.iOS,
|
DevelopmentArtifact.iOS,
|
||||||
DevelopmentArtifact.android,
|
DevelopmentArtifact.androidGenSnapshot,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
|
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user