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('module_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',
|
||||
));
|
||||
|
||||
checkFileExists(path.join(
|
||||
final String releasePom = path.join(
|
||||
repoPath,
|
||||
'io',
|
||||
'flutter',
|
||||
@ -89,78 +89,40 @@ Future<void> main() async {
|
||||
'flutter_release',
|
||||
'1.0',
|
||||
'flutter_release-1.0.pom',
|
||||
));
|
||||
);
|
||||
|
||||
checkFileExists(path.join(
|
||||
repoPath,
|
||||
'io',
|
||||
'flutter',
|
||||
'plugins',
|
||||
'deviceinfo',
|
||||
'device_info_release',
|
||||
'1.0',
|
||||
'device_info_release-1.0.aar',
|
||||
));
|
||||
checkFileExists(releasePom);
|
||||
|
||||
checkFileExists(path.join(
|
||||
repoPath,
|
||||
'io',
|
||||
'flutter',
|
||||
'plugins',
|
||||
'deviceinfo',
|
||||
'device_info_release',
|
||||
'1.0',
|
||||
'device_info_release-1.0.pom',
|
||||
));
|
||||
section('Check AOT blobs in release POM');
|
||||
|
||||
checkFileExists(path.join(
|
||||
repoPath,
|
||||
'io',
|
||||
'flutter',
|
||||
'plugins',
|
||||
'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',
|
||||
));
|
||||
checkFileContains(<String>[
|
||||
'flutter_embedding_release',
|
||||
'armeabi_v7a_release',
|
||||
'arm64_v8a_release',
|
||||
], releasePom);
|
||||
|
||||
section('Check assets in release AAR');
|
||||
|
||||
final Iterable<String> releaseAar = await getFilesInAar(path.join(
|
||||
repoPath,
|
||||
'io',
|
||||
'flutter',
|
||||
'devicelab',
|
||||
'hello',
|
||||
'flutter_release',
|
||||
'1.0',
|
||||
'flutter_release-1.0.aar',
|
||||
));
|
||||
|
||||
checkItContains<String>(<String>[
|
||||
'assets/flutter_assets/FontManifest.json',
|
||||
'assets/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf',
|
||||
], releaseAar);
|
||||
|
||||
section('Check AOT blobs in release 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);
|
||||
checkItContains<String>(
|
||||
<String>[
|
||||
...flutterAssets,
|
||||
// AOT snapshots
|
||||
'jni/arm64-v8a/libapp.so',
|
||||
'jni/armeabi-v7a/libapp.so',
|
||||
],
|
||||
await getFilesInAar(
|
||||
path.join(
|
||||
repoPath,
|
||||
'io',
|
||||
'flutter',
|
||||
'devicelab',
|
||||
'hello',
|
||||
'flutter_release',
|
||||
'1.0',
|
||||
'flutter_release-1.0.aar',
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
section('Build debug AAR');
|
||||
|
||||
@ -182,7 +144,7 @@ Future<void> main() async {
|
||||
'flutter_debug-1.0.aar',
|
||||
));
|
||||
|
||||
checkFileExists(path.join(
|
||||
final String debugPom = path.join(
|
||||
repoPath,
|
||||
'io',
|
||||
'flutter',
|
||||
@ -191,52 +153,19 @@ Future<void> main() async {
|
||||
'flutter_debug',
|
||||
'1.0',
|
||||
'flutter_debug-1.0.pom',
|
||||
));
|
||||
);
|
||||
|
||||
checkFileExists(path.join(
|
||||
repoPath,
|
||||
'io',
|
||||
'flutter',
|
||||
'plugins',
|
||||
'deviceinfo',
|
||||
'device_info_debug',
|
||||
'1.0',
|
||||
'device_info_debug-1.0.aar',
|
||||
));
|
||||
checkFileExists(debugPom);
|
||||
|
||||
checkFileExists(path.join(
|
||||
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',
|
||||
));
|
||||
section('Check AOT blobs in debug POM');
|
||||
|
||||
checkFileContains(<String>[
|
||||
'flutter_embedding_debug',
|
||||
'x86_debug',
|
||||
'x86_64_debug',
|
||||
'armeabi_v7a_debug',
|
||||
'arm64_v8a_debug',
|
||||
], debugPom);
|
||||
|
||||
section('Check assets in debug AAR');
|
||||
|
||||
@ -252,23 +181,13 @@ Future<void> main() async {
|
||||
));
|
||||
|
||||
checkItContains<String>(<String>[
|
||||
'assets/flutter_assets/FontManifest.json',
|
||||
'assets/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf',
|
||||
...flutterAssets,
|
||||
// JIT snapshots.
|
||||
'assets/flutter_assets/isolate_snapshot_data',
|
||||
'assets/flutter_assets/kernel_blob.bin',
|
||||
'assets/flutter_assets/vm_snapshot_data',
|
||||
], 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);
|
||||
} on TaskResult catch (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) {
|
||||
print('Unexpected process result:');
|
||||
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.tasks.Upload
|
||||
|
||||
void configureProject(Project project, File outputDir) {
|
||||
void configureProject(Project project, String outputDir) {
|
||||
if (!project.hasProperty("android")) {
|
||||
throw new GradleException("Android property not found.")
|
||||
}
|
||||
@ -85,55 +85,64 @@ void addAarTask(Project project, variant) {
|
||||
if (!project.gradle.startParameter.taskNames.contains(taskName)) {
|
||||
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 {
|
||||
pom {
|
||||
artifactId = "${project.name}_${variant.name.toLowerCase()}"
|
||||
}
|
||||
}
|
||||
// Clear the current archives since the current one is assigned based on
|
||||
// `android.defaultPublishConfig` which defaults to `release`.
|
||||
project.configurations["archives"].artifacts.clear()
|
||||
// Add the artifact that will be published.
|
||||
project.artifacts.add("archives", bundle)
|
||||
overrideDefaultPublishConfig(project, variant)
|
||||
// Generate the Maven artifacts.
|
||||
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 {
|
||||
assert rootProject.hasProperty("is-plugin")
|
||||
if (rootProject.property("is-plugin").toBoolean()) {
|
||||
if (rootProject.hasProperty("output-dir")) {
|
||||
rootProject.buildDir = rootProject.property("output-dir")
|
||||
} else {
|
||||
rootProject.buildDir = "../build";
|
||||
}
|
||||
assert rootProject.hasProperty("output-dir")
|
||||
// In plugin projects, the Android library is the root project.
|
||||
configureProject(rootProject, rootProject.buildDir)
|
||||
configureProject(rootProject, rootProject.property("output-dir"))
|
||||
return
|
||||
}
|
||||
// In module projects, the Android library project is the `:flutter` subproject.
|
||||
Project androidLibrarySubproject = rootProject.subprojects.find { it.name == "flutter" }
|
||||
// In module projects, the `buildDir` is defined in the `:app` subproject.
|
||||
Project appSubproject = rootProject.subprojects.find { it.name == "app" }
|
||||
|
||||
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)
|
||||
Project androidLibraryProject = rootProject.subprojects.find { it.name == "flutter" }
|
||||
assert androidLibraryProject != null
|
||||
assert androidLibraryProject.hasProperty("output-dir")
|
||||
configureProject(androidLibraryProject, androidLibraryProject.property("output-dir"))
|
||||
}
|
||||
|
@ -220,6 +220,7 @@ class FlutterPlugin implements Plugin<Project> {
|
||||
}
|
||||
}
|
||||
String flutterBuildMode = buildModeFor(buildType)
|
||||
println "flutter dependency"
|
||||
// Add the embedding dependency.
|
||||
addApiDependencies(project, buildType.name,
|
||||
"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",
|
||||
{
|
||||
// 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 {
|
||||
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 cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets")
|
||||
// In add to app scenarios, :flutter is a subproject of another Android app.
|
||||
// We know that :flutter is used as a subproject when these tasks exist.
|
||||
boolean isUsedAsSubproject = packageAssets && cleanPackageAssets
|
||||
Task copyFlutterAssetsTask = project.tasks.create(name: "copyFlutterAssets${variant.name.capitalize()}", type: Copy) {
|
||||
boolean isUsedAsSubproject = packageAssets && cleanPackageAssets && !isBuildingAar
|
||||
Task copyFlutterAssetsTask = project.tasks.create(
|
||||
name: "copyFlutterAssets${variant.name.capitalize()}",
|
||||
type: Copy,
|
||||
) {
|
||||
dependsOn compileTasks
|
||||
compileTasks.each { flutterTask ->
|
||||
// Add flutter_assets.
|
||||
@ -645,9 +651,10 @@ class FlutterPlugin implements Plugin<Project> {
|
||||
into mergeAssets.outputDir
|
||||
}
|
||||
if (!isUsedAsSubproject) {
|
||||
def mergeResources = variant.hasProperty("mergeResourcesProvider") ?
|
||||
variant.mergeResourcesProvider.get() : variant.mergeResources
|
||||
mergeResources.dependsOn(copyFlutterAssetsTask)
|
||||
def variantOutput = variant.outputs.first()
|
||||
def processResources = variantOutput.hasProperty("processResourcesProvider") ?
|
||||
variantOutput.processResourcesProvider.get() : variantOutput.processResources
|
||||
processResources.dependsOn(copyFlutterAssetsTask)
|
||||
return
|
||||
}
|
||||
// Flutter module included as a subproject in add to app.
|
||||
|
Loading…
Reference in New Issue
Block a user