普通文本  |  361行  |  14.69 KB

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import androidx.build.DiffAndDocs
import androidx.build.PublishDocsRulesKt
import androidx.build.gmaven.GMavenVersionChecker
import androidx.build.license.CheckExternalDependencyLicensesTask
import com.android.build.gradle.internal.coverage.JacocoReportTask
import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask
import org.gradle.api.logging.configuration.ShowStacktrace

import javax.tools.ToolProvider

def supportRoot = ext.supportRootFolder
if (supportRoot == null) {
    throw new RuntimeException("variable supportRootFolder is not set. you must set it before" +
            " including this script")
}
def init = new Properties()
ext.init = init
rootProject.ext.versionChecker = new GMavenVersionChecker(rootProject.logger)
ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null

apply from: "${supportRoot}/buildSrc/dependencies.gradle"
apply from: "${supportRoot}/buildSrc/build_dependencies.gradle"
apply from: "${supportRoot}/buildSrc/unbundled_check.gradle"


def enableDoclavaAndJDiff(p, dacOptions, rules = []) {
    p.configurations {
        doclava
        jdiff
    }

    p.dependencies {
        doclava build_libs.doclava
        // tools.jar required for com.sun.javadoc
        doclava files(((URLClassLoader) ToolProvider.getSystemToolClassLoader()).getURLs())
        jdiff build_libs.jdiff
        jdiff build_libs.xml_parser_apis
        jdiff build_libs.xerces_impl
    }

    return DiffAndDocs.configureDiffAndDocs(rootProject, supportRootFolder,
            dacOptions, rules)
}

def getFullSdkPath() {
    if (isUnbundledBuild(ext.supportRootFolder)) {
        Properties properties = new Properties()
        File propertiesFile = new File('local.properties')
        if (propertiesFile.exists()) {
            propertiesFile.withInputStream {
                properties.load(it)
            }
        }
        File location = findSdkLocation(properties, supportRootFolder)
        return location.getAbsolutePath()
    } else {
        final String osName = System.getProperty("os.name").toLowerCase();
        final boolean isMacOsX =
                osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx");
        final String platform = isMacOsX ? 'darwin' : 'linux'
        return "${repos.prebuiltsRoot}/fullsdk-${platform}"
    }
}

/**
 * Adapted from com.android.build.gradle.internal.SdkHandler
 */
public static File findSdkLocation(Properties properties, File rootDir) {
    String sdkDirProp = properties.getProperty("sdk.dir");
    if (sdkDirProp != null) {
        File sdk = new File(sdkDirProp);
        if (!sdk.isAbsolute()) {
            sdk = new File(rootDir, sdkDirProp);
        }
        return sdk
    }

    sdkDirProp = properties.getProperty("android.dir");
    if (sdkDirProp != null) {
        return new File(rootDir, sdkDirProp);
    }

    String envVar = System.getenv("ANDROID_HOME");
    if (envVar != null) {
        return new File(envVar);
    }

    String property = System.getProperty("android.home");
    if (property != null) {
        return new File(property);
    }
    return null;
}

def setSdkInLocalPropertiesFile() {
    final File fullSdkPath = file(getFullSdkPath())
    if (fullSdkPath.exists()) {
        project.ext.fullSdkPath = fullSdkPath
        File props = file("local.properties")
        props.write "sdk.dir=${fullSdkPath.getAbsolutePath()}"
        ext.usingFullSdk = true
    } else {
        throw Exception("You are using non ub-supportlib-* checkout. You need to check out "
                + "ub-supportlib-* to work on support library. See go/supportlib for details.")
    }
}

def setupRepoOutAndBuildNumber() {
    // common support repo folder which works well for prebuilts.
    ext.supportRepoOut = ''
    ext.buildNumber = "0"
    /*
     * With the build server you are given two env variables.
     * The OUT_DIR is a temporary directory you can use to put things during the build.
     * The DIST_DIR is where you want to save things from the build.
     *
     * The build server will copy the contents of DIST_DIR to somewhere and make it available.
     */
    if (ext.runningInBuildServer) {
        buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build')
                .getCanonicalFile()
        project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile()

        // the build server does not pass the build number so we infer it from the last folder of
        // the dist path.
        ext.buildNumber = project.ext.distDir.getName()

        // the build server should always print out full stack traces for any failures.
        gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS
    } else {
        buildDir = file("${ext.supportRootFolder}/../../out/host/gradle/frameworks/support/build")
        project.ext.distDir = new File("${ext.supportRootFolder}/../../out/dist")
    }
    subprojects {
        // Change buildDir first so that all plugins pick up the new value.
        project.buildDir = new File("$project.parent.buildDir/../$project.name/build")
    }
    ext.supportRepoOut = new File(buildDir, 'support_repo')
    ext.testApkDistOut = ext.distDir
    ext.testResultsDistDir = new File(distDir, "host-test-reports")
    ext.docsDir = new File(buildDir, 'javadoc')
}

def configureBuildOnServer() {
    def buildOnServerTask = rootProject.tasks.create("buildOnServer")
    rootProject.tasks.whenTaskAdded { task ->
        if ("createArchive".equals(task.name)
                || "createDiffArchive".equals(task.name)
                || "distDocs".equals(task.name)
                || "dejetifyArchive".equals(task.name)
                || CheckExternalDependencyLicensesTask.ROOT_TASK_NAME.equals(task.name)) {
            buildOnServerTask.dependsOn task
        }
    }
    def docsProject = rootProject.findProject(":docs-fake")
    subprojects {
        if (docsProject == project) {
            return
        }
        project.tasks.whenTaskAdded { task ->
            if ("assembleErrorProne".equals(task.name)
                    || "assembleAndroidTest".equals(task.name)
                    || "assembleDebug".equals(task.name)) {
                buildOnServerTask.dependsOn task
            }
        }
    }
    buildOnServerTask.dependsOn createJacocoAntUberJarTask()
    return buildOnServerTask
}

def createJacocoAntUberJarTask() {
    def myJacoco = project.configurations.create('myJacoco')
    project.dependencies.add('myJacoco', build_libs.jacoco_ant)

    return project.tasks.create(
            name: "JacocoAntUberJar",
            type: Jar) {
        inputs.files myJacoco
        from {
            myJacoco
                    .resolvedConfiguration
                    .resolvedArtifacts.collect{ zipTree(it.getFile()) }} {
            // exclude all the signatures the jar might have
            exclude "META-INF/*.SF"
            exclude "META-INF/*.DSA"
            exclude "META-INF/*.RSA"
        }
        destinationDir file(project.distDir)
        archiveName "jacocoant.jar"
    }
}

def configureSubProjects() {
    subprojects {
        repos.addMavenRepositories(repositories)

        // Only modify Android projects.
        if (project.name.equals('noto-emoji-compat')) {
            // disable tests and return
            project.tasks.whenTaskAdded { task ->
                if (task instanceof org.gradle.api.tasks.testing.Test) {
                    task.enabled = false
                }
            }
            return
        }

        project.plugins.whenPluginAdded { plugin ->
            def isAndroidLibrary = "com.android.build.gradle.LibraryPlugin"
                    .equals(plugin.class.name)
            def isAndroidApp = "com.android.build.gradle.AppPlugin".equals(plugin.class.name)

            if (isAndroidLibrary || isAndroidApp) {
                // Enable code coverage for debug builds only if we are not running inside the IDE,
                // since enabling coverage reports breaks the method parameter resolution in the IDE
                // debugger.
                project.android.buildTypes.debug.testCoverageEnabled =
                        !project.hasProperty('android.injected.invoked.from.ide')

                // Copy the class files in a jar to be later used to generate code coverage report
                project.android.testVariants.all { v ->
                    // check if the variant has any source files
                    // and test coverage is enabled
                    if (v.buildType.testCoverageEnabled
                            && v.sourceSets.any { !it.java.sourceFiles.isEmpty() }) {
                        def jarifyTask = project.tasks.create(
                                name: "package${v.name.capitalize()}ClassFilesForCoverageReport",
                                type: Jar) {
                            from v.testedVariant.javaCompile.destinationDir
                            exclude "**/R.class"
                            exclude "**/R\$*.class"
                            exclude "**/BuildConfig.class"
                            destinationDir file(project.distDir)
                            archiveName "${project.name}-${v.baseName}-allclasses.jar"
                        }

                        jarifyTask.dependsOn v.getJavaCompiler()
                        v.assemble.dependsOn jarifyTask
                    }
                }
            }
        }

        // Copy instrumentation test APKs and app APKs into the dist dir
        // For test apks, they are uploaded only if we have java test sources.
        // For regular app apks, they are uploaded only if they have java sources.
        project.tasks.whenTaskAdded { task ->
            if (task.name.startsWith("packageDebug")) {
                def testApk = task.name.contains("AndroidTest")
                task.doLast {
                    def source = testApk ? project.android.sourceSets.androidTest
                            : project.android.sourceSets.main
                    def hasKotlinSources = false
                    if (source.hasProperty('kotlin')) {
                        if (!source.kotlin.files.isEmpty()) {
                            hasKotlinSources = true
                        } else {
                            // kotlin files does not show in java sources due to the *.java filter
                            // so we need to check them manually
                            hasKotlinSources = source.java.sourceDirectoryTrees.any {
                                !fileTree(dir: it.dir, include:'**/*.kt').files.isEmpty()
                            }
                        }
                    }
                    def hasSourceCode = !source.java.sourceFiles.isEmpty() || hasKotlinSources
                    if (task.hasProperty("outputDirectory") && (hasSourceCode || !testApk)) {
                        copy {
                            from(task.outputDirectory)
                            include '*.apk'
                            into(rootProject.ext.testApkDistOut)
                            rename { String fileName ->
                                // Exclude media-compat-test-* modules from existing support library
                                // presubmit tests.
                                if (fileName.contains("media-compat-test")) {
                                    fileName.replace("-debug-androidTest", "")
                                } else {
                                    // multiple modules may have the same name so prefix the name with
                                    // the module's path to ensure it is unique.
                                    // e.g. palette-v7-debug-androidTest.apk becomes
                                    // support-palette-v7_palette-v7-debug-androidTest.apk
                                    "${project.getPath().replace(':', '-').substring(1)}_${fileName}"
                                }
                            }
                        }
                    }
                }
            }
        }

        // copy host side test results to DIST
        project.tasks.whenTaskAdded { task ->
            if (task instanceof org.gradle.api.tasks.testing.Test) {
                def junitReport = task.reports.junitXml
                if (junitReport.enabled) {
                    def zipTask = project.tasks.create(name : "zipResultsOf${task.name.capitalize()}", type : Zip) {
                        destinationDir(testResultsDistDir)
                        // first one is always :, drop it.
                        archiveName("${project.getPath().split(":").join("_").substring(1)}.zip")
                    }
                    if (project.rootProject.ext.runningInBuildServer) {
                        task.ignoreFailures = true
                    }
                    task.finalizedBy zipTask
                    task.doFirst {
                        zipTask.from(junitReport.destination)
                    }
                }
            }
        }

        project.afterEvaluate { p ->
            // remove dependency on the test so that we still get coverage even if some tests fail
            p.tasks.findAll { it instanceof JacocoReportTask }.each { task ->
                def toBeRemoved = new ArrayList()
                def dependencyList = task.taskDependencies.values
                dependencyList.each { dep ->
                    if (dep instanceof String) {
                        def t = tasks.findByName(dep)
                        if (t instanceof DeviceProviderInstrumentTestTask) {
                            toBeRemoved.add(dep)
                            task.mustRunAfter(t)
                        }
                    }
                }
                toBeRemoved.each { dep ->
                    dependencyList.remove(dep)
                }
            }
        }
    }
}

def setupRelease() {
    apply from: "${ext.supportRootFolder}/buildSrc/release.gradle"
}

ext.init.enableDoclavaAndJDiff = this.&enableDoclavaAndJDiff
ext.init.setSdkInLocalPropertiesFile = this.&setSdkInLocalPropertiesFile
ext.init.setupRepoOutAndBuildNumber = this.&setupRepoOutAndBuildNumber
ext.init.setupRelease = this.&setupRelease
ext.init.configureSubProjects = this.&configureSubProjects
ext.init.configureBuildOnServer = this.&configureBuildOnServer