Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
96482eeb
Unverified
Commit
96482eeb
authored
Sep 20, 2019
by
Emmanuel Garcia
Committed by
GitHub
Sep 20, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Re-enable AAR plugins when an AndroidX failure occurred (#40810)
parent
c238045a
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
401 additions
and
247 deletions
+401
-247
test.dart
dev/bots/test.dart
+1
-0
gradle_jetifier_test.dart
dev/devicelab/bin/tasks/gradle_jetifier_test.dart
+4
-1
aar_init_script.gradle
packages/flutter_tools/gradle/aar_init_script.gradle
+27
-10
flutter.gradle
packages/flutter_tools/gradle/flutter.gradle
+54
-156
gradle.dart
packages/flutter_tools/lib/src/android/gradle.dart
+149
-53
features.dart
packages/flutter_tools/lib/src/features.dart
+0
-3
events.dart
packages/flutter_tools/lib/src/reporting/events.dart
+4
-0
usage.dart
packages/flutter_tools/lib/src/reporting/usage.dart
+1
-0
gradle_test.dart
...flutter_tools/test/general.shard/android/gradle_test.dart
+161
-5
features_test.dart
packages/flutter_tools/test/general.shard/features_test.dart
+0
-15
testbed.dart
packages/flutter_tools/test/src/testbed.dart
+0
-4
No files found.
dev/bots/test.dart
View file @
96482eeb
...
@@ -1022,6 +1022,7 @@ Future<void> _androidGradleTests(String subShard) async {
...
@@ -1022,6 +1022,7 @@ Future<void> _androidGradleTests(String subShard) async {
await
_runDevicelabTest
(
'gradle_plugin_fat_apk_test'
,
env:
env
);
await
_runDevicelabTest
(
'gradle_plugin_fat_apk_test'
,
env:
env
);
await
_runDevicelabTest
(
'gradle_r8_test'
,
env:
env
);
await
_runDevicelabTest
(
'gradle_r8_test'
,
env:
env
);
await
_runDevicelabTest
(
'gradle_non_android_plugin_test'
,
env:
env
);
await
_runDevicelabTest
(
'gradle_non_android_plugin_test'
,
env:
env
);
await
_runDevicelabTest
(
'gradle_jetifier_test'
,
env:
env
);
}
}
if
(
subShard
==
'gradle2'
)
{
if
(
subShard
==
'gradle2'
)
{
await
_runDevicelabTest
(
'gradle_plugin_bundle_test'
,
env:
env
);
await
_runDevicelabTest
(
'gradle_plugin_bundle_test'
,
env:
env
);
...
...
dev/devicelab/bin/tasks/gradle_jetifier_test.dart
View file @
96482eeb
...
@@ -64,6 +64,7 @@ Future<void> main() async {
...
@@ -64,6 +64,7 @@ Future<void> main() async {
options:
<
String
>[
options:
<
String
>[
'apk'
,
'apk'
,
'--target-platform'
,
'android-arm'
,
'--target-platform'
,
'android-arm'
,
'--no-shrink'
,
'--verbose'
,
'--verbose'
,
],
],
);
);
...
@@ -100,7 +101,9 @@ Future<void> main() async {
...
@@ -100,7 +101,9 @@ Future<void> main() async {
options:
<
String
>[
options:
<
String
>[
'apk'
,
'apk'
,
'--target-platform'
,
'android-arm'
,
'--target-platform'
,
'android-arm'
,
'--debug'
,
'--verbose'
,
'--debug'
,
'--no-shrink'
,
'--verbose'
,
],
],
);
);
});
});
...
...
packages/flutter_tools/gradle/aar_init_script.gradle
View file @
96482eeb
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
// destination of the local repository.
// destination of the local repository.
// The local repository will contain the AAR and POM files.
// The local repository will contain the AAR and POM files.
import
java.nio.file.Paths
import
org.gradle.api.Project
import
org.gradle.api.Project
import
org.gradle.api.artifacts.Configuration
import
org.gradle.api.artifacts.Configuration
import
org.gradle.api.artifacts.maven.MavenDeployer
import
org.gradle.api.artifacts.maven.MavenDeployer
...
@@ -39,16 +40,32 @@ void configureProject(Project project, File outputDir) {
...
@@ -39,16 +40,32 @@ void configureProject(Project project, File outputDir) {
}
}
}
}
}
}
// Check if the project uses the Flutter plugin (defined in flutter.gradle).
if
(!
project
.
property
(
"is-plugin"
).
toBoolean
())
{
Boolean
usesFlutterPlugin
=
project
.
plugins
.
find
{
it
.
class
.
name
==
"FlutterPlugin"
}
!=
null
return
if
(!
usesFlutterPlugin
)
{
}
project
.
dependencies
{
if
(
project
.
hasProperty
(
'localEngineOut'
))
{
// Some plugins don't include `annotations` and they don't set
// TODO(egarciad): Support local engine.
// `android.useAndroidX=true` in `gradle.properties`.
// This most likely requires refactoring `flutter.gradle`, so the logic can be reused.
compileOnly
"androidx.annotation:annotation:+"
throw
new
GradleException
(
compileOnly
"com.android.support:support-annotations:+"
"Local engine isn't supported when building the plugins as AAR. "
+
// The Flutter plugin already adds `flutter.jar`.
"See: https://github.com/flutter/flutter/issues/40866"
)
compileOnly
project
.
files
(
"${getFlutterRoot(project)}/bin/cache/artifacts/engine/android-arm-release/flutter.jar"
)
}
// This is a Flutter plugin project. Plugin projects don't apply the Flutter Gradle plugin,
// as a result, add the dependency on the embedding.
project
.
repositories
{
maven
{
url
"http://download.flutter.io"
}
}
String
engineVersion
=
Paths
.
get
(
getFlutterRoot
(
project
),
"bin"
,
"internal"
,
"engine.version"
)
.
toFile
().
text
.
trim
()
project
.
dependencies
{
// Add the embedding dependency.
compileOnly
(
"io.flutter:flutter_embedding_release:1.0.0-$engineVersion"
)
{
// We only need to expose io.flutter.plugin.*
// No need for the embedding transitive dependencies.
transitive
=
false
}
}
}
}
}
}
...
...
packages/flutter_tools/gradle/flutter.gradle
View file @
96482eeb
...
@@ -8,6 +8,8 @@ import com.android.builder.model.AndroidProject
...
@@ -8,6 +8,8 @@ import com.android.builder.model.AndroidProject
import
com.android.build.OutputFile
import
com.android.build.OutputFile
import
java.nio.file.Path
import
java.nio.file.Path
import
java.nio.file.Paths
import
java.nio.file.Paths
import
java.util.regex.Matcher
import
java.util.regex.Pattern
import
org.apache.tools.ant.taskdefs.condition.Os
import
org.apache.tools.ant.taskdefs.condition.Os
import
org.gradle.api.DefaultTask
import
org.gradle.api.DefaultTask
import
org.gradle.api.GradleException
import
org.gradle.api.GradleException
...
@@ -256,29 +258,65 @@ class FlutterPlugin implements Plugin<Project> {
...
@@ -256,29 +258,65 @@ class FlutterPlugin implements Plugin<Project> {
*/
*/
private
void
configurePlugins
()
{
private
void
configurePlugins
()
{
if
(!
buildPluginAsAar
())
{
if
(!
buildPluginAsAar
())
{
getPluginList
().
each
this
.&
configurePlugin
getPluginList
().
each
this
.&
configurePlugin
Project
return
return
}
}
addPluginTasks
()
if
(
useLocalEngine
())
{
List
<
String
>
tasksToExecute
=
project
.
gradle
.
startParameter
.
taskNames
throw
new
GradleException
(
"Local engine isn't supported when building the plugins as AAR"
)
Set
buildTypes
=
getBuildTypesForTasks
(
tasksToExecute
)
}
if
(
tasksToExecute
.
contains
(
"clean"
))
{
List
<
Project
>
projects
=
[
project
]
// Because the plugins are built during configuration, the task "clean"
// Module projects set the `hostProjects` extra property in `include_flutter.groovy`.
// cannot run in conjunction with an assembly task.
// This is required to set the local repository in each host app project.
if
(!
buildTypes
.
empty
)
{
if
(
project
.
ext
.
has
(
"hostProjects"
))
{
throw
new
GradleException
(
"Can't run the clean task along with other assemble tasks"
)
projects
.
addAll
(
project
.
ext
.
get
(
"hostProjects"
))
}
// Configure the repository for the plugins.
projects
.
each
{
hostProject
->
hostProject
.
repositories
{
maven
{
url
"${getPluginBuildDir()}/outputs/repo"
}
}
}
}
}
// Build plugins when a task "assembly*" will be called later.
getPluginList
().
each
{
pluginName
,
pluginPath
->
if
(!
buildTypes
.
empty
)
{
configurePluginAar
(
pluginName
,
pluginPath
,
project
)
// 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
_
)
{
private
static
final
Pattern
GROUP_PATTERN
=
~
/group\s+\'(.+)\'/
private
static
final
Pattern
PROJECT_NAME_PATTERN
=
~
/rootProject\.name\s+=\s+\'(.+)\'/
// Adds the plugin AAR dependency to the app project.
private
void
configurePluginAar
(
String
pluginName
,
String
pluginPath
,
Project
project
)
{
// Extract the group id from the plugin's build.gradle.
// This is `group '<group-id>'`
File
pluginBuildFile
=
project
.
file
(
Paths
.
get
(
pluginPath
,
"android"
,
"build.gradle"
));
if
(!
pluginBuildFile
.
exists
())
{
throw
new
GradleException
(
"Plugin $pluginName doesn't have the required file $pluginBuildFile."
)
}
Matcher
groupParts
=
GROUP_PATTERN
.
matcher
(
pluginBuildFile
.
text
)
assert
groupParts
.
count
==
1
assert
groupParts
.
hasGroup
()
String
groupId
=
groupParts
[
0
][
1
]
// Extract the artifact name from the plugin's settings.gradle.
// This is `rootProject.name = '<artifact-name>'`
File
pluginSettings
=
project
.
file
(
Paths
.
get
(
pluginPath
,
"android"
,
"settings.gradle"
));
if
(!
pluginSettings
.
exists
())
{
throw
new
GradleException
(
"Plugin $pluginName doesn't have the required file $pluginSettings."
)
}
Matcher
projectNameParts
=
PROJECT_NAME_PATTERN
.
matcher
(
pluginSettings
.
text
)
assert
projectNameParts
.
count
==
1
assert
projectNameParts
.
hasGroup
()
String
artifactId
=
"${projectNameParts[0][1]}_release"
assert
!
groupId
.
empty
project
.
dependencies
.
add
(
"api"
,
"$groupId:$artifactId:+"
)
}
// Adds the plugin project dependency to the app project .
private
void
configurePluginProject
(
String
name
,
String
_
)
{
Project
pluginProject
=
project
.
rootProject
.
findProject
(
":$name"
)
Project
pluginProject
=
project
.
rootProject
.
findProject
(
":$name"
)
if
(
pluginProject
==
null
)
{
if
(
pluginProject
==
null
)
{
project
.
logger
.
error
(
"Plugin project :$name not found. Please update settings.gradle."
)
project
.
logger
.
error
(
"Plugin project :$name not found. Please update settings.gradle."
)
...
@@ -343,93 +381,6 @@ class FlutterPlugin implements Plugin<Project> {
...
@@ -343,93 +381,6 @@ class FlutterPlugin implements Plugin<Project> {
return
androidPlugins
return
androidPlugins
}
}
private
void
addPluginTasks
()
{
Properties
plugins
=
getPluginList
()
project
.
android
.
buildTypes
.
each
{
buildType
->
plugins
.
each
{
name
,
path
->
String
buildModeValue
=
buildType
.
debuggable
?
"debug"
:
"release"
List
<
String
>
taskNameParts
=
[
"build"
,
"plugin"
,
buildModeValue
]
taskNameParts
.
addAll
(
name
.
split
(
"_"
))
String
taskName
=
toCammelCase
(
taskNameParts
)
// Build types can be extended. For example, a build type can extend the `debug` mode.
// In such cases, prevent creating the same task.
if
(
project
.
tasks
.
findByName
(
taskName
)
==
null
)
{
project
.
tasks
.
create
(
name:
taskName
,
type:
FlutterPluginTask
)
{
flutterExecutable
this
.
flutterExecutable
buildMode
buildModeValue
verbose
isVerbose
()
pluginDir
project
.
file
(
path
)
sourceDir
project
.
file
(
project
.
flutter
.
source
)
intermediateDir
getPluginBuildDir
()
}
}
}
}
}
private
void
buildAarPlugins
(
Set
buildTypes
)
{
List
<
Project
>
projects
=
[
project
]
// Module projects set the `hostProjects` extra property in `include_flutter.groovy`.
// This is required to set the local repository in each host app project.
if
(
project
.
ext
.
has
(
"hostProjects"
))
{
projects
.
addAll
(
project
.
ext
.
get
(
"hostProjects"
))
}
projects
.
each
{
hostProject
->
hostProject
.
repositories
{
maven
{
url
"${getPluginBuildDir()}/outputs/repo"
}
}
}
buildTypes
.
each
{
buildType
->
project
.
tasks
.
withType
(
FlutterPluginTask
).
all
{
pluginTask
->
String
buildMode
=
buildType
.
debuggable
?
"debug"
:
"release"
if
(
pluginTask
.
buildMode
!=
buildMode
)
{
return
}
pluginTask
.
execute
()
pluginTask
.
intermediateDir
.
eachFileRecurse
(
FILES
)
{
file
->
if
(
file
.
name
!=
"maven-metadata.xml"
)
{
return
}
def
mavenMetadata
=
new
XmlParser
().
parse
(
file
)
String
groupId
=
mavenMetadata
.
groupId
.
text
()
String
artifactId
=
mavenMetadata
.
artifactId
.
text
()
if
(!
artifactId
.
endsWith
(
buildMode
))
{
return
}
// Add the plugin dependency based on the Maven metadata.
addApiDependencies
(
project
,
buildType
.
name
,
"$groupId:$artifactId:+@aar"
,
{
transitive
=
true
})
}
}
}
}
/**
* Returns a set with the build type names that apply to the given list of tasks
* required to configure the plugin dependencies.
*/
private
Set
getBuildTypesForTasks
(
List
<
String
>
tasksToExecute
)
{
Set
buildTypes
=
[]
tasksToExecute
.
each
{
task
->
project
.
android
.
buildTypes
.
each
{
buildType
->
if
(
task
==
"androidDependencies"
||
task
.
endsWith
(
"dependencies"
))
{
// The tasks to query the dependencies includes all the build types.
buildTypes
.
add
(
buildType
)
}
else
if
(
task
.
endsWith
(
"assemble"
))
{
// The `assemble` task includes all the build types.
buildTypes
.
add
(
buildType
)
}
else
if
(
task
.
endsWith
(
buildType
.
name
.
capitalize
()))
{
buildTypes
.
add
(
buildType
)
}
}
}
return
buildTypes
}
private
static
String
toCammelCase
(
List
<
String
>
parts
)
{
private
static
String
toCammelCase
(
List
<
String
>
parts
)
{
if
(
parts
.
empty
)
{
if
(
parts
.
empty
)
{
return
""
return
""
...
@@ -920,56 +871,3 @@ class FlutterTask extends BaseFlutterTask {
...
@@ -920,56 +871,3 @@ class FlutterTask extends BaseFlutterTask {
buildBundle
()
buildBundle
()
}
}
}
}
class
FlutterPluginTask
extends
DefaultTask
{
File
flutterExecutable
@Optional
@Input
Boolean
verbose
@Input
String
buildMode
@Input
File
pluginDir
@Input
File
intermediateDir
File
sourceDir
@InputFiles
FileCollection
getSourceFiles
()
{
return
project
.
fileTree
(
dir:
sourceDir
,
exclude:
[
"android"
,
"ios"
],
include:
[
"pubspec.yaml"
]
)
}
@OutputDirectory
File
getOutputDirectory
()
{
return
intermediateDir
}
@TaskAction
void
build
()
{
intermediateDir
.
mkdirs
()
project
.
exec
{
executable
flutterExecutable
.
absolutePath
workingDir
pluginDir
args
"build"
,
"aar"
args
"--quiet"
args
"--suppress-analytics"
args
"--output-dir"
,
"${intermediateDir}"
switch
(
buildMode
)
{
case
'release'
:
args
"--release"
break
case
'debug'
:
args
"--debug"
break
default:
assert
false
}
if
(
verbose
)
{
args
"--verbose"
}
}
}
}
packages/flutter_tools/lib/src/android/gradle.dart
View file @
96482eeb
...
@@ -22,7 +22,6 @@ import '../base/utils.dart';
...
@@ -22,7 +22,6 @@ import '../base/utils.dart';
import
'../base/version.dart'
;
import
'../base/version.dart'
;
import
'../build_info.dart'
;
import
'../build_info.dart'
;
import
'../cache.dart'
;
import
'../cache.dart'
;
import
'../features.dart'
;
import
'../flutter_manifest.dart'
;
import
'../flutter_manifest.dart'
;
import
'../globals.dart'
;
import
'../globals.dart'
;
import
'../project.dart'
;
import
'../project.dart'
;
...
@@ -47,18 +46,20 @@ class GradleUtils {
...
@@ -47,18 +46,20 @@ class GradleUtils {
return
_cachedExecutable
;
return
_cachedExecutable
;
}
}
GradleProject
_cachedAppProject
;
final
Map
<
FlutterProject
,
GradleProject
>
_cachedAppProject
=
/// Gets the [GradleProject] for the current [FlutterProject] if built as an app.
<
FlutterProject
,
GradleProject
>{};
Future
<
GradleProject
>
get
appProject
async
{
/// Gets the [GradleProject] for the [project] if built as an app.
_cachedAppProject
??=
await
_readGradleProject
(
isLibrary:
false
);
Future
<
GradleProject
>
getAppProject
(
FlutterProject
project
)
async
{
return
_cachedAppProject
;
_cachedAppProject
[
project
]
??=
await
_readGradleProject
(
project
,
isLibrary:
false
);
return
_cachedAppProject
[
project
];
}
}
GradleProject
_cachedLibraryProject
;
final
Map
<
FlutterProject
,
GradleProject
>
_cachedLibraryProject
=
/// Gets the [GradleProject] for the current [FlutterProject] if built as a library.
<
FlutterProject
,
GradleProject
>{};
Future
<
GradleProject
>
get
libraryProject
async
{
/// Gets the [GradleProject] for the [project] if built as a library.
_cachedLibraryProject
??=
await
_readGradleProject
(
isLibrary:
true
);
Future
<
GradleProject
>
getLibraryProject
(
FlutterProject
project
)
async
{
return
_cachedLibraryProject
;
_cachedLibraryProject
[
project
]
??=
await
_readGradleProject
(
project
,
isLibrary:
true
);
return
_cachedLibraryProject
[
project
];
}
}
}
}
...
@@ -133,7 +134,8 @@ Future<File> getGradleAppOut(AndroidProject androidProject) async {
...
@@ -133,7 +134,8 @@ Future<File> getGradleAppOut(AndroidProject androidProject) async {
case
FlutterPluginVersion
.
managed
:
case
FlutterPluginVersion
.
managed
:
// Fall through. The managed plugin matches plugin v2 for now.
// Fall through. The managed plugin matches plugin v2 for now.
case
FlutterPluginVersion
.
v2
:
case
FlutterPluginVersion
.
v2
:
final
GradleProject
gradleProject
=
await
gradleUtils
.
appProject
;
final
GradleProject
gradleProject
=
await
gradleUtils
.
getAppProject
(
FlutterProject
.
current
());
return
fs
.
file
(
gradleProject
.
apkDirectory
.
childFile
(
'app.apk'
));
return
fs
.
file
(
gradleProject
.
apkDirectory
.
childFile
(
'app.apk'
));
}
}
return
null
;
return
null
;
...
@@ -209,8 +211,10 @@ void createSettingsAarGradle(Directory androidDirectory) {
...
@@ -209,8 +211,10 @@ void createSettingsAarGradle(Directory androidDirectory) {
// Note: Dependencies are resolved and possibly downloaded as a side-effect
// Note: Dependencies are resolved and possibly downloaded as a side-effect
// of calculating the app properties using Gradle. This may take minutes.
// of calculating the app properties using Gradle. This may take minutes.
Future
<
GradleProject
>
_readGradleProject
({
bool
isLibrary
=
false
})
async
{
Future
<
GradleProject
>
_readGradleProject
(
final
FlutterProject
flutterProject
=
FlutterProject
.
current
();
FlutterProject
flutterProject
,
{
bool
isLibrary
=
false
,
})
async
{
final
String
gradlew
=
await
gradleUtils
.
getExecutable
(
flutterProject
);
final
String
gradlew
=
await
gradleUtils
.
getExecutable
(
flutterProject
);
updateLocalProperties
(
project:
flutterProject
);
updateLocalProperties
(
project:
flutterProject
);
...
@@ -218,10 +222,6 @@ Future<GradleProject> _readGradleProject({bool isLibrary = false}) async {
...
@@ -218,10 +222,6 @@ Future<GradleProject> _readGradleProject({bool isLibrary = false}) async {
final
FlutterManifest
manifest
=
flutterProject
.
manifest
;
final
FlutterManifest
manifest
=
flutterProject
.
manifest
;
final
Directory
hostAppGradleRoot
=
flutterProject
.
android
.
hostAppGradleRoot
;
final
Directory
hostAppGradleRoot
=
flutterProject
.
android
.
hostAppGradleRoot
;
if
(
featureFlags
.
isPluginAsAarEnabled
&&
!
manifest
.
isPlugin
&&
!
manifest
.
isModule
)
{
createSettingsAarGradle
(
hostAppGradleRoot
);
}
if
(
manifest
.
isPlugin
)
{
if
(
manifest
.
isPlugin
)
{
assert
(
isLibrary
);
assert
(
isLibrary
);
return
GradleProject
(
return
GradleProject
(
...
@@ -581,9 +581,9 @@ Future<void> buildGradleAar({
...
@@ -581,9 +581,9 @@ Future<void> buildGradleAar({
GradleProject
gradleProject
;
GradleProject
gradleProject
;
if
(
manifest
.
isModule
)
{
if
(
manifest
.
isModule
)
{
gradleProject
=
await
gradleUtils
.
appProject
;
gradleProject
=
await
gradleUtils
.
getAppProject
(
project
)
;
}
else
if
(
manifest
.
isPlugin
)
{
}
else
if
(
manifest
.
isPlugin
)
{
gradleProject
=
await
gradleUtils
.
libraryProject
;
gradleProject
=
await
gradleUtils
.
getLibraryProject
(
project
)
;
}
else
{
}
else
{
throwToolExit
(
'AARs can only be built for plugin or module projects.'
);
throwToolExit
(
'AARs can only be built for plugin or module projects.'
);
}
}
...
@@ -612,13 +612,11 @@ Future<void> buildGradleAar({
...
@@ -612,13 +612,11 @@ Future<void> buildGradleAar({
'-Pflutter-root=
$flutterRoot
'
,
'-Pflutter-root=
$flutterRoot
'
,
'-Poutput-dir=
${gradleProject.buildDirectory}
'
,
'-Poutput-dir=
${gradleProject.buildDirectory}
'
,
'-Pis-plugin=
${manifest.isPlugin}
'
,
'-Pis-plugin=
${manifest.isPlugin}
'
,
'-Dbuild-plugins-as-aars=true'
,
];
];
if
(
target
!=
null
&&
target
.
isNotEmpty
)
{
if
(
target
!=
null
&&
target
.
isNotEmpty
)
{
command
.
add
(
'-Ptarget=
$target
'
);
command
.
add
(
'-Ptarget=
$target
'
);
}
}
if
(
androidBuildInfo
.
targetArchs
.
isNotEmpty
)
{
if
(
androidBuildInfo
.
targetArchs
.
isNotEmpty
)
{
final
String
targetPlatforms
=
androidBuildInfo
.
targetArchs
final
String
targetPlatforms
=
androidBuildInfo
.
targetArchs
.
map
(
getPlatformNameForAndroidArch
).
join
(
','
);
.
map
(
getPlatformNameForAndroidArch
).
join
(
','
);
...
@@ -633,34 +631,30 @@ Future<void> buildGradleAar({
...
@@ -633,34 +631,30 @@ Future<void> buildGradleAar({
command
.
add
(
aarTask
);
command
.
add
(
aarTask
);
final
Stopwatch
sw
=
Stopwatch
()..
start
();
final
Stopwatch
sw
=
Stopwatch
()..
start
();
int
exitCode
=
1
;
RunResult
result
;
try
{
try
{
exitCode
=
await
processUtils
.
stream
(
result
=
await
processUtils
.
run
(
command
,
command
,
workingDirectory:
project
.
android
.
hostAppGradleRoot
.
path
,
workingDirectory:
project
.
android
.
hostAppGradleRoot
.
path
,
allowReentrantFlutter:
true
,
allowReentrantFlutter:
true
,
environment:
gradleEnv
,
environment:
gradleEnv
,
mapFunction:
(
String
line
)
{
// Always print the full line in verbose mode.
if
(
logger
.
isVerbose
)
{
return
line
;
}
return
null
;
},
);
);
}
finally
{
}
finally
{
status
.
stop
();
status
.
stop
();
}
}
flutterUsage
.
sendTiming
(
'build'
,
'gradle-aar'
,
Duration
(
milliseconds:
sw
.
elapsedMilliseconds
)
);
flutterUsage
.
sendTiming
(
'build'
,
'gradle-aar'
,
sw
.
elapsed
);
if
(
exitCode
!=
0
)
{
if
(
result
.
exitCode
!=
0
)
{
throwToolExit
(
'Gradle task
$aarTask
failed with exit code
$exitCode
'
,
exitCode:
exitCode
);
printStatus
(
result
.
stdout
,
wrap:
false
);
printError
(
result
.
stderr
,
wrap:
false
);
throwToolExit
(
'Gradle task
$aarTask
failed with exit code
$exitCode
.'
,
exitCode:
exitCode
);
}
}
final
Directory
repoDirectory
=
gradleProject
.
repoDirectory
;
final
Directory
repoDirectory
=
gradleProject
.
repoDirectory
;
if
(!
repoDirectory
.
existsSync
())
{
if
(!
repoDirectory
.
existsSync
())
{
throwToolExit
(
'Gradle task
$aarTask
failed to produce
$repoDirectory
'
,
exitCode:
exitCode
);
printStatus
(
result
.
stdout
,
wrap:
false
);
printError
(
result
.
stderr
,
wrap:
false
);
throwToolExit
(
'Gradle task
$aarTask
failed to produce
$repoDirectory
.'
,
exitCode:
exitCode
);
}
}
printStatus
(
'Built
${fs.path.relative(repoDirectory.path)}
.'
,
color:
TerminalColor
.
green
);
printStatus
(
'Built
${fs.path.relative(repoDirectory.path)}
.'
,
color:
TerminalColor
.
green
);
}
}
...
@@ -730,21 +724,33 @@ Future<void> _buildGradleProjectV2(
...
@@ -730,21 +724,33 @@ Future<void> _buildGradleProjectV2(
FlutterProject
flutterProject
,
FlutterProject
flutterProject
,
AndroidBuildInfo
androidBuildInfo
,
AndroidBuildInfo
androidBuildInfo
,
String
target
,
String
target
,
bool
isBuildingBundle
,
bool
isBuildingBundle
,
{
)
async
{
bool
shouldBuildPluginAsAar
=
false
,
})
async
{
final
String
gradlew
=
await
gradleUtils
.
getExecutable
(
flutterProject
);
final
String
gradlew
=
await
gradleUtils
.
getExecutable
(
flutterProject
);
final
GradleProject
project
=
await
gradleUtils
.
appProject
;
final
GradleProject
gradleProject
=
await
gradleUtils
.
getAppProject
(
flutterProject
);
if
(
shouldBuildPluginAsAar
)
{
// Create a settings.gradle that doesn't import the plugins as subprojects.
createSettingsAarGradle
(
flutterProject
.
android
.
hostAppGradleRoot
);
await
buildPluginsAsAar
(
flutterProject
,
androidBuildInfo
,
buildDirectory:
gradleProject
.
buildDirectory
,
);
}
final
BuildInfo
buildInfo
=
androidBuildInfo
.
buildInfo
;
final
BuildInfo
buildInfo
=
androidBuildInfo
.
buildInfo
;
String
assembleTask
;
String
assembleTask
;
if
(
isBuildingBundle
)
{
if
(
isBuildingBundle
)
{
assembleTask
=
p
roject
.
bundleTaskFor
(
buildInfo
);
assembleTask
=
gradleP
roject
.
bundleTaskFor
(
buildInfo
);
}
else
{
}
else
{
assembleTask
=
p
roject
.
assembleTaskFor
(
buildInfo
);
assembleTask
=
gradleP
roject
.
assembleTaskFor
(
buildInfo
);
}
}
if
(
assembleTask
==
null
)
{
if
(
assembleTask
==
null
)
{
printUndefinedTask
(
p
roject
,
buildInfo
);
printUndefinedTask
(
gradleP
roject
,
buildInfo
);
throwToolExit
(
'Gradle build aborted.'
);
throwToolExit
(
'Gradle build aborted.'
);
}
}
final
Status
status
=
logger
.
startProgress
(
final
Status
status
=
logger
.
startProgress
(
...
@@ -791,13 +797,12 @@ Future<void> _buildGradleProjectV2(
...
@@ -791,13 +797,12 @@ Future<void> _buildGradleProjectV2(
.
map
(
getPlatformNameForAndroidArch
).
join
(
','
);
.
map
(
getPlatformNameForAndroidArch
).
join
(
','
);
command
.
add
(
'-Ptarget-platform=
$targetPlatforms
'
);
command
.
add
(
'-Ptarget-platform=
$targetPlatforms
'
);
}
}
if
(
featureFlags
.
isPluginAsAarEnabled
)
{
if
(
shouldBuildPluginAsAar
)
{
// Pass a system flag instead of a project flag, so this flag can be
// Pass a system flag instead of a project flag, so this flag can be
// read from include_flutter.groovy.
// read from include_flutter.groovy.
command
.
add
(
'-Dbuild-plugins-as-aars=true'
);
command
.
add
(
'-Dbuild-plugins-as-aars=true'
);
if
(!
flutterProject
.
manifest
.
isModule
)
{
// Don't use settings.gradle from the current project since it includes the plugins as subprojects.
command
.
add
(
'--settings-file=settings_aar.gradle'
);
command
.
add
(
'--settings-file=settings_aar.gradle'
);
}
}
}
command
.
add
(
assembleTask
);
command
.
add
(
assembleTask
);
bool
potentialAndroidXFailure
=
false
;
bool
potentialAndroidXFailure
=
false
;
...
@@ -844,24 +849,60 @@ Future<void> _buildGradleProjectV2(
...
@@ -844,24 +849,60 @@ Future<void> _buildGradleProjectV2(
printStatus
(
'To learn more, see: https://developer.android.com/studio/build/shrink-code'
,
indent:
4
);
printStatus
(
'To learn more, see: https://developer.android.com/studio/build/shrink-code'
,
indent:
4
);
BuildEvent
(
'r8-failure'
).
send
();
BuildEvent
(
'r8-failure'
).
send
();
}
else
if
(
potentialAndroidXFailure
)
{
}
else
if
(
potentialAndroidXFailure
)
{
printStatus
(
'AndroidX incompatibilities may have caused this build to fail. See https://goo.gl/CP92wY.'
);
final
bool
hasPlugins
=
flutterProject
.
flutterPluginsFile
.
existsSync
();
BuildEvent
(
'android-x-failure'
).
send
();
final
bool
usesAndroidX
=
isAppUsingAndroidX
(
flutterProject
.
android
.
hostAppGradleRoot
);
if
(!
hasPlugins
)
{
// If the app doesn't use any plugin, then it's unclear where the incompatibility is coming from.
BuildEvent
(
'android-x-failure'
,
eventError:
'app-not-using-plugins'
).
send
();
}
if
(
hasPlugins
&&
!
usesAndroidX
)
{
// If the app isn't using AndroidX, then the app is likely using a plugin already migrated to AndroidX.
printStatus
(
'AndroidX incompatibilities may have caused this build to fail. '
);
printStatus
(
'Please migrate your app to AndroidX. See https://goo.gl/CP92wY.'
);
BuildEvent
(
'android-x-failure'
,
eventError:
'app-not-using-androidx'
).
send
();
}
if
(
hasPlugins
&&
usesAndroidX
&&
shouldBuildPluginAsAar
)
{
// This is a dependency conflict instead of an AndroidX failure since by this point
// the app is using AndroidX, the plugins are built as AARs, Jetifier translated
// Support libraries for AndroidX equivalents.
BuildEvent
(
'android-x-failure'
,
eventError:
'using-jetifier'
).
send
();
}
if
(
hasPlugins
&&
usesAndroidX
&&
!
shouldBuildPluginAsAar
)
{
printStatus
(
'The built failed likely due to AndroidX incompatibilities in a plugin. '
'The tool is about to try using Jetfier to solve the incompatibility.'
);
BuildEvent
(
'android-x-failure'
,
eventError:
'not-using-jetifier'
).
send
();
// The app is using Androidx, but Jetifier hasn't run yet.
// Call the current method again, build the plugins as AAR, so Jetifier can translate
// the dependencies.
// NOTE: Don't build the plugins as AARs by default since this drastically increases
// the build time.
await
_buildGradleProjectV2
(
flutterProject
,
androidBuildInfo
,
target
,
isBuildingBundle
,
shouldBuildPluginAsAar:
true
,
);
return
;
}
}
}
throwToolExit
(
'Gradle task
$assembleTask
failed with exit code
$exitCode
'
,
exitCode:
exitCode
);
throwToolExit
(
'Gradle task
$assembleTask
failed with exit code
$exitCode
'
,
exitCode:
exitCode
);
}
}
flutterUsage
.
sendTiming
(
'build'
,
'gradle-v2'
,
Duration
(
milliseconds:
sw
.
elapsedMilliseconds
));
flutterUsage
.
sendTiming
(
'build'
,
'gradle-v2'
,
Duration
(
milliseconds:
sw
.
elapsedMilliseconds
));
if
(!
isBuildingBundle
)
{
if
(!
isBuildingBundle
)
{
final
Iterable
<
File
>
apkFiles
=
findApkFiles
(
p
roject
,
androidBuildInfo
);
final
Iterable
<
File
>
apkFiles
=
findApkFiles
(
gradleP
roject
,
androidBuildInfo
);
if
(
apkFiles
.
isEmpty
)
{
if
(
apkFiles
.
isEmpty
)
{
throwToolExit
(
'Gradle build failed to produce an Android package.'
);
throwToolExit
(
'Gradle build failed to produce an Android package.'
);
}
}
// Copy the first APK to app.apk, so `flutter run`, `flutter install`, etc. can find it.
// Copy the first APK to app.apk, so `flutter run`, `flutter install`, etc. can find it.
// TODO(blasten): Handle multiple APKs.
// TODO(blasten): Handle multiple APKs.
apkFiles
.
first
.
copySync
(
p
roject
.
apkDirectory
.
childFile
(
'app.apk'
).
path
);
apkFiles
.
first
.
copySync
(
gradleP
roject
.
apkDirectory
.
childFile
(
'app.apk'
).
path
);
printTrace
(
'calculateSha:
${
p
roject.apkDirectory}
/app.apk'
);
printTrace
(
'calculateSha:
${
gradleP
roject.apkDirectory}
/app.apk'
);
final
File
apkShaFile
=
p
roject
.
apkDirectory
.
childFile
(
'app.apk.sha1'
);
final
File
apkShaFile
=
gradleP
roject
.
apkDirectory
.
childFile
(
'app.apk.sha1'
);
apkShaFile
.
writeAsStringSync
(
_calculateSha
(
apkFiles
.
first
));
apkShaFile
.
writeAsStringSync
(
_calculateSha
(
apkFiles
.
first
));
for
(
File
apkFile
in
apkFiles
)
{
for
(
File
apkFile
in
apkFiles
)
{
...
@@ -875,7 +916,7 @@ Future<void> _buildGradleProjectV2(
...
@@ -875,7 +916,7 @@ Future<void> _buildGradleProjectV2(
color:
TerminalColor
.
green
);
color:
TerminalColor
.
green
);
}
}
}
else
{
}
else
{
final
File
bundleFile
=
findBundleFile
(
p
roject
,
buildInfo
);
final
File
bundleFile
=
findBundleFile
(
gradleP
roject
,
buildInfo
);
if
(
bundleFile
==
null
)
{
if
(
bundleFile
==
null
)
{
throwToolExit
(
'Gradle build failed to produce an Android bundle package.'
);
throwToolExit
(
'Gradle build failed to produce an Android bundle package.'
);
}
}
...
@@ -891,6 +932,61 @@ Future<void> _buildGradleProjectV2(
...
@@ -891,6 +932,61 @@ Future<void> _buildGradleProjectV2(
}
}
}
}
/// Returns [true] if the current app uses AndroidX.
// TODO(egarciad): https://github.com/flutter/flutter/issues/40800
// Remove `FlutterManifest.usesAndroidX` and provide a unified `AndroidProject.usesAndroidX`.
@visibleForTesting
bool
isAppUsingAndroidX
(
Directory
androidDirectory
)
{
final
File
properties
=
androidDirectory
.
childFile
(
'gradle.properties'
);
if
(!
properties
.
existsSync
())
{
return
false
;
}
return
properties
.
readAsStringSync
().
contains
(
'android.useAndroidX=true'
);
}
/// Builds the plugins as AARs.
@visibleForTesting
Future
<
void
>
buildPluginsAsAar
(
FlutterProject
flutterProject
,
AndroidBuildInfo
androidBuildInfo
,
{
String
buildDirectory
,
})
async
{
final
File
flutterPluginFile
=
flutterProject
.
flutterPluginsFile
;
if
(!
flutterPluginFile
.
existsSync
())
{
return
;
}
final
List
<
String
>
plugins
=
flutterPluginFile
.
readAsStringSync
().
split
(
'
\n
'
);
for
(
String
plugin
in
plugins
)
{
final
List
<
String
>
pluginParts
=
plugin
.
split
(
'='
);
if
(
pluginParts
.
length
!=
2
)
{
continue
;
}
final
Directory
pluginDirectory
=
fs
.
directory
(
pluginParts
.
last
);
assert
(
pluginDirectory
.
existsSync
());
final
String
pluginName
=
pluginParts
.
first
;
logger
.
printStatus
(
'Building plugin
$pluginName
...'
);
try
{
await
buildGradleAar
(
project:
FlutterProject
.
fromDirectory
(
pluginDirectory
),
androidBuildInfo:
const
AndroidBuildInfo
(
BuildInfo
(
BuildMode
.
release
,
// Plugins are built as release.
null
,
// Plugins don't define flavors.
),
),
target:
''
,
outputDir:
buildDirectory
,
);
}
on
ToolExit
{
// Log the entire plugin entry in `.flutter-plugins` since it
// includes the plugin name and the version.
BuildEvent
(
'plugin-aar-failure'
,
eventError:
plugin
).
send
();
throwToolExit
(
'The plugin
$pluginName
could not be built due to the issue above. '
);
}
}
}
@visibleForTesting
@visibleForTesting
Iterable
<
File
>
findApkFiles
(
GradleProject
project
,
AndroidBuildInfo
androidBuildInfo
)
{
Iterable
<
File
>
findApkFiles
(
GradleProject
project
,
AndroidBuildInfo
androidBuildInfo
)
{
final
Iterable
<
String
>
apkFileNames
=
project
.
apkFilesFor
(
androidBuildInfo
);
final
Iterable
<
String
>
apkFileNames
=
project
.
apkFilesFor
(
androidBuildInfo
);
...
...
packages/flutter_tools/lib/src/features.dart
View file @
96482eeb
...
@@ -36,9 +36,6 @@ class FeatureFlags {
...
@@ -36,9 +36,6 @@ class FeatureFlags {
/// Whether flutter desktop for Windows is enabled.
/// Whether flutter desktop for Windows is enabled.
bool
get
isWindowsEnabled
=>
_isEnabled
(
flutterWindowsDesktopFeature
);
bool
get
isWindowsEnabled
=>
_isEnabled
(
flutterWindowsDesktopFeature
);
/// Whether plugins are built as AARs in app projects.
bool
get
isPluginAsAarEnabled
=>
_isEnabled
(
flutterBuildPluginAsAarFeature
);
// Calculate whether a particular feature is enabled for the current channel.
// Calculate whether a particular feature is enabled for the current channel.
static
bool
_isEnabled
(
Feature
feature
)
{
static
bool
_isEnabled
(
Feature
feature
)
{
final
String
currentChannel
=
FlutterVersion
.
instance
.
channel
;
final
String
currentChannel
=
FlutterVersion
.
instance
.
channel
;
...
...
packages/flutter_tools/lib/src/reporting/events.dart
View file @
96482eeb
...
@@ -125,6 +125,7 @@ class BuildEvent extends UsageEvent {
...
@@ -125,6 +125,7 @@ class BuildEvent extends UsageEvent {
BuildEvent
(
String
parameter
,
{
BuildEvent
(
String
parameter
,
{
this
.
command
,
this
.
command
,
this
.
settings
,
this
.
settings
,
this
.
eventError
,
})
:
super
(
})
:
super
(
'build'
+
'build'
+
(
FlutterCommand
.
current
==
null
?
''
:
'-
${FlutterCommand.current.name}
'
),
(
FlutterCommand
.
current
==
null
?
''
:
'-
${FlutterCommand.current.name}
'
),
...
@@ -132,6 +133,7 @@ class BuildEvent extends UsageEvent {
...
@@ -132,6 +133,7 @@ class BuildEvent extends UsageEvent {
final
String
command
;
final
String
command
;
final
String
settings
;
final
String
settings
;
final
String
eventError
;
@override
@override
void
send
()
{
void
send
()
{
...
@@ -140,6 +142,8 @@ class BuildEvent extends UsageEvent {
...
@@ -140,6 +142,8 @@ class BuildEvent extends UsageEvent {
CustomDimensions
.
buildEventCommand
:
command
,
CustomDimensions
.
buildEventCommand
:
command
,
if
(
settings
!=
null
)
if
(
settings
!=
null
)
CustomDimensions
.
buildEventSettings
:
settings
,
CustomDimensions
.
buildEventSettings
:
settings
,
if
(
eventError
!=
null
)
CustomDimensions
.
buildEventError
:
eventError
,
});
});
flutterUsage
.
sendEvent
(
category
,
parameter
,
parameters:
parameters
);
flutterUsage
.
sendEvent
(
category
,
parameter
,
parameters:
parameters
);
}
}
...
...
packages/flutter_tools/lib/src/reporting/usage.dart
View file @
96482eeb
...
@@ -53,6 +53,7 @@ enum CustomDimensions {
...
@@ -53,6 +53,7 @@ enum CustomDimensions {
commandBuildApkSplitPerAbi
,
// cd40
commandBuildApkSplitPerAbi
,
// cd40
commandBuildAppBundleTargetPlatform
,
// cd41
commandBuildAppBundleTargetPlatform
,
// cd41
commandBuildAppBundleBuildMode
,
// cd42
commandBuildAppBundleBuildMode
,
// cd42
buildEventError
,
// cd43
}
}
String
cdKey
(
CustomDimensions
cd
)
=>
'cd
${cd.index + 1}
'
;
String
cdKey
(
CustomDimensions
cd
)
=>
'cd
${cd.index + 1}
'
;
...
...
packages/flutter_tools/test/general.shard/android/gradle_test.dart
View file @
96482eeb
...
@@ -25,7 +25,6 @@ import 'package:process/process.dart';
...
@@ -25,7 +25,6 @@ import 'package:process/process.dart';
import
'../../src/common.dart'
;
import
'../../src/common.dart'
;
import
'../../src/context.dart'
;
import
'../../src/context.dart'
;
import
'../../src/mocks.dart'
;
import
'../../src/pubspec_schema.dart'
;
import
'../../src/pubspec_schema.dart'
;
void
main
(
)
{
void
main
(
)
{
...
@@ -1155,6 +1154,153 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
...
@@ -1155,6 +1154,153 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
});
});
});
});
group
(
'isAppUsingAndroidX'
,
()
{
FileSystem
fs
;
setUp
(()
{
fs
=
MemoryFileSystem
();
});
testUsingContext
(
'returns true when the project is using AndroidX'
,
()
async
{
final
Directory
androidDirectory
=
fs
.
systemTempDirectory
.
createTempSync
(
'android.'
);
androidDirectory
.
childFile
(
'gradle.properties'
)
.
writeAsStringSync
(
'android.useAndroidX=true'
);
expect
(
isAppUsingAndroidX
(
androidDirectory
),
isTrue
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
});
testUsingContext
(
'returns false when the project is not using AndroidX'
,
()
async
{
final
Directory
androidDirectory
=
fs
.
systemTempDirectory
.
createTempSync
(
'android.'
);
androidDirectory
.
childFile
(
'gradle.properties'
)
.
writeAsStringSync
(
'android.useAndroidX=false'
);
expect
(
isAppUsingAndroidX
(
androidDirectory
),
isFalse
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
});
testUsingContext
(
'returns false when gradle.properties does not exist'
,
()
async
{
final
Directory
androidDirectory
=
fs
.
systemTempDirectory
.
createTempSync
(
'android.'
);
expect
(
isAppUsingAndroidX
(
androidDirectory
),
isFalse
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fs
,
});
});
group
(
'buildPluginsAsAar'
,
()
{
FileSystem
fs
;
MockProcessManager
mockProcessManager
;
MockAndroidSdk
mockAndroidSdk
;
setUp
(()
{
fs
=
MemoryFileSystem
();
mockProcessManager
=
MockProcessManager
();
when
(
mockProcessManager
.
run
(
any
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
),
)).
thenAnswer
((
_
)
async
=>
ProcessResult
(
1
,
0
,
''
,
''
));
mockAndroidSdk
=
MockAndroidSdk
();
when
(
mockAndroidSdk
.
directory
).
thenReturn
(
'irrelevant'
);
});
testUsingContext
(
'calls gradle'
,
()
async
{
final
Directory
androidDirectory
=
fs
.
directory
(
'android.'
);
androidDirectory
.
createSync
();
androidDirectory
.
childFile
(
'pubspec.yaml'
)
.
writeAsStringSync
(
'name: irrelevant'
);
final
Directory
plugin1
=
fs
.
directory
(
'plugin1.'
);
plugin1
..
createSync
()
..
childFile
(
'pubspec.yaml'
)
.
writeAsStringSync
(
'''
name: irrelevant
flutter:
plugin:
androidPackage: irrelevant
'''
);
final
Directory
plugin2
=
fs
.
directory
(
'plugin2.'
);
plugin2
..
createSync
()
..
childFile
(
'pubspec.yaml'
)
.
writeAsStringSync
(
'''
name: irrelevant
flutter:
plugin:
androidPackage: irrelevant
'''
);
androidDirectory
.
childFile
(
'.flutter-plugins'
)
.
writeAsStringSync
(
'''
plugin1=
${plugin1.path}
plugin2=
${plugin2.path}
'''
);
final
Directory
buildDirectory
=
androidDirectory
.
childDirectory
(
'build'
);
buildDirectory
.
childDirectory
(
'outputs'
)
.
childDirectory
(
'repo'
)
.
createSync
(
recursive:
true
);
await
buildPluginsAsAar
(
FlutterProject
.
fromPath
(
androidDirectory
.
path
),
const
AndroidBuildInfo
(
BuildInfo
.
release
),
buildDirectory:
buildDirectory
.
path
,
);
final
String
flutterRoot
=
fs
.
path
.
absolute
(
Cache
.
flutterRoot
);
final
String
initScript
=
fs
.
path
.
join
(
flutterRoot
,
'packages'
,
'flutter_tools'
,
'gradle'
,
'aar_init_script.gradle'
);
verify
(
mockProcessManager
.
run
(
<
String
>[
'gradlew'
,
'-I=
$initScript
'
,
'-Pflutter-root=
$flutterRoot
'
,
'-Poutput-dir=
${buildDirectory.path}
'
,
'-Pis-plugin=true'
,
'-Ptarget-platform=android-arm,android-arm64'
,
'assembleAarRelease'
,
],
environment:
anyNamed
(
'environment'
),
workingDirectory:
plugin1
.
childDirectory
(
'android'
).
path
),
).
called
(
1
);
verify
(
mockProcessManager
.
run
(
<
String
>[
'gradlew'
,
'-I=
$initScript
'
,
'-Pflutter-root=
$flutterRoot
'
,
'-Poutput-dir=
${buildDirectory.path}
'
,
'-Pis-plugin=true'
,
'-Ptarget-platform=android-arm,android-arm64'
,
'assembleAarRelease'
,
],
environment:
anyNamed
(
'environment'
),
workingDirectory:
plugin2
.
childDirectory
(
'android'
).
path
),
).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
FileSystem:
()
=>
fs
,
GradleUtils:
()
=>
FakeGradleUtils
(),
ProcessManager:
()
=>
mockProcessManager
,
});
});
group
(
'gradle build'
,
()
{
group
(
'gradle build'
,
()
{
MockAndroidSdk
mockAndroidSdk
;
MockAndroidSdk
mockAndroidSdk
;
MockAndroidStudio
mockAndroidStudio
;
MockAndroidStudio
mockAndroidStudio
;
...
@@ -1235,11 +1381,13 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
...
@@ -1235,11 +1381,13 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
fs
.
currentDirectory
=
'path/to/project'
;
fs
.
currentDirectory
=
'path/to/project'
;
// Let any process start. Assert after.
// Let any process start. Assert after.
when
(
mockProcessManager
.
start
(
when
(
mockProcessManager
.
run
(
any
,
any
,
environment:
anyNamed
(
'environment'
),
environment:
anyNamed
(
'environment'
),
workingDirectory:
anyNamed
(
'workingDirectory'
))
workingDirectory:
anyNamed
(
'workingDirectory'
))
).
thenAnswer
((
Invocation
invocation
)
=>
Future
<
Process
>.
value
(
MockProcess
()));
).
thenAnswer
(
(
_
)
async
=>
ProcessResult
(
1
,
0
,
''
,
''
),
);
fs
.
directory
(
'build/outputs/repo'
).
createSync
(
recursive:
true
);
fs
.
directory
(
'build/outputs/repo'
).
createSync
(
recursive:
true
);
await
buildGradleAar
(
await
buildGradleAar
(
...
@@ -1249,11 +1397,11 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
...
@@ -1249,11 +1397,11 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
target:
''
target:
''
);
);
final
List
<
String
>
actualGradlewCall
=
verify
(
mockProcessManager
.
start
(
final
List
<
String
>
actualGradlewCall
=
verify
(
mockProcessManager
.
run
(
captureAny
,
captureAny
,
environment:
anyNamed
(
'environment'
),
environment:
anyNamed
(
'environment'
),
workingDirectory:
anyNamed
(
'workingDirectory'
)),
workingDirectory:
anyNamed
(
'workingDirectory'
)),
).
captured
.
single
;
).
captured
.
last
;
expect
(
actualGradlewCall
,
contains
(
'/path/to/project/.android/gradlew'
));
expect
(
actualGradlewCall
,
contains
(
'/path/to/project/.android/gradlew'
));
expect
(
actualGradlewCall
,
contains
(
'-PlocalEngineOut=out/android_arm'
));
expect
(
actualGradlewCall
,
contains
(
'-PlocalEngineOut=out/android_arm'
));
...
@@ -1284,6 +1432,14 @@ Platform fakePlatform(String name) {
...
@@ -1284,6 +1432,14 @@ Platform fakePlatform(String name) {
return
FakePlatform
.
fromPlatform
(
const
LocalPlatform
())..
operatingSystem
=
name
;
return
FakePlatform
.
fromPlatform
(
const
LocalPlatform
())..
operatingSystem
=
name
;
}
}
class
FakeGradleUtils
extends
GradleUtils
{
@override
Future
<
String
>
getExecutable
(
FlutterProject
project
)
async
{
return
'gradlew'
;
}
}
class
MockAndroidSdk
extends
Mock
implements
AndroidSdk
{}
class
MockAndroidStudio
extends
Mock
implements
AndroidStudio
{}
class
MockAndroidStudio
extends
Mock
implements
AndroidStudio
{}
class
MockDirectory
extends
Mock
implements
Directory
{}
class
MockDirectory
extends
Mock
implements
Directory
{}
class
MockFile
extends
Mock
implements
File
{}
class
MockFile
extends
Mock
implements
File
{}
...
...
packages/flutter_tools/test/general.shard/features_test.dart
View file @
96482eeb
...
@@ -432,21 +432,6 @@ void main() {
...
@@ -432,21 +432,6 @@ void main() {
expect
(
featureFlags
.
isWindowsEnabled
,
false
);
expect
(
featureFlags
.
isWindowsEnabled
,
false
);
}));
}));
/// Plugins as AARS
test
(
'plugins built as AARs with config on master'
,
()
=>
testbed
.
run
(()
{
when
(
mockFlutterVerion
.
channel
).
thenReturn
(
'master'
);
when
<
bool
>(
mockFlutterConfig
.
getValue
(
'enable-build-plugin-as-aar'
)).
thenReturn
(
false
);
expect
(
featureFlags
.
isPluginAsAarEnabled
,
false
);
}));
test
(
'plugins built as AARs with config on dev'
,
()
=>
testbed
.
run
(()
{
when
(
mockFlutterVerion
.
channel
).
thenReturn
(
'dev'
);
when
<
bool
>(
mockFlutterConfig
.
getValue
(
'enable-build-plugin-as-aar'
)).
thenReturn
(
false
);
expect
(
featureFlags
.
isPluginAsAarEnabled
,
false
);
}));
});
});
}
}
...
...
packages/flutter_tools/test/src/testbed.dart
View file @
96482eeb
...
@@ -693,7 +693,6 @@ class TestFeatureFlags implements FeatureFlags {
...
@@ -693,7 +693,6 @@ class TestFeatureFlags implements FeatureFlags {
this
.
isMacOSEnabled
=
false
,
this
.
isMacOSEnabled
=
false
,
this
.
isWebEnabled
=
false
,
this
.
isWebEnabled
=
false
,
this
.
isWindowsEnabled
=
false
,
this
.
isWindowsEnabled
=
false
,
this
.
isPluginAsAarEnabled
=
false
,
});
});
@override
@override
...
@@ -707,7 +706,4 @@ class TestFeatureFlags implements FeatureFlags {
...
@@ -707,7 +706,4 @@ class TestFeatureFlags implements FeatureFlags {
@override
@override
final
bool
isWindowsEnabled
;
final
bool
isWindowsEnabled
;
@override
final
bool
isPluginAsAarEnabled
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment