mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Ensure that flutter assets are copied in the AAR (#42306)
This commit is contained in:
parent
a3c750a272
commit
1d2eaaf204
@ -956,6 +956,7 @@ Future<void> _androidGradleTests(String subShard) async {
|
|||||||
await _runDevicelabTest('gradle_plugin_bundle_test', env: env);
|
await _runDevicelabTest('gradle_plugin_bundle_test', env: env);
|
||||||
await _runDevicelabTest('module_test', env: env);
|
await _runDevicelabTest('module_test', env: env);
|
||||||
await _runDevicelabTest('module_host_with_custom_build_test', env: env);
|
await _runDevicelabTest('module_host_with_custom_build_test', env: env);
|
||||||
|
await _runDevicelabTest('build_aar_module_test', env: env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ Future<void> main() async {
|
|||||||
'flutter_release-1.0.aar',
|
'flutter_release-1.0.aar',
|
||||||
));
|
));
|
||||||
|
|
||||||
checkFileExists(path.join(
|
final String releasePom = path.join(
|
||||||
repoPath,
|
repoPath,
|
||||||
'io',
|
'io',
|
||||||
'flutter',
|
'flutter',
|
||||||
@ -89,78 +89,40 @@ Future<void> main() async {
|
|||||||
'flutter_release',
|
'flutter_release',
|
||||||
'1.0',
|
'1.0',
|
||||||
'flutter_release-1.0.pom',
|
'flutter_release-1.0.pom',
|
||||||
));
|
);
|
||||||
|
|
||||||
checkFileExists(path.join(
|
checkFileExists(releasePom);
|
||||||
repoPath,
|
|
||||||
'io',
|
|
||||||
'flutter',
|
|
||||||
'plugins',
|
|
||||||
'deviceinfo',
|
|
||||||
'device_info_release',
|
|
||||||
'1.0',
|
|
||||||
'device_info_release-1.0.aar',
|
|
||||||
));
|
|
||||||
|
|
||||||
checkFileExists(path.join(
|
section('Check AOT blobs in release POM');
|
||||||
repoPath,
|
|
||||||
'io',
|
|
||||||
'flutter',
|
|
||||||
'plugins',
|
|
||||||
'deviceinfo',
|
|
||||||
'device_info_release',
|
|
||||||
'1.0',
|
|
||||||
'device_info_release-1.0.pom',
|
|
||||||
));
|
|
||||||
|
|
||||||
checkFileExists(path.join(
|
checkFileContains(<String>[
|
||||||
repoPath,
|
'flutter_embedding_release',
|
||||||
'io',
|
'armeabi_v7a_release',
|
||||||
'flutter',
|
'arm64_v8a_release',
|
||||||
'plugins',
|
], releasePom);
|
||||||
'packageinfo',
|
|
||||||
'package_info_release',
|
|
||||||
'1.0',
|
|
||||||
'package_info_release-1.0.aar',
|
|
||||||
));
|
|
||||||
|
|
||||||
checkFileExists(path.join(
|
|
||||||
repoPath,
|
|
||||||
'io',
|
|
||||||
'flutter',
|
|
||||||
'plugins',
|
|
||||||
'packageinfo',
|
|
||||||
'package_info_release',
|
|
||||||
'1.0',
|
|
||||||
'package_info_release-1.0.pom',
|
|
||||||
));
|
|
||||||
|
|
||||||
section('Check assets in release AAR');
|
section('Check assets in release AAR');
|
||||||
|
|
||||||
final Iterable<String> releaseAar = await getFilesInAar(path.join(
|
checkItContains<String>(
|
||||||
repoPath,
|
<String>[
|
||||||
'io',
|
...flutterAssets,
|
||||||
'flutter',
|
// AOT snapshots
|
||||||
'devicelab',
|
'jni/arm64-v8a/libapp.so',
|
||||||
'hello',
|
'jni/armeabi-v7a/libapp.so',
|
||||||
'flutter_release',
|
],
|
||||||
'1.0',
|
await getFilesInAar(
|
||||||
'flutter_release-1.0.aar',
|
path.join(
|
||||||
));
|
repoPath,
|
||||||
|
'io',
|
||||||
checkItContains<String>(<String>[
|
'flutter',
|
||||||
'assets/flutter_assets/FontManifest.json',
|
'devicelab',
|
||||||
'assets/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf',
|
'hello',
|
||||||
], releaseAar);
|
'flutter_release',
|
||||||
|
'1.0',
|
||||||
section('Check AOT blobs in release AAR');
|
'flutter_release-1.0.aar',
|
||||||
|
)
|
||||||
checkItContains<String>(<String>[
|
)
|
||||||
'jni/arm64-v8a/libapp.so',
|
);
|
||||||
'jni/arm64-v8a/libflutter.so',
|
|
||||||
'jni/armeabi-v7a/libapp.so',
|
|
||||||
'jni/armeabi-v7a/libflutter.so',
|
|
||||||
], releaseAar);
|
|
||||||
|
|
||||||
section('Build debug AAR');
|
section('Build debug AAR');
|
||||||
|
|
||||||
@ -182,7 +144,7 @@ Future<void> main() async {
|
|||||||
'flutter_debug-1.0.aar',
|
'flutter_debug-1.0.aar',
|
||||||
));
|
));
|
||||||
|
|
||||||
checkFileExists(path.join(
|
final String debugPom = path.join(
|
||||||
repoPath,
|
repoPath,
|
||||||
'io',
|
'io',
|
||||||
'flutter',
|
'flutter',
|
||||||
@ -191,52 +153,19 @@ Future<void> main() async {
|
|||||||
'flutter_debug',
|
'flutter_debug',
|
||||||
'1.0',
|
'1.0',
|
||||||
'flutter_debug-1.0.pom',
|
'flutter_debug-1.0.pom',
|
||||||
));
|
);
|
||||||
|
|
||||||
checkFileExists(path.join(
|
checkFileExists(debugPom);
|
||||||
repoPath,
|
|
||||||
'io',
|
|
||||||
'flutter',
|
|
||||||
'plugins',
|
|
||||||
'deviceinfo',
|
|
||||||
'device_info_debug',
|
|
||||||
'1.0',
|
|
||||||
'device_info_debug-1.0.aar',
|
|
||||||
));
|
|
||||||
|
|
||||||
checkFileExists(path.join(
|
section('Check AOT blobs in debug POM');
|
||||||
repoPath,
|
|
||||||
'io',
|
|
||||||
'flutter',
|
|
||||||
'plugins',
|
|
||||||
'deviceinfo',
|
|
||||||
'device_info_debug',
|
|
||||||
'1.0',
|
|
||||||
'device_info_debug-1.0.pom',
|
|
||||||
));
|
|
||||||
|
|
||||||
checkFileExists(path.join(
|
|
||||||
repoPath,
|
|
||||||
'io',
|
|
||||||
'flutter',
|
|
||||||
'plugins',
|
|
||||||
'packageinfo',
|
|
||||||
'package_info_debug',
|
|
||||||
'1.0',
|
|
||||||
'package_info_debug-1.0.aar',
|
|
||||||
));
|
|
||||||
|
|
||||||
checkFileExists(path.join(
|
|
||||||
repoPath,
|
|
||||||
'io',
|
|
||||||
'flutter',
|
|
||||||
'plugins',
|
|
||||||
'packageinfo',
|
|
||||||
'package_info_debug',
|
|
||||||
'1.0',
|
|
||||||
'package_info_debug-1.0.pom',
|
|
||||||
));
|
|
||||||
|
|
||||||
|
checkFileContains(<String>[
|
||||||
|
'flutter_embedding_debug',
|
||||||
|
'x86_debug',
|
||||||
|
'x86_64_debug',
|
||||||
|
'armeabi_v7a_debug',
|
||||||
|
'arm64_v8a_debug',
|
||||||
|
], debugPom);
|
||||||
|
|
||||||
section('Check assets in debug AAR');
|
section('Check assets in debug AAR');
|
||||||
|
|
||||||
@ -252,23 +181,13 @@ Future<void> main() async {
|
|||||||
));
|
));
|
||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
'assets/flutter_assets/FontManifest.json',
|
...flutterAssets,
|
||||||
'assets/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf',
|
|
||||||
// JIT snapshots.
|
// JIT snapshots.
|
||||||
'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',
|
||||||
], debugAar);
|
], debugAar);
|
||||||
|
|
||||||
section('Check AOT blobs in debug AAR');
|
|
||||||
|
|
||||||
checkItContains<String>(<String>[
|
|
||||||
'jni/arm64-v8a/libflutter.so',
|
|
||||||
'jni/armeabi-v7a/libflutter.so',
|
|
||||||
'jni/x86/libflutter.so',
|
|
||||||
'jni/x86_64/libflutter.so',
|
|
||||||
], debugAar);
|
|
||||||
|
|
||||||
return TaskResult.success(null);
|
return TaskResult.success(null);
|
||||||
} on TaskResult catch (taskResult) {
|
} on TaskResult catch (taskResult) {
|
||||||
return taskResult;
|
return taskResult;
|
||||||
|
@ -84,6 +84,20 @@ void checkItDoesNotContain<T>(Iterable<T> values, Iterable<T> collection) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks that [str] contains the specified [Pattern]s, otherwise throws
|
||||||
|
/// a [TaskResult].
|
||||||
|
void checkFileContains(List<Pattern> patterns, String filePath) {
|
||||||
|
final String fileContent = File(filePath).readAsStringSync();
|
||||||
|
for (Pattern pattern in patterns) {
|
||||||
|
if (!fileContent.contains(pattern)) {
|
||||||
|
throw TaskResult.failure(
|
||||||
|
'Expected to find `$pattern` in `$filePath` '
|
||||||
|
'instead it found:\n$fileContent'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TaskResult failure(String message, ProcessResult result) {
|
TaskResult failure(String message, ProcessResult result) {
|
||||||
print('Unexpected process result:');
|
print('Unexpected process result:');
|
||||||
print('Exit code: ${result.exitCode}');
|
print('Exit code: ${result.exitCode}');
|
||||||
|
@ -14,7 +14,7 @@ import org.gradle.api.artifacts.maven.MavenDeployer
|
|||||||
import org.gradle.api.plugins.MavenPlugin
|
import org.gradle.api.plugins.MavenPlugin
|
||||||
import org.gradle.api.tasks.Upload
|
import org.gradle.api.tasks.Upload
|
||||||
|
|
||||||
void configureProject(Project project, File outputDir) {
|
void configureProject(Project project, String outputDir) {
|
||||||
if (!project.hasProperty("android")) {
|
if (!project.hasProperty("android")) {
|
||||||
throw new GradleException("Android property not found.")
|
throw new GradleException("Android property not found.")
|
||||||
}
|
}
|
||||||
@ -85,55 +85,64 @@ void addAarTask(Project project, variant) {
|
|||||||
if (!project.gradle.startParameter.taskNames.contains(taskName)) {
|
if (!project.gradle.startParameter.taskNames.contains(taskName)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// NOTE(blasten): `android.defaultPublishConfig` must equal the variant name to build.
|
|
||||||
// Where variant name is `<product-flavor><Build-Type>`. However, it's too late to configure
|
|
||||||
// `defaultPublishConfig` at this point. Therefore, the code below ensures that the
|
|
||||||
// default build config uses the artifacts produced for the specific build variant.
|
|
||||||
Task bundle = project.tasks.findByName("bundle${variantName}Aar") // gradle:3.2.0
|
|
||||||
if (bundle == null) {
|
|
||||||
bundle = project.tasks.findByName("bundle${variantName}") // gradle:3.1.0
|
|
||||||
}
|
|
||||||
if (bundle == null) {
|
|
||||||
throw new GradleException("Can't generate AAR for variant ${variantName}.");
|
|
||||||
}
|
|
||||||
project.uploadArchives.repositories.mavenDeployer {
|
project.uploadArchives.repositories.mavenDeployer {
|
||||||
pom {
|
pom {
|
||||||
artifactId = "${project.name}_${variant.name.toLowerCase()}"
|
artifactId = "${project.name}_${variant.name.toLowerCase()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clear the current archives since the current one is assigned based on
|
overrideDefaultPublishConfig(project, variant)
|
||||||
// `android.defaultPublishConfig` which defaults to `release`.
|
|
||||||
project.configurations["archives"].artifacts.clear()
|
|
||||||
// Add the artifact that will be published.
|
|
||||||
project.artifacts.add("archives", bundle)
|
|
||||||
// Generate the Maven artifacts.
|
// Generate the Maven artifacts.
|
||||||
finalizedBy "uploadArchives"
|
finalizedBy "uploadArchives"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method mimics the logic in AGP when `android.defaultPublishConfig` is set in `build.gradle`:
|
||||||
|
// https://android.googlesource.com/platform/tools/base/+/studio-master-dev/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/VariantHelper.java
|
||||||
|
//
|
||||||
|
// Unfortunately, `android.defaultPublishConfig` cannot be overriden at this point since
|
||||||
|
// AGP already run this code.
|
||||||
|
void overrideDefaultPublishConfig(Project project, variant) {
|
||||||
|
String variantName = variant.name.capitalize()
|
||||||
|
Task bundle = project.tasks.findByName("bundle${variantName}Aar") // gradle:3.2.0
|
||||||
|
if (bundle == null) {
|
||||||
|
bundle = project.tasks.findByName("bundle${variantName}") // gradle:3.1.0
|
||||||
|
}
|
||||||
|
if (bundle == null) {
|
||||||
|
throw new GradleException("Can't generate AAR for variant ${variantName}.");
|
||||||
|
}
|
||||||
|
// Clear the current archive artifacts since the artifacts are based on `android.defaultPublishConfig`.
|
||||||
|
project.configurations["archives"].artifacts.clear()
|
||||||
|
// Add the artifact that will be published.
|
||||||
|
project.artifacts.add("archives", bundle)
|
||||||
|
|
||||||
|
def scopeMappings = project.uploadArchives.repositories.mavenDeployer.pom.scopeMappings
|
||||||
|
// Clear the scope mappings added by AGP since they are based on the current `android.defaultPublishConfig`.
|
||||||
|
scopeMappings.mappings.clear()
|
||||||
|
// Add the new mappings.
|
||||||
|
for (Configuration configuration : flattenConfiguration(variant.runtimeConfiguration)) {
|
||||||
|
scopeMappings.addMapping(/* priority = */ 300, configuration, "compile")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Configuration> flattenConfiguration(Configuration configuration) {
|
||||||
|
Set<Configuration> configs = [configuration]
|
||||||
|
for (Configuration extend : configuration.extendsFrom) {
|
||||||
|
configs.addAll(flattenConfiguration(extend))
|
||||||
|
}
|
||||||
|
return configs
|
||||||
|
}
|
||||||
|
|
||||||
projectsEvaluated {
|
projectsEvaluated {
|
||||||
|
assert rootProject.hasProperty("is-plugin")
|
||||||
if (rootProject.property("is-plugin").toBoolean()) {
|
if (rootProject.property("is-plugin").toBoolean()) {
|
||||||
if (rootProject.hasProperty("output-dir")) {
|
assert rootProject.hasProperty("output-dir")
|
||||||
rootProject.buildDir = rootProject.property("output-dir")
|
|
||||||
} else {
|
|
||||||
rootProject.buildDir = "../build";
|
|
||||||
}
|
|
||||||
// In plugin projects, the Android library is the root project.
|
// In plugin projects, the Android library is the root project.
|
||||||
configureProject(rootProject, rootProject.buildDir)
|
configureProject(rootProject, rootProject.property("output-dir"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// In module projects, the Android library project is the `:flutter` subproject.
|
// In module projects, the Android library project is the `:flutter` subproject.
|
||||||
Project androidLibrarySubproject = rootProject.subprojects.find { it.name == "flutter" }
|
Project androidLibraryProject = rootProject.subprojects.find { it.name == "flutter" }
|
||||||
// In module projects, the `buildDir` is defined in the `:app` subproject.
|
assert androidLibraryProject != null
|
||||||
Project appSubproject = rootProject.subprojects.find { it.name == "app" }
|
assert androidLibraryProject.hasProperty("output-dir")
|
||||||
|
configureProject(androidLibraryProject, androidLibraryProject.property("output-dir"))
|
||||||
assert appSubproject != null
|
|
||||||
assert androidLibrarySubproject != null
|
|
||||||
|
|
||||||
if (appSubproject.hasProperty("output-dir")) {
|
|
||||||
appSubproject.buildDir = appSubproject.property("output-dir")
|
|
||||||
} else {
|
|
||||||
appSubproject.buildDir = "../build/host"
|
|
||||||
}
|
|
||||||
configureProject(androidLibrarySubproject, appSubproject.buildDir)
|
|
||||||
}
|
}
|
||||||
|
@ -220,6 +220,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
String flutterBuildMode = buildModeFor(buildType)
|
String flutterBuildMode = buildModeFor(buildType)
|
||||||
|
println "flutter dependency"
|
||||||
// Add the embedding dependency.
|
// Add the embedding dependency.
|
||||||
addApiDependencies(project, buildType.name,
|
addApiDependencies(project, buildType.name,
|
||||||
"io.flutter:flutter_embedding_$flutterBuildMode:1.0.0-$engineVersion")
|
"io.flutter:flutter_embedding_$flutterBuildMode:1.0.0-$engineVersion")
|
||||||
@ -351,7 +352,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
"io.flutter:flutter_embedding_$flutterBuildMode:1.0.0-$engineVersion",
|
"io.flutter:flutter_embedding_$flutterBuildMode:1.0.0-$engineVersion",
|
||||||
{
|
{
|
||||||
// Include the embedding transitive dependencies since plugins may depend on them.
|
// Include the embedding transitive dependencies since plugins may depend on them.
|
||||||
transitive = true
|
transitive = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -619,12 +620,17 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
addApiDependencies(project, variant.name, project.files {
|
addApiDependencies(project, variant.name, project.files {
|
||||||
packFlutterAppAotTask
|
packFlutterAppAotTask
|
||||||
})
|
})
|
||||||
|
// We build an AAR when this property is defined.
|
||||||
|
boolean isBuildingAar = project.hasProperty('is-plugin')
|
||||||
|
// In add to app scenarios, a Gradle project contains a `:flutter` and `:app` project.
|
||||||
|
// We know that `:flutter` is used as a subproject when these tasks exists and we aren't building an AAR.
|
||||||
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")
|
||||||
// In add to app scenarios, :flutter is a subproject of another Android app.
|
boolean isUsedAsSubproject = packageAssets && cleanPackageAssets && !isBuildingAar
|
||||||
// We know that :flutter is used as a subproject when these tasks exist.
|
Task copyFlutterAssetsTask = project.tasks.create(
|
||||||
boolean isUsedAsSubproject = packageAssets && cleanPackageAssets
|
name: "copyFlutterAssets${variant.name.capitalize()}",
|
||||||
Task copyFlutterAssetsTask = project.tasks.create(name: "copyFlutterAssets${variant.name.capitalize()}", type: Copy) {
|
type: Copy,
|
||||||
|
) {
|
||||||
dependsOn compileTasks
|
dependsOn compileTasks
|
||||||
compileTasks.each { flutterTask ->
|
compileTasks.each { flutterTask ->
|
||||||
// Add flutter_assets.
|
// Add flutter_assets.
|
||||||
@ -645,9 +651,10 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
into mergeAssets.outputDir
|
into mergeAssets.outputDir
|
||||||
}
|
}
|
||||||
if (!isUsedAsSubproject) {
|
if (!isUsedAsSubproject) {
|
||||||
def mergeResources = variant.hasProperty("mergeResourcesProvider") ?
|
def variantOutput = variant.outputs.first()
|
||||||
variant.mergeResourcesProvider.get() : variant.mergeResources
|
def processResources = variantOutput.hasProperty("processResourcesProvider") ?
|
||||||
mergeResources.dependsOn(copyFlutterAssetsTask)
|
variantOutput.processResourcesProvider.get() : variantOutput.processResources
|
||||||
|
processResources.dependsOn(copyFlutterAssetsTask)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Flutter module included as a subproject in add to app.
|
// Flutter module included as a subproject in add to app.
|
||||||
|
Loading…
Reference in New Issue
Block a user