aar_init_script.gradle 7.01 KB
Newer Older
1 2 3 4 5
// This script is used to initialize the build in a module or plugin project.
// During this phase, the script applies the Maven plugin and configures the
// destination of the local repository.
// The local repository will contain the AAR and POM files.

6
import java.nio.file.Paths
7 8 9 10 11 12
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.maven.MavenDeployer
import org.gradle.api.plugins.MavenPlugin
import org.gradle.api.tasks.Upload

13
void configureProject(Project project, String outputDir) {
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
    if (!project.hasProperty("android")) {
        throw new GradleException("Android property not found.")
    }
    if (!project.android.hasProperty("libraryVariants")) {
        throw new GradleException("Can't generate AAR on a non Android library project.");
    }

    project.apply plugin: "maven"

    // Snapshot versions include the timestamp in the artifact name.
    // Therefore, remove the snapshot part, so new runs of `flutter build aar` overrides existing artifacts.
    // This version isn't relevant in Flutter since the pub version is used
    // to resolve dependencies.
    project.version = project.version.replace("-SNAPSHOT", "")

29 30 31 32 33 34 35
    if (project.hasProperty("buildNumber")) {
        project.version = project.property("buildNumber")
    }

    project.android.libraryVariants.all { variant ->
        addAarTask(project, variant)
    }
36

37 38 39 40 41 42 43
    project.uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "file://${outputDir}/outputs/repo")
            }
        }
    }
44 45 46
    if (!project.property("is-plugin").toBoolean()) {
        return
    }
47

48
    String storageUrl = System.getenv('FLUTTER_STORAGE_BASE_URL') ?: "https://storage.googleapis.com"
49 50 51 52
    // 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 {
53
            url "$storageUrl/download.flutter.io"
54 55 56 57 58 59 60 61 62 63
        }
    }
    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
64 65 66 67
        }
    }
}

68 69 70 71 72 73 74 75
void configurePlugin(Project project, String outputDir) {
    if (!project.hasProperty("android")) {
        // A plugin doesn't support the Android platform when this property isn't defined in the plugin.
        return
    }
    configureProject(project, outputDir)
}

76 77 78 79 80 81 82 83 84
String getFlutterRoot(Project project) {
    if (!project.hasProperty("flutter-root")) {
        throw new GradleException("The `-Pflutter-root` flag must be specified.")
    }
    return project.property("flutter-root")
}

void addAarTask(Project project, variant) {
    String variantName = variant.name.capitalize()
85
    String taskName = "assembleAar$variantName"
86 87 88 89 90 91 92 93 94 95
    project.tasks.create(name: taskName) {
        // This check is required to be able to configure the archives before `uploadArchives` runs.
        if (!project.gradle.startParameter.taskNames.contains(taskName)) {
            return
        }
        project.uploadArchives.repositories.mavenDeployer {
            pom {
                artifactId = "${project.name}_${variant.name.toLowerCase()}"
            }
        }
96
        overrideDefaultPublishConfig(project, variant)
97 98 99 100 101
        // Generate the Maven artifacts.
        finalizedBy "uploadArchives"
    }
}

102 103 104
// 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
//
105
// Unfortunately, `android.defaultPublishConfig` cannot be overridden at this point since
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
// 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
}

138
projectsEvaluated {
139
    assert rootProject.hasProperty("is-plugin")
140
    if (rootProject.property("is-plugin").toBoolean()) {
141
        assert rootProject.hasProperty("output-dir")
142
        // In plugin projects, the root project is the plugin.
143
        configureProject(rootProject, rootProject.property("output-dir"))
144 145
        return
    }
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    // The module project is the `:flutter` subproject.
    Project moduleProject = rootProject.subprojects.find { it.name == "flutter" }
    assert moduleProject != null
    assert moduleProject.hasProperty("output-dir")
    configureProject(moduleProject, moduleProject.property("output-dir"))

    // Gets the plugin subprojects.
    Set<Project> modulePlugins = rootProject.subprojects.findAll {
        it.name != "flutter" && it.name != "app"
    }
    // When a module is built as a Maven artifacts, plugins must also be built this way
    // because the module POM's file will include a dependency on the plugin Maven artifact.
    // This is due to the Android Gradle Plugin expecting all library subprojects to be published
    // as Maven artifacts.
    modulePlugins.each { pluginProject ->
161
        configurePlugin(pluginProject, moduleProject.property("output-dir"))
162 163 164 165 166 167 168 169
        moduleProject.android.libraryVariants.all { variant ->
            // Configure the `assembleAar<variantName>` task for each plugin's projects and make
            // the module's equivalent task depend on the plugin's task.
            String variantName = variant.name.capitalize()
            moduleProject.tasks.findByPath("assembleAar$variantName")
                .dependsOn(pluginProject.tasks.findByPath("assembleAar$variantName"))
        }
    }
170
}