Pill: Fix artifact generation

This commit is contained in:
Yan Zhulanow
2019-04-11 02:43:17 +03:00
parent 5b49043939
commit 9e99bca322
3 changed files with 121 additions and 120 deletions
@@ -5,11 +5,13 @@ package org.jetbrains.kotlin.pill
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.internal.file.copy.SingleParentCopySpec
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.Copy
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.extra
import org.jetbrains.kotlin.pill.DependencyInfo.ResolvedDependencyInfo
import org.jetbrains.kotlin.pill.ArtifactElement.*
import org.jetbrains.kotlin.pill.POrderRoot.*
import java.io.File
@@ -34,6 +36,10 @@ sealed class ArtifactElement {
myChildren += child
}
fun add(children: List<ArtifactElement>) {
myChildren += children
}
abstract fun render(context: PathContext): xml
fun renderRecursively(context: PathContext): xml {
@@ -102,99 +108,37 @@ sealed class ArtifactElement {
}
}
fun generateKotlinPluginArtifactFile(rootProject: Project): PFile {
val mainIdeaPluginTask = rootProject.tasks.getByName("ideaPlugin")
val gradleArtifactDir = File(rootProject.extra["ideaPluginDir"] as File, "lib")
val ideaPluginTasks = mainIdeaPluginTask.taskDependencies
.getDependencies(mainIdeaPluginTask)
.filter { it.name == "ideaPlugin" }
.filterIsInstance<Copy>()
fun generateKotlinPluginArtifactFile(rootProject: Project, dependencyMappers: List<DependencyMapper>): PFile {
val root = Root()
// Copy kotlinc directory
fun Project.getProject(name: String) = findProject(name) ?: error("Cannot find project $name")
val prepareIdeaPluginProject = rootProject.getProject(":prepare:idea-plugin")
val prepareJpsPluginProject = rootProject.getProject(":kotlin-jps-plugin")
root.add(Directory("kotlinc").apply {
val kotlincDirectory = rootProject.extra["distKotlinHomeDir"].toString()
add(DirectoryCopy(File(kotlincDirectory)))
})
for (task in ideaPluginTasks) {
val spec = task.rootSpec.children.filterIsInstance<SingleParentCopySpec>().singleOrNull()
?: error("Copy spec is not unique in ${rootProject.name}. Available specs: ${task.rootSpec.children}")
root.add(Directory("lib").apply {
val librariesConfiguration = prepareIdeaPluginProject.configurations.getByName("libraries")
add(getArtifactElements(librariesConfiguration, dependencyMappers, false))
val sourcePaths = spec.sourcePaths
for (sourcePath in sourcePaths) {
if (sourcePath is ShadowJar) {
if (sourcePath.project.path == ":prepare:idea-plugin") {
val kotlinPluginJar = Archive(sourcePath.archiveName).also { root.getDirectory("lib").add(it) }
add(Directory("jps").apply {
add(Archive(prepareJpsPluginProject.name).apply {
val embeddedConfiguration = prepareJpsPluginProject.configurations.getByName(EmbeddedComponents.CONFIGURATION_NAME)
add(getArtifactElements(embeddedConfiguration, dependencyMappers, true))
})
})
kotlinPluginJar.add(FileCopy(File(rootProject.projectDir, "resources/kotlinManifest.properties")))
add(Archive(prepareIdeaPluginProject.name + ".jar").apply {
add(FileCopy(File(rootProject.projectDir, "resources/kotlinManifest.properties")))
for (jarFile in sourcePath.project.configurations.getByName(EmbeddedComponents.CONFIGURATION_NAME).resolve()) {
kotlinPluginJar.add(ExtractedDirectory(jarFile))
}
@Suppress("UNCHECKED_CAST")
for (projectPath in sourcePath.project.extra["projectsToShadow"] as List<String>) {
val jpsModuleName = rootProject.findProject(projectPath)!!.name + ".src"
kotlinPluginJar.add(ModuleOutput(jpsModuleName))
}
continue
}
}
fun fileCopySnapshotAware(file: File): FileCopy {
val SHAPSHOT_JAR_SUFFIX = "-SNAPSHOT.jar"
if (file.name.endsWith(SHAPSHOT_JAR_SUFFIX)) {
return FileCopy(file, file.name.dropLast(SHAPSHOT_JAR_SUFFIX.length).substringBeforeLast("-") + ".jar")
}
return FileCopy(file)
}
when (sourcePath) {
is Jar -> {
val targetDir = ("lib/" + task.destinationDir.toRelativeString(gradleArtifactDir)).withoutSlash()
val archiveForJar = Archive(sourcePath.project.name + ".jar").apply {
if (task.project.plugins.hasPlugin(JavaPlugin::class.java)) {
add(ModuleOutput(sourcePath.project.name + ".src"))
}
root.getDirectory(targetDir).add(this)
}
val embeddedComponents = sourcePath.project.configurations
.findByName(EmbeddedComponents.CONFIGURATION_NAME)?.resolvedConfiguration
if (embeddedComponents != null) {
val configuration = CollectedConfiguration(embeddedComponents, Scope.COMPILE)
for (dependencyInfo in listOf(configuration).collectDependencies()) {
val dependency = (dependencyInfo as? DependencyInfo.ResolvedDependencyInfo)?.dependency ?: continue
if (dependency.isModuleDependency) {
archiveForJar.add(ModuleOutput(dependency.moduleName + ".src"))
} else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") {
error("Test configurations are not allowed here")
} else {
for (file in dependency.moduleArtifacts.map { it.file }) {
archiveForJar.add(ExtractedDirectory(file))
}
}
}
}
}
is Configuration -> {
require(sourcePath.name == "sideJars") { "Configurations other than 'sideJars' are not supported" }
for (file in sourcePath.resolve()) {
root.getDirectory("lib").add(fileCopySnapshotAware(file))
}
}
else -> error("${task.name} Unexpected task type ${task.javaClass.name}")
}
}
}
val embeddedConfiguration = prepareIdeaPluginProject.configurations.getByName(EmbeddedComponents.CONFIGURATION_NAME)
add(getArtifactElements(embeddedConfiguration, dependencyMappers, true))
})
})
val artifact = PArtifact("KotlinPlugin", File(rootProject.projectDir, "out/artifacts/Kotlin"), root)
return PFile(
@@ -203,3 +147,50 @@ fun generateKotlinPluginArtifactFile(rootProject: Project): PFile {
)
}
private fun getArtifactElements(
configuration: Configuration,
dependencyMappers: List<DependencyMapper>,
extractDependencies: Boolean
): List<ArtifactElement> {
val resolved = configuration.resolvedConfiguration
val collected = CollectedConfiguration(resolved, Scope.COMPILE)
val dependencies = listOf(collected).collectDependencies()
val mainRoots = mutableListOf<POrderRoot>()
val deferredRoots = mutableListOf<POrderRoot>()
dependencies.forEach { it.processResolvedDependency(mainRoots, deferredRoots, dependencyMappers) }
val artifacts = mutableListOf<ArtifactElement>()
for (dependency in configuration.allDependencies) {
if (dependency !is ProjectDependency) continue
val project = dependency.dependencyProject
val moduleOutput = ModuleOutput(project.name + ".src")
if (extractDependencies) {
artifacts += moduleOutput
} else {
artifacts += Archive(project.name + ".jar").apply {
add(moduleOutput)
}
}
val embeddedConfiguration = project.configurations.findByName(EmbeddedComponents.CONFIGURATION_NAME) ?: continue
artifacts += getArtifactElements(embeddedConfiguration, dependencyMappers, extractDependencies)
}
for (orderRoot in listOf(mainRoots, deferredRoots).flatten()) {
when (val dependency = orderRoot.dependency) {
is PDependency.Module -> {} // already added above
is PDependency.Library -> artifacts += ProjectLibrary(dependency.name)
is PDependency.ModuleLibrary -> {
val files = dependency.library.classes
artifacts += files.map(if (extractDependencies) ::ExtractedDirectory else ::FileCopy)
}
}
}
return artifacts
}
+43 -35
View File
@@ -376,7 +376,7 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
return configurations
}
nextDependency@ for (dependencyInfo in collectConfigurations().collectDependencies()) {
for (dependencyInfo in collectConfigurations().collectDependencies()) {
val scope = dependencyInfo.scope
if (dependencyInfo is DependencyInfo.CustomDependencyInfo) {
@@ -387,46 +387,54 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean)
continue
}
val dependency = (dependencyInfo as DependencyInfo.ResolvedDependencyInfo).dependency
for (mapper in dependencyMappers) {
if (dependency.configuration in mapper.configurations && mapper.predicate(dependency)) {
val mappedDependency = mapper.mapping(dependency)
if (mappedDependency != null) {
val mainDependency = mappedDependency.main
if (mainDependency != null) {
mainRoots += POrderRoot(mainDependency, scope)
}
for (deferredDep in mappedDependency.deferred) {
deferredRoots += POrderRoot(deferredDep, scope)
}
}
continue@nextDependency
}
}
mainRoots += if (dependency.isModuleDependency && scope != Scope.TEST) {
POrderRoot(PDependency.Module(dependency.moduleName + ".src"), scope)
} else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") {
POrderRoot(
PDependency.Module(dependency.moduleName + ".test"),
scope,
isProductionOnTestDependency = true
)
} else {
val classes = dependency.moduleArtifacts.map { it.file }
val library = PLibrary(dependency.moduleName, classes)
POrderRoot(PDependency.ModuleLibrary(library), scope)
}
dependencyInfo.processResolvedDependency(mainRoots, deferredRoots, dependencyMappers)
}
return removeDuplicates(mainRoots + deferredRoots)
}
}
fun DependencyInfo.processResolvedDependency(
mainConsumer: MutableList<POrderRoot>,
deferredConsumer: MutableList<POrderRoot>,
dependencyMappers: List<DependencyMapper>
) {
val dependency = (this as? DependencyInfo.ResolvedDependencyInfo)?.dependency ?: return
for (mapper in dependencyMappers) {
if (dependency.configuration in mapper.configurations && mapper.predicate(dependency)) {
val mappedDependency = mapper.mapping(dependency)
if (mappedDependency != null) {
val mainDependency = mappedDependency.main
if (mainDependency != null) {
mainConsumer += POrderRoot(mainDependency, scope)
}
for (deferredDep in mappedDependency.deferred) {
deferredConsumer += POrderRoot(deferredDep, scope)
}
}
return
}
}
mainConsumer += if (dependency.isModuleDependency && scope != Scope.TEST) {
POrderRoot(PDependency.Module(dependency.moduleName + ".src"), scope)
} else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") {
POrderRoot(
PDependency.Module(dependency.moduleName + ".test"),
scope,
isProductionOnTestDependency = true
)
} else {
val classes = dependency.moduleArtifacts.map { it.file }
val library = PLibrary(dependency.moduleName, classes)
POrderRoot(PDependency.ModuleLibrary(library), scope)
}
}
private fun resolveExtraDependencies(configuration: Configuration): List<File> {
return configuration.dependencies
.filterIsInstance<SelfResolvingDependency>()
+4 -2
View File
@@ -141,7 +141,9 @@ class JpsCompatiblePlugin : Plugin<Project> {
}
val projectLibraries = getProjectLibraries(rootProject)
val parserContext = ParserContext(getDependencyMappers(projectLibraries), variant)
val dependencyMappers = getDependencyMappers(projectLibraries)
val parserContext = ParserContext(dependencyMappers, variant)
val jpsProject = parse(rootProject, projectLibraries, parserContext)
.mapLibraries(this::attachPlatformSources, this::attachAsmSources)
@@ -152,7 +154,7 @@ class JpsCompatiblePlugin : Plugin<Project> {
removeJpsAndPillRunConfigurations()
removeAllArtifactConfigurations()
generateKotlinPluginArtifactFile(rootProject).write()
generateKotlinPluginArtifactFile(rootProject, dependencyMappers).write()
copyRunConfigurations()
setOptionsForDefaultJunitRunConfiguration(rootProject)