| /* |
| * 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. |
| */ |
| |
| package com.android.build.gradle.internal.plugins |
| |
| import com.android.build.gradle.BasePlugin |
| import com.android.build.gradle.internal.tasks.structureplugin.CombineModuleInfoTask |
| import com.android.build.gradle.internal.tasks.structureplugin.GatherModuleInfoTask |
| import org.gradle.api.NamedDomainObjectContainer |
| import org.gradle.api.Plugin |
| import org.gradle.api.Project |
| import org.gradle.api.artifacts.Configuration |
| import org.gradle.api.artifacts.ConfigurationVariant |
| import org.gradle.api.attributes.Usage |
| import org.gradle.api.plugins.JavaLibraryPlugin |
| import org.gradle.api.plugins.JavaPlugin |
| |
| const val USAGE_STRUCTURE = "android-debug-structure" |
| const val ARTIFACT_TYPE_MODULE_INFO = "android-debug-module-info" |
| |
| const val ELEMENT_CONFIG_NAME = "structureElements" |
| const val CLASSPATH_CONFIG_NAME = "structureClasspath" |
| |
| /** |
| * Plugin to gather the project structure of modules |
| */ |
| class StructurePlugin: Plugin<Project> { |
| |
| private var combineModuleTask: CombineModuleInfoTask? = null |
| private var gatherModuleTask: GatherModuleInfoTask? = null |
| |
| override fun apply(project: Project) { |
| if (project == project.rootProject) { |
| // create a configuration to consume the files |
| val structureConfig = project.configurations.create(CLASSPATH_CONFIG_NAME).apply { |
| isCanBeConsumed = false |
| attributes.attribute( |
| Usage.USAGE_ATTRIBUTE, |
| project.objects.named(Usage::class.java, USAGE_STRUCTURE)) |
| } |
| |
| // go through all the sub modules add add as a dependencies |
| val depHandler = project.dependencies |
| project.subprojects.forEach { |
| depHandler.add(CLASSPATH_CONFIG_NAME, it) |
| } |
| |
| // create the task |
| combineModuleTask = project.tasks.create( |
| "getStructure", |
| CombineModuleInfoTask::class.java, |
| CombineModuleInfoTask.ConfigAction(project, structureConfig)) |
| } |
| |
| // we have to do the following in afterEvaluate because we want to see all the plugins |
| // in one go. Using [PluginContainer.withType] doesn't really work because we have |
| // to do some conditional work depending on which plugins are applied, or not applied. |
| project.afterEvaluate { |
| if (it.plugins.count { |
| it is BasePlugin || it is JavaPlugin || it is JavaLibraryPlugin |
| } > 0) createTask(it) |
| |
| if (gatherModuleTask == null) { |
| // no plugin? still create the configuration. |
| createPublishingConfiguration(it) |
| } |
| } |
| } |
| |
| private fun createTask(project: Project) { |
| // create a configuration to publish the file |
| val structureConfig = createPublishingConfiguration(project) |
| gatherModuleTask = project.tasks.create( |
| "gatherModuleInfo", |
| GatherModuleInfoTask::class.java, |
| GatherModuleInfoTask.ConfigAction(project)) |
| |
| // publish the json file as an artifact |
| structureConfig.outgoing.variants( |
| { variants: NamedDomainObjectContainer<ConfigurationVariant> -> |
| variants.create(ARTIFACT_TYPE_MODULE_INFO) { variant -> |
| variant.artifact(gatherModuleTask!!.outputProvider) { artifact -> |
| artifact.type = ARTIFACT_TYPE_MODULE_INFO |
| artifact.builtBy(gatherModuleTask) |
| } |
| } |
| }) |
| |
| // if this the root project, register this output as an input to the combine task |
| combineModuleTask?.let { |
| it.localModuleInfo = gatherModuleTask!!.outputProvider |
| it.dependsOn(gatherModuleTask) |
| } |
| } |
| |
| private fun createPublishingConfiguration(project: Project): Configuration { |
| return project.configurations.create(ELEMENT_CONFIG_NAME).apply { |
| isCanBeResolved = false |
| attributes.attribute( |
| Usage.USAGE_ATTRIBUTE, |
| project.objects.named(Usage::class.java, USAGE_STRUCTURE)) |
| } |
| } |
| } |
| |