mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-11 08:31:29 +00:00
Compare commits
23 Commits
rr/stdlib/
...
native-too
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f0e20b1c7 | ||
|
|
f924de871f | ||
|
|
f953726f64 | ||
|
|
d32afbf28c | ||
|
|
2f567f0fdb | ||
|
|
c94386cff7 | ||
|
|
2cb379c7da | ||
|
|
eeb9281b25 | ||
|
|
698d69070c | ||
|
|
59cc320abc | ||
|
|
6bd1675a8b | ||
|
|
d8d69fca98 | ||
|
|
504a9ec48f | ||
|
|
712a108c7f | ||
|
|
ab9536b64a | ||
|
|
0072b62d76 | ||
|
|
83d9e9363e | ||
|
|
150f8f34c7 | ||
|
|
3bb1afb05a | ||
|
|
0aaf084ff6 | ||
|
|
415006e7b2 | ||
|
|
6631d539ad | ||
|
|
204c36fea2 |
2
.idea/runConfigurations/IDEA.xml
generated
2
.idea/runConfigurations/IDEA.xml
generated
@@ -15,6 +15,6 @@
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<method />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -22,6 +22,7 @@ buildscript {
|
||||
"https://jcenter.bintray.com/",
|
||||
"https://plugins.gradle.org/m2",
|
||||
"http://dl.bintray.com/kotlin/kotlinx",
|
||||
"https://jetbrains.bintray.com/kotlin-native-dependencies",
|
||||
"https://repo.gradle.org/gradle/ext-releases-local", // for native-platform
|
||||
"https://jetbrains.bintray.com/intellij-third-party-dependencies", // for jflex
|
||||
"https://dl.bintray.com/jetbrains/markdown" // for org.jetbrains:markdown
|
||||
|
||||
@@ -123,4 +123,4 @@ class KotlinScriptDependenciesClassFinder(project: Project,
|
||||
private fun String.splitByLastDot(): Pair<String, String> {
|
||||
return Pair(substringBeforeLast('.', missingDelimiterValue = ""), substringAfterLast('.'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
82
idea/idea-gradle/native/build.gradle.kts
Normal file
82
idea/idea-gradle/native/build.gradle.kts
Normal file
@@ -0,0 +1,82 @@
|
||||
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.teamcityServer
|
||||
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.tc
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
id("com.github.jk1.tcdeps") version "0.17"
|
||||
}
|
||||
|
||||
repositories {
|
||||
teamcityServer {
|
||||
setUrl("http://buildserver.labs.intellij.net")
|
||||
credentials {
|
||||
username = "guest"
|
||||
password = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinNativeVersion = "0.9-dev-2798"
|
||||
|
||||
dependencies {
|
||||
compile(tc("Kotlin_KotlinNative_Master_KotlinNativeLinuxDist:$kotlinNativeVersion:shared.jar"))
|
||||
compile(tc("Kotlin_KotlinNative_Master_KotlinNativeLinuxDist:$kotlinNativeVersion:backend.native.jar"))
|
||||
|
||||
compile("org.jetbrains.kotlin:kotlin-native-gradle-plugin:0.9-dev-2809") { isTransitive = false }
|
||||
|
||||
compileOnly(project(":idea:idea-gradle"))
|
||||
compileOnly(project(":idea:idea-native"))
|
||||
|
||||
testRuntime(intellijDep())
|
||||
|
||||
compileOnly(project(":idea")) { isTransitive = false }
|
||||
compileOnly(project(":idea:idea-jvm"))
|
||||
compile(project(":idea:kotlin-gradle-tooling"))
|
||||
|
||||
compile(project(":compiler:frontend"))
|
||||
compile(project(":compiler:frontend.java"))
|
||||
compile(project(":compiler:frontend.script"))
|
||||
|
||||
compile(project(":js:js.frontend"))
|
||||
|
||||
compileOnly(intellijDep())
|
||||
compileOnly(intellijPluginDep("gradle"))
|
||||
compileOnly(intellijPluginDep("Groovy"))
|
||||
compileOnly(intellijPluginDep("junit"))
|
||||
|
||||
testCompile(projectTests(":idea"))
|
||||
testCompile(projectTests(":idea:idea-test-framework"))
|
||||
|
||||
testCompile(intellijPluginDep("gradle"))
|
||||
testCompileOnly(intellijPluginDep("Groovy"))
|
||||
testCompileOnly(intellijDep())
|
||||
|
||||
testRuntime(projectDist(":kotlin-reflect"))
|
||||
testRuntime(project(":idea:idea-jvm"))
|
||||
testRuntime(project(":idea:idea-android"))
|
||||
testRuntime(project(":plugins:kapt3-idea"))
|
||||
testRuntime(project(":plugins:android-extensions-ide"))
|
||||
testRuntime(project(":plugins:lint"))
|
||||
testRuntime(project(":sam-with-receiver-ide-plugin"))
|
||||
testRuntime(project(":allopen-ide-plugin"))
|
||||
testRuntime(project(":noarg-ide-plugin"))
|
||||
testRuntime(project(":kotlin-scripting-idea"))
|
||||
// TODO: the order of the plugins matters here, consider avoiding order-dependency
|
||||
testRuntime(intellijPluginDep("junit"))
|
||||
testRuntime(intellijPluginDep("testng"))
|
||||
testRuntime(intellijPluginDep("properties"))
|
||||
testRuntime(intellijPluginDep("gradle"))
|
||||
testRuntime(intellijPluginDep("Groovy"))
|
||||
testRuntime(intellijPluginDep("coverage"))
|
||||
testRuntime(intellijPluginDep("maven"))
|
||||
testRuntime(intellijPluginDep("android"))
|
||||
testRuntime(intellijPluginDep("smali"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { none() }
|
||||
}
|
||||
|
||||
configureInstrumentation()
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.jetbrains.konan.gradle
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.find
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.findAll
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.util.BooleanFunction
|
||||
import org.jetbrains.konan.settings.KonanArtifact
|
||||
import org.jetbrains.konan.settings.KonanModelProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModel
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
|
||||
import org.jetbrains.kotlin.konan.target.PlatformManager
|
||||
import org.jetbrains.kotlin.konan.target.customerDistribution
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
|
||||
class GradleKonanModelProvider : KonanModelProvider {
|
||||
override fun reloadLibraries(project: Project, libraryPaths: Collection<Path>): Boolean =
|
||||
GradleSettings.getInstance(project).linkedProjectsSettings.isNotEmpty()
|
||||
|
||||
override fun getKonanHome(project: Project): Path? {
|
||||
val projectNode = ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID)
|
||||
.mapNotNull { it.externalProjectStructure }
|
||||
.firstOrNull() ?: return null
|
||||
projectNode.getUserData(KONAN_HOME)?.let { return it }
|
||||
|
||||
var konanHomePath: Path? = null
|
||||
find(projectNode, ProjectKeys.MODULE, BooleanFunction { moduleNode ->
|
||||
find(moduleNode, KonanProjectResolver.KONAN_MODEL_KEY, BooleanFunction { konanModelNode ->
|
||||
konanHomePath = konanModelNode.data.konanHome.toPath()
|
||||
projectNode.putUserData(KONAN_HOME, konanHomePath)
|
||||
konanHomePath != null
|
||||
}) != null
|
||||
})
|
||||
return konanHomePath
|
||||
}
|
||||
|
||||
override fun getArtifacts(project: Project): Collection<KonanArtifact> {
|
||||
val artifacts = mutableListOf<KonanArtifact>()
|
||||
ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID)
|
||||
.mapNotNull { it.externalProjectStructure }
|
||||
.forEach { projectStructure ->
|
||||
findAll(projectStructure, ProjectKeys.MODULE)
|
||||
.map { Pair(it.data.externalName, find<KonanModel>(it, KonanProjectResolver.KONAN_MODEL_KEY)) }
|
||||
.filter { it.second != null }
|
||||
.forEach { (moduleName, konanProjectNode) ->
|
||||
konanProjectNode!!.data.artifacts.forEach { konanArtifact ->
|
||||
val sources = konanArtifact.srcFiles.map { it.toPath() }
|
||||
|
||||
artifacts.add(KonanArtifact(
|
||||
konanArtifact.name,
|
||||
moduleName,
|
||||
konanArtifact.type,
|
||||
konanTarget(konanProjectNode.data.konanHome, konanArtifact),
|
||||
mutableListOf(), sources, konanArtifact.file.toPath()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
return artifacts
|
||||
}
|
||||
|
||||
private fun konanTarget(konanHome: File, konanArtifactEx: KonanModelArtifact) =
|
||||
PlatformManager(customerDistribution(konanHome.absolutePath)).targetValues.find { it.name == konanArtifactEx.targetPlatform }
|
||||
|
||||
companion object {
|
||||
val KONAN_HOME = Key.create<Path>("KONAN_HOME")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.konan.gradle
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.konan.settings.KonanProjectComponent
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
||||
|
||||
class GradleKonanProjectComponent(project: Project) : KonanProjectComponent(project) {
|
||||
override fun projectOpened() {
|
||||
super.projectOpened()
|
||||
ExternalProjectsManager.getInstance(project).runWhenInitialized {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
reloadLibraries()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun looksLikeKotlinNativeProject(): Boolean {
|
||||
//TODO not just any gradle project
|
||||
return GradleSettings.getInstance(project).linkedProjectsSettings.isNotEmpty()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.jetbrains.konan.gradle
|
||||
|
||||
import com.intellij.execution.RunManager
|
||||
import com.intellij.execution.RunnerAndConfigurationSettings
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.Key
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||
import com.intellij.openapi.externalSystem.service.project.IdeModelsProvider
|
||||
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.konan.settings.KonanArtifact
|
||||
import org.jetbrains.konan.settings.KonanModelProvider
|
||||
import org.jetbrains.konan.settings.isExecutable
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModel
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
|
||||
class KonanProjectDataService : AbstractProjectDataService<KonanModel, Module>() {
|
||||
|
||||
override fun getTargetDataKey(): Key<KonanModel> = KonanProjectResolver.KONAN_MODEL_KEY
|
||||
|
||||
override fun postProcess(toImport: Collection<DataNode<KonanModel>>,
|
||||
projectData: ProjectData?,
|
||||
project: Project,
|
||||
modelsProvider: IdeModifiableModelsProvider) {
|
||||
}
|
||||
|
||||
override fun onSuccessImport(imported: Collection<DataNode<KonanModel>>,
|
||||
projectData: ProjectData?,
|
||||
project: Project,
|
||||
modelsProvider: IdeModelsProvider) {
|
||||
if (projectData?.owner != GradleConstants.SYSTEM_ID) return
|
||||
project.messageBus.syncPublisher(KonanModelProvider.RELOAD_TOPIC).run()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun forEachKonanProject(project: Project, consumer: (konanProject: KonanModel, moduleData: ModuleData, rootProjectPath: String) -> Unit) {
|
||||
for (projectInfo in ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID)) {
|
||||
val projectStructure = projectInfo.externalProjectStructure ?: continue
|
||||
val projectData = projectStructure.data
|
||||
val rootProjectPath = projectData.linkedExternalProjectPath
|
||||
val modulesNodes = ExternalSystemApiUtil.findAll(projectStructure, ProjectKeys.MODULE)
|
||||
for (moduleNode in modulesNodes) {
|
||||
val projectNode = ExternalSystemApiUtil.find<KonanModel>(moduleNode, KonanProjectResolver.KONAN_MODEL_KEY)
|
||||
if (projectNode != null) {
|
||||
val konanProject = projectNode.data
|
||||
val moduleData = moduleNode.data
|
||||
consumer(konanProject, moduleData, rootProjectPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package org.jetbrains.konan.gradle
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.Key
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||
import com.intellij.openapi.externalSystem.model.project.*
|
||||
import com.intellij.util.containers.ContainerUtil.set
|
||||
import com.intellij.util.io.isDirectory
|
||||
import org.gradle.tooling.model.idea.IdeaModule
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModel
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.MetaVersion
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import java.io.File
|
||||
import java.nio.file.Files.isDirectory
|
||||
import java.nio.file.Files.walk
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* [KonanProjectResolver] creates IDE project model in terms of External System API
|
||||
*/
|
||||
class KonanProjectResolver : AbstractProjectResolverExtension() {
|
||||
|
||||
// to ask gradle for the model
|
||||
override fun getExtraProjectModelClasses(): Set<Class<*>> {
|
||||
return set<Class<*>>(KonanModel::class.java)
|
||||
}
|
||||
|
||||
override fun populateModuleExtraModels(gradleModule: IdeaModule, ideModule: DataNode<ModuleData>) {
|
||||
resolverCtx.getExtraProject(gradleModule, KonanModel::class.java)?.let {
|
||||
// store a local process copy of the object to get rid of proxy types for further serialization
|
||||
ideModule.createChild(KONAN_MODEL_KEY, MyKonanModel(it))
|
||||
}
|
||||
|
||||
nextResolver.populateModuleExtraModels(gradleModule, ideModule)
|
||||
}
|
||||
|
||||
override fun populateModuleContentRoots(gradleModule: IdeaModule, ideModule: DataNode<ModuleData>) {
|
||||
resolverCtx.getExtraProject(gradleModule, KonanModel::class.java)?.let {
|
||||
val added = mutableSetOf<String>()
|
||||
for (artifact in it.artifacts) {
|
||||
for (srcDir in artifact.srcDirs) {
|
||||
val rootPath = srcDir.absolutePath
|
||||
if (!added.add(rootPath)) continue
|
||||
|
||||
val ideContentRoot = ContentRootData(GradleConstants.SYSTEM_ID, rootPath)
|
||||
ideContentRoot.storePath(ExternalSystemSourceType.SOURCE, rootPath)
|
||||
ideModule.createChild(ProjectKeys.CONTENT_ROOT, ideContentRoot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nextResolver.populateModuleContentRoots(gradleModule, ideModule)
|
||||
}
|
||||
|
||||
// based on KonanCMakeProjectComponent.reloadLibraries but with the multi-module projects support
|
||||
override fun populateModuleDependencies(gradleModule: IdeaModule,
|
||||
ideModule: DataNode<ModuleData>,
|
||||
ideProject: DataNode<ProjectData>) {
|
||||
val konanModelEx = resolverCtx.getExtraProject(gradleModule, KonanModel::class.java)
|
||||
if (konanModelEx != null) {
|
||||
val libraryPaths = LinkedHashSet<Path>()
|
||||
var konanHome: Path? = null
|
||||
var targetPlatform: String? = null
|
||||
for (konanArtifact in konanModelEx.artifacts) {
|
||||
if (konanHome == null) {
|
||||
konanHome = konanModelEx.konanHome.toPath()
|
||||
targetPlatform = konanArtifact.targetPlatform
|
||||
}
|
||||
konanArtifact.libraries.forEach { libraryPaths.add(it.toPath()) }
|
||||
}
|
||||
|
||||
if (konanHome != null) {
|
||||
// add konanStdlib copied from KonanPaths.konanStdlib
|
||||
libraryPaths.add(konanHome.resolve("klib/common/stdlib"))
|
||||
|
||||
// add konanPlatformLibraries, copied from KonanPaths.konanPlatformLibraries
|
||||
if (targetPlatform != null) {
|
||||
try {
|
||||
val resolvedTargetName = HostManager.resolveAlias(targetPlatform)
|
||||
val klibPath = konanHome.resolve("klib/platform/${resolvedTargetName}")
|
||||
walk(klibPath, 1)
|
||||
.filter { it.isDirectory() && it.fileName.toString() != "stdlib" && it != klibPath }
|
||||
.forEach { libraryPaths.add(it) }
|
||||
}
|
||||
catch (e: Exception) {
|
||||
LOG.warn("Unable to collect konan platform libraries paths for '$targetPlatform'", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val moduleData = ideModule.data
|
||||
for (path in libraryPaths) {
|
||||
val library = LibraryData(moduleData.owner, path.fileName.toString())
|
||||
if (isDirectory(path)) {
|
||||
library.addPath(LibraryPathType.BINARY, path.resolve("linkdata").toAbsolutePath().toString())
|
||||
}
|
||||
else {
|
||||
library.addPath(LibraryPathType.BINARY, path.toString() + "!/linkdata")
|
||||
}
|
||||
val data = LibraryDependencyData(moduleData, library, LibraryLevel.MODULE)
|
||||
ideModule.createChild(ProjectKeys.LIBRARY_DEPENDENCY, data)
|
||||
}
|
||||
}
|
||||
|
||||
nextResolver.populateModuleDependencies(gradleModule, ideModule, ideProject)
|
||||
}
|
||||
|
||||
private class MyKonanModel(konanModel: KonanModel) : KonanModel {
|
||||
override val artifacts: List<KonanModelArtifact> = konanModel.artifacts.map { MyKonanArtifactEx(it) }
|
||||
override val konanHome: File = konanModel.konanHome
|
||||
override val konanVersion: KonanVersion = MyKonanVersionEx(konanModel.konanVersion)
|
||||
override val apiVersion: String? = konanModel.apiVersion
|
||||
override val languageVersion: String? = konanModel.languageVersion
|
||||
|
||||
private class MyKonanVersionEx(version: KonanVersion) : KonanVersion {
|
||||
override val build: Int = version.build
|
||||
override val maintenance: Int = version.maintenance
|
||||
override val major: Int = version.major
|
||||
override val meta: MetaVersion = version.meta
|
||||
override val minor: Int = version.minor
|
||||
|
||||
override fun toString(showMeta: Boolean, showBuild: Boolean): String {
|
||||
val sb = StringBuilder("$major.$minor.$maintenance")
|
||||
if (showMeta) sb.append('-').append(meta)
|
||||
if (showBuild) sb.append('-').append(build)
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private class MyKonanArtifactEx(artifact: KonanModelArtifact) : KonanModelArtifact {
|
||||
override val searchPaths: List<File> = artifact.searchPaths
|
||||
override val name: String = artifact.name
|
||||
override val type: CompilerOutputKind = artifact.type
|
||||
override val targetPlatform: String = artifact.targetPlatform
|
||||
override val file: File = artifact.file
|
||||
override val buildTaskName: String = artifact.buildTaskName
|
||||
|
||||
override val srcDirs: List<File> = artifact.srcDirs.toList()
|
||||
override val srcFiles: List<File> = artifact.srcFiles.toList()
|
||||
override val libraries: List<File> = artifact.libraries.toList()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val KONAN_MODEL_KEY = Key.create(KonanModel::class.java, ProjectKeys.MODULE.processingWeight + 1)
|
||||
private val LOG = Logger.getInstance(KonanProjectResolver::class.java)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.jetbrains.konan.gradle.internal;
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionEP;
|
||||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.extensions.ExtensionPoint;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
|
||||
public class KotlinNativeIdeInitializer implements ApplicationComponent {
|
||||
@Override
|
||||
public void initComponent() {
|
||||
unregisterGroovyInspections();
|
||||
}
|
||||
|
||||
// There are groovy local inspections which should not be loaded w/o groovy plugin enabled.
|
||||
// Those plugin definitions should become optional and dependant on groovy plugin.
|
||||
// This is a temp workaround before it happens.
|
||||
private static void unregisterGroovyInspections() {
|
||||
ExtensionPoint<LocalInspectionEP> extensionPoint =
|
||||
Extensions.getRootArea().getExtensionPoint(LocalInspectionEP.LOCAL_INSPECTION);
|
||||
|
||||
for (LocalInspectionEP ep : extensionPoint.getExtensions()) {
|
||||
if ("Kotlin".equals(ep.groupDisplayName) && "Groovy".equals(ep.language)) {
|
||||
extensionPoint.unregisterExtension(ep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
idea/idea-native/build.gradle.kts
Normal file
44
idea/idea-native/build.gradle.kts
Normal file
@@ -0,0 +1,44 @@
|
||||
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.teamcityServer
|
||||
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.tc
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
//application
|
||||
id("com.github.jk1.tcdeps") version "0.17"
|
||||
}
|
||||
|
||||
|
||||
|
||||
repositories {
|
||||
teamcityServer {
|
||||
setUrl("http://buildserver.labs.intellij.net")
|
||||
credentials {
|
||||
username = "guest"
|
||||
password = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinNativeVersion = "0.9-dev-2798"
|
||||
|
||||
dependencies {
|
||||
compile(tc("Kotlin_KotlinNative_Master_KotlinNativeLinuxDist:$kotlinNativeVersion:shared.jar"))
|
||||
compile(tc("Kotlin_KotlinNative_Master_KotlinNativeLinuxDist:$kotlinNativeVersion:backend.native.jar"))
|
||||
|
||||
compile(project(":idea"))
|
||||
compile(project(":idea:idea-core"))
|
||||
compile(project(":compiler:frontend"))
|
||||
compileOnly(intellijDep())
|
||||
}
|
||||
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { none() }
|
||||
}
|
||||
|
||||
configureInstrumentation()
|
||||
|
||||
runtimeJar {
|
||||
archiveName = "native-ide.jar"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.jetbrains.konan
|
||||
|
||||
import com.intellij.ide.highlighter.ArchiveFileType
|
||||
import com.intellij.ide.plugins.cl.PluginClassLoader
|
||||
import com.intellij.ide.util.TipAndTrickBean
|
||||
import com.intellij.openapi.components.ApplicationComponent
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
class KonanApplicationComponent : ApplicationComponent {
|
||||
override fun getComponentName(): String = "KonanApplicationComponent"
|
||||
|
||||
override fun initComponent() {
|
||||
FileTypeManager.getInstance().associateExtension(ArchiveFileType.INSTANCE, "klib")
|
||||
|
||||
val extensionPoint = Extensions.getRootArea().getExtensionPoint(TipAndTrickBean.EP_NAME)
|
||||
for (name in arrayOf("Kotlin.html", "Kotlin_project.html", "Kotlin_mix.html", "Kotlin_Java_convert.html")) {
|
||||
TipAndTrickBean.findByFileName(name)?.let {
|
||||
extensionPoint.unregisterExtension(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.jetbrains.konan
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.stubs.StubTree
|
||||
import org.jetbrains.konan.analyser.index.KonanDescriptorManager
|
||||
import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider
|
||||
import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText
|
||||
|
||||
class KonanDecompiledFile(provider: KotlinDecompiledFileViewProvider,
|
||||
text: (VirtualFile) -> DecompiledText) : KtDecompiledFile(provider, text) {
|
||||
|
||||
override fun getStubTree(): StubTree? {
|
||||
val vFile = virtualFile
|
||||
val cache = KonanDescriptorManager.INSTANCE
|
||||
|
||||
val cached = cache.getStub(vFile)
|
||||
if (cached != null) {
|
||||
return cached
|
||||
}
|
||||
|
||||
val stubTree = super.getStubTree()
|
||||
if (stubTree != null) {
|
||||
cache.cacheStub(vFile, stubTree)
|
||||
}
|
||||
|
||||
return stubTree
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.jetbrains.konan
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.progress.Task
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.SystemProperties.getUserHome
|
||||
import com.intellij.util.io.exists
|
||||
import com.intellij.util.net.IOExceptionDialog
|
||||
import org.jetbrains.konan.settings.KonanProjectComponent
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.util.DependencyDownloader
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
import org.jetbrains.kotlin.konan.util.DependencySource
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
class KotlinNativeToolchain(
|
||||
val version: String,
|
||||
val repoUrl: String
|
||||
) {
|
||||
private val artifactName = "kotlin-native-$KONAN_OS-$version"
|
||||
val baseDir: Path get() = Paths.get("${getUserHome()}/.konan/$artifactName")
|
||||
val konanc: Path get() = baseDir.resolve("bin/konanc")
|
||||
val cinterop: Path get() = baseDir.resolve("bin/cinterop")
|
||||
|
||||
|
||||
fun ensureExists(project: Project) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread()
|
||||
if (baseDir.exists()) return
|
||||
|
||||
for (attempt in 0..3) {
|
||||
var exception: Throwable? = null
|
||||
object : Task.Modal(project, "Downloading Kotlin/Native $version", false) {
|
||||
override fun run(progress: ProgressIndicator) {
|
||||
DependencyProcessor(
|
||||
baseDir.parent.toFile(),
|
||||
repoUrl,
|
||||
mapOf(artifactName to listOf(DependencySource.Remote.Public)),
|
||||
customProgressCallback = { _, downloaded, total ->
|
||||
progress.fraction = downloaded / maxOf(total, downloaded, 1).toDouble()
|
||||
}
|
||||
).run()
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
project.getComponent(KonanProjectComponent::class.java).reloadLibraries()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onThrowable(error: Throwable) {
|
||||
exception = error
|
||||
}
|
||||
}.queue()
|
||||
|
||||
val ex = exception
|
||||
val tryAgain = if (ex == null) {
|
||||
false
|
||||
}
|
||||
else {
|
||||
val details = if (ex is DependencyDownloader.HTTPResponseException) {
|
||||
"Server returned ${ex.responseCode} when trying to download ${ex.url}."
|
||||
}
|
||||
else {
|
||||
LOG.error(ex)
|
||||
"Unknown error occurred."
|
||||
}
|
||||
IOExceptionDialog.showErrorDialog(
|
||||
"Failed to download Kotlin/Native",
|
||||
details
|
||||
)
|
||||
}
|
||||
if (!tryAgain) break
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun looksLikeBundledToolchain(path: String): Boolean =
|
||||
Paths.get(path).startsWith(Paths.get("${getUserHome()}/.konan/"))
|
||||
|
||||
private val KONAN_OS = HostManager.simpleOsName()
|
||||
|
||||
//todo: fixme
|
||||
private val BUNDLED_VERSION = "0.8" //bundledFile("kotlin-native-version").readText().trim()
|
||||
private val BUILD_DIR = "releases"
|
||||
|
||||
val BUNDLED = KotlinNativeToolchain(
|
||||
version = BUNDLED_VERSION,
|
||||
repoUrl = "https://download.jetbrains.com/kotlin/native/builds/$BUILD_DIR/$BUNDLED_VERSION/$KONAN_OS"
|
||||
)
|
||||
|
||||
private val LOG = Logger.getInstance(KotlinNativeToolchain::class.java)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.jetbrains.konan;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.stubs.PsiFileStub;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import kotlin.Pair;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.analyzer.ModuleContent;
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo;
|
||||
import org.jetbrains.kotlin.context.ModuleContext;
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType;
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage;
|
||||
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo;
|
||||
import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider;
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText;
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter;
|
||||
import org.jetbrains.kotlin.idea.references.KtReference;
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression;
|
||||
import org.jetbrains.kotlin.psi.KtExpressionCodeFragment;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory;
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class KotlinWorkaroundUtil {
|
||||
@NotNull
|
||||
public static PsiFileStub createFileStub(@NotNull Project project, @NotNull String text) {
|
||||
final LightVirtualFile virtualFile = new LightVirtualFile("dummy.kt", KotlinFileType.INSTANCE, text);
|
||||
virtualFile.setLanguage(KotlinLanguage.INSTANCE);
|
||||
SingleRootFileViewProvider.doNotCheckFileSizeLimit(virtualFile);
|
||||
|
||||
PsiFileFactoryImpl psiFileFactory = (PsiFileFactoryImpl)PsiFileFactory.getInstance(project);
|
||||
PsiFile file = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, false, false);
|
||||
assert file != null;
|
||||
return (PsiFileStub)KtStubElementTypes.FILE.getBuilder().buildStubTree(file);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static KtExpressionCodeFragment createCodeFragment(@NotNull Project project,
|
||||
@NotNull String referenceText,
|
||||
@NotNull KtBlockExpression blockExpression) {
|
||||
return new KtPsiFactory(project, false).createExpressionCodeFragment(referenceText, blockExpression);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement resolveMainReference(@NotNull KtReference mainReference) {
|
||||
return mainReference.resolve();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static KtBlockExpression getNonStrictParentOfType(@Nullable PsiElement contextElement) {
|
||||
if (contextElement == null) return null;
|
||||
return PsiUtilsKt.getNonStrictParentOfType(contextElement, KtBlockExpression.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LoggingErrorReporter createLoggingErrorReporter(@NotNull Logger log) {
|
||||
return new LoggingErrorReporter(log);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FileViewProvider createDecompiledFileViewProvider(@NotNull PsiManager manager,
|
||||
@NotNull VirtualFile file,
|
||||
boolean physical,
|
||||
@NotNull Function1<VirtualFile, DecompiledText> buildDecompiledText) {
|
||||
return new KotlinDecompiledFileViewProvider(manager, file, physical,
|
||||
provider -> new KonanDecompiledFile(provider, buildDecompiledText));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Project getProject(@NotNull ModuleContext moduleContext) {
|
||||
return moduleContext.getProject();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <M extends ModuleInfo> Pair<Collection<KtFile>, GlobalSearchScope> destructModuleContent(@NotNull ModuleContent<M> moduleContent) {
|
||||
return new Pair<>(moduleContent.component2(), moduleContent.component3());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <M extends ModuleInfo> DeclarationProviderFactory createDeclarationProviderFactory(@NotNull Project project,
|
||||
@NotNull ModuleContext moduleContext,
|
||||
@NotNull Collection<KtFile> syntheticFiles,
|
||||
@NotNull M moduleInfo,
|
||||
@Nullable GlobalSearchScope globalSearchScope) {
|
||||
return DeclarationProviderFactoryService.createDeclarationProviderFactory(
|
||||
project,
|
||||
moduleContext.getStorageManager(),
|
||||
syntheticFiles,
|
||||
globalSearchScope,
|
||||
moduleInfo);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LibraryInfo createLibraryInfo(@NotNull Project project, @NotNull Library library) {
|
||||
return new LibraryInfo(project, library);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.jetbrains.konan
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.StartupActivity
|
||||
import org.jetbrains.konan.settings.KonanProjectComponent
|
||||
|
||||
class SetupKotlinNativeStartupActivity : StartupActivity {
|
||||
override fun runActivity(project: Project) {
|
||||
//todo: looks like without default project component (like disabled Gradle plugin) we will get exception here (that's bad)
|
||||
if (!KonanProjectComponent.getInstance(project).looksLikeKotlinNativeProject()) return
|
||||
ensureKotlinNativeExists(project)
|
||||
}
|
||||
|
||||
private fun ensureKotlinNativeExists(project: Project) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread()
|
||||
KotlinNativeToolchain.BUNDLED.ensureExists(project)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package org.jetbrains.konan.analyser
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.ProjectFileIndex
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import org.jetbrains.konan.KotlinWorkaroundUtil.*
|
||||
import org.jetbrains.konan.analyser.index.KonanDescriptorManager
|
||||
import org.jetbrains.konan.settings.KonanPaths
|
||||
import org.jetbrains.kotlin.analyzer.*
|
||||
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.createForwardDeclarationsModule
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.TargetPlatformVersion
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.descriptors.PackagePartProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.frontend.di.createContainerForLazyResolve
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* @author Alefas
|
||||
*/
|
||||
|
||||
class KonanAnalyzerFacade : ResolverForModuleFactory() {
|
||||
override val targetPlatform: TargetPlatform
|
||||
get() = KonanPlatform
|
||||
|
||||
override fun <M : ModuleInfo> createResolverForModule(
|
||||
moduleDescriptor: ModuleDescriptorImpl,
|
||||
moduleContext: ModuleContext,
|
||||
moduleContent: ModuleContent<M>,
|
||||
platformParameters: PlatformAnalysisParameters,
|
||||
targetEnvironment: TargetEnvironment,
|
||||
resolverForProject: ResolverForProject<M>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
targetPlatformVersion: TargetPlatformVersion,
|
||||
packagePartProvider: PackagePartProvider): ResolverForModule {
|
||||
|
||||
val (syntheticFiles, moduleContentScope) = destructModuleContent(moduleContent)
|
||||
val project = getProject(moduleContext)
|
||||
val declarationProviderFactory = createDeclarationProviderFactory(project, moduleContext, syntheticFiles, moduleContent.moduleInfo,
|
||||
moduleContentScope)
|
||||
|
||||
val container = createContainerForLazyResolve(
|
||||
moduleContext,
|
||||
declarationProviderFactory,
|
||||
BindingTraceContext(),
|
||||
KonanPlatform,
|
||||
TargetPlatformVersion.NoVersion,
|
||||
targetEnvironment,
|
||||
languageVersionSettings
|
||||
)
|
||||
|
||||
val packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider
|
||||
|
||||
val konanPaths = KonanPaths.getInstance(project)
|
||||
val libraryPaths = konanPaths.libraryPaths().toMutableList()
|
||||
libraryPaths.addAll(konanPaths.konanPlatformLibraries())
|
||||
|
||||
val module = resolveModule(syntheticFiles, project)
|
||||
|
||||
fun setLibraryForDescriptor(path: Path, descriptor: ModuleDescriptorImpl) {
|
||||
val library = findLibrary(module, path) ?: return
|
||||
//todo: replace reflection by changes to kotlin-native?
|
||||
descriptor.setField("capabilities", { oldValue ->
|
||||
val capabilities = oldValue as Map<*, *>
|
||||
val libraryInfo = createLibraryInfo(project, library)
|
||||
capabilities + Pair(ModuleInfo.Capability, libraryInfo)
|
||||
})
|
||||
}
|
||||
|
||||
fun createDescriptor(path: Path): ModuleDescriptorImpl? {
|
||||
val file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(path.toFile())
|
||||
return if (file != null && file.exists()) {
|
||||
val descriptor = KonanDescriptorManager.INSTANCE.getDescriptor(file, languageVersionSettings)
|
||||
setLibraryForDescriptor(path, descriptor)
|
||||
descriptor
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
val descriptors = libraryPaths.mapNotNull(::createDescriptor)
|
||||
val stdlibDescriptor = konanPaths.konanStdlib()?.let(::createDescriptor)
|
||||
|
||||
val dependencies = descriptors.toMutableList()
|
||||
if (stdlibDescriptor != null)
|
||||
dependencies.add(stdlibDescriptor)
|
||||
|
||||
// Create module for handling `cnames.structs` opaque declarations. It should be singleton and last dependency in the list.
|
||||
val builtIns = moduleContext.module.builtIns
|
||||
val storageManager: StorageManager = moduleContext.storageManager
|
||||
val forwardDeclarationsModule = createForwardDeclarationsModule(builtIns, storageManager)
|
||||
|
||||
for (descriptor in descriptors) {
|
||||
descriptor.setField("dependencies", { null })
|
||||
descriptor.setDependencies(descriptor, stdlibDescriptor!!, forwardDeclarationsModule)
|
||||
}
|
||||
|
||||
stdlibDescriptor?.let {
|
||||
it.setField("dependencies", { null })
|
||||
it.setDependencies(listOf(it))
|
||||
}
|
||||
|
||||
val fragmentProviders = mutableListOf(packageFragmentProvider)
|
||||
descriptors.mapTo(fragmentProviders) { it.packageFragmentProvider }
|
||||
fragmentProviders.add(forwardDeclarationsModule.packageFragmentProvider)
|
||||
|
||||
return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container)
|
||||
}
|
||||
|
||||
private fun resolveModule(syntheticFiles: MutableCollection<KtFile>,
|
||||
project: Project): Module {
|
||||
val virtualFilePath = try {
|
||||
syntheticFiles.firstOrNull()?.virtualFilePath
|
||||
}
|
||||
catch (e: IllegalStateException) {
|
||||
null
|
||||
}
|
||||
return virtualFilePath
|
||||
?.run { VfsUtil.findFileByIoFile(java.io.File(this), false) }
|
||||
?.run { ProjectFileIndex.SERVICE.getInstance(project).getModuleForFile(this) }
|
||||
?: ModuleManager.getInstance(project).modules.first()
|
||||
}
|
||||
|
||||
private fun findLibrary(module: Module, path: Path): Library? {
|
||||
var lib: Library? = null
|
||||
ModuleRootManager.getInstance(module).orderEntries().forEachLibrary {
|
||||
if (it.name?.substringAfter(": ") == path.fileName.toString()) {
|
||||
lib = it
|
||||
false
|
||||
}
|
||||
else {
|
||||
true
|
||||
}
|
||||
}
|
||||
return lib
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Any.setField(fieldName: String, update: (Any?) -> Any?) {
|
||||
val field = javaClass.declaredFields.find { it.name == fieldName }
|
||||
if (field != null) {
|
||||
field.isAccessible = true
|
||||
val oldValue = field.get(this)
|
||||
val newValue = update(oldValue)
|
||||
field.set(this, newValue)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.jetbrains.konan.analyser
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.util.io.exists
|
||||
import org.jetbrains.konan.analyser.index.KonanDescriptorManager
|
||||
import org.jetbrains.konan.settings.KonanPaths
|
||||
import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
|
||||
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.caches.resolve.IdePlatformSupport
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.context.GlobalContextImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
|
||||
/**
|
||||
* @author Alefas
|
||||
*/
|
||||
class KonanPlatformSupport : IdePlatformSupport() {
|
||||
|
||||
override val resolverForModuleFactory: ResolverForModuleFactory
|
||||
get() = KonanAnalyzerFacade()
|
||||
|
||||
override val libraryKind: PersistentLibraryKind<*>?
|
||||
get() = null
|
||||
|
||||
override val platform: TargetPlatform
|
||||
get() = KonanPlatform
|
||||
|
||||
override fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl): KotlinBuiltIns {
|
||||
val storageManager = sdkContext.storageManager
|
||||
val builtIns = KonanBuiltIns(storageManager)
|
||||
|
||||
//todo: it depends on a random project's stdlib, propagate the actual project here
|
||||
val konanStdlib = ProjectManager.getInstance().openProjects.asSequence().mapNotNull { KonanPaths.getInstance(it).konanStdlib() }.firstOrNull()
|
||||
if (konanStdlib != null && konanStdlib.exists()) {
|
||||
val stdLib = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(konanStdlib.toFile())
|
||||
if (stdLib != null) {
|
||||
val manager = KonanDescriptorManager.INSTANCE
|
||||
val builtInsModule: ModuleDescriptorImpl = manager.getDescriptor(stdLib, LanguageVersionSettingsImpl.DEFAULT)
|
||||
builtInsModule.setField("dependencies", { null })
|
||||
builtInsModule.setDependencies(builtInsModule)
|
||||
builtIns.builtInsModule = builtInsModule
|
||||
}
|
||||
}
|
||||
|
||||
return builtIns
|
||||
}
|
||||
|
||||
override fun isModuleForPlatform(module: Module): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.jetbrains.konan.analyser.index
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.ApplicationComponent
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileEvent
|
||||
import com.intellij.openapi.vfs.VirtualFileListener
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.psi.stubs.StubTree
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.metadata.KonanLinkData
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
private const val currentAbiVersion = 1
|
||||
|
||||
class KonanDescriptorManager : ApplicationComponent {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val INSTANCE: KonanDescriptorManager
|
||||
get() = ApplicationManager.getApplication().getComponent(KonanDescriptorManager::class.java)
|
||||
}
|
||||
|
||||
override fun initComponent() {
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(object : VirtualFileListener {
|
||||
override fun fileCreated(event: VirtualFileEvent) {
|
||||
val file = event.file
|
||||
|
||||
descriptorCache.values.forEach { it.remove(file) }
|
||||
protoCache.remove(file)
|
||||
stubCache.remove(file)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private val descriptorCache = ContainerUtil.createConcurrentSoftValueMap<LanguageVersionSettings, ConcurrentMap<VirtualFile, ModuleDescriptorImpl>>()
|
||||
private val protoCache = ContainerUtil.createConcurrentSoftValueMap<VirtualFile, KonanLinkData.LinkDataPackageFragment>()
|
||||
private val stubCache = ContainerUtil.createConcurrentSoftValueMap<VirtualFile, StubTree>()
|
||||
|
||||
fun getDescriptor(file: VirtualFile, specifics: LanguageVersionSettings): ModuleDescriptorImpl {
|
||||
val cache = descriptorCache.computeIfAbsent(specifics, {
|
||||
ContainerUtil.createConcurrentSoftValueMap()
|
||||
})
|
||||
|
||||
return cache.computeIfAbsent(file, {
|
||||
val reader = LibraryReaderImpl(File(file.path), currentAbiVersion)
|
||||
reader.moduleDescriptor(specifics)
|
||||
})
|
||||
}
|
||||
|
||||
fun parsePackageFragment(file: VirtualFile): KonanLinkData.LinkDataPackageFragment {
|
||||
return protoCache.computeIfAbsent(file, {
|
||||
val bytes = file.contentsToByteArray(false)
|
||||
org.jetbrains.kotlin.backend.konan.serialization.parsePackageFragment(bytes)
|
||||
})
|
||||
}
|
||||
|
||||
fun getStub(file: VirtualFile): StubTree? {
|
||||
return stubCache[file]
|
||||
}
|
||||
|
||||
fun cacheStub(file: VirtualFile, stubTree: StubTree?) {
|
||||
stubCache[file] = stubTree
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.konan.analyser.index;
|
||||
|
||||
import org.jetbrains.kotlin.idea.util.KotlinBinaryExtension;
|
||||
|
||||
public class KonanMetaBinary extends KotlinBinaryExtension {
|
||||
public KonanMetaBinary() {
|
||||
super(KonanMetaFileType.INSTANCE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.jetbrains.konan.analyser.index;
|
||||
|
||||
import com.intellij.util.indexing.DataIndexer;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.indexing.FileContent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.idea.vfilefinder.KotlinFileIndexBase;
|
||||
import org.jetbrains.kotlin.metadata.KonanLinkData;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
|
||||
public class KonanMetaFileIndex extends KotlinFileIndexBase<KonanMetaFileIndex> {
|
||||
private static final int VERSION = 4;
|
||||
|
||||
/*todo: check version?!*/
|
||||
private final DataIndexer<FqName, Void, FileContent> INDEXER = indexer(fileContent -> {
|
||||
KonanLinkData.LinkDataPackageFragment fragment = KonanDescriptorManager.getINSTANCE().parsePackageFragment(fileContent.getFile());
|
||||
return new FqName(fragment.getFqName());
|
||||
});
|
||||
|
||||
public KonanMetaFileIndex() {
|
||||
super(KonanMetaFileIndex.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FileBasedIndex.InputFilter getInputFilter() {
|
||||
return file -> file.getFileType() == KonanMetaFileType.INSTANCE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DataIndexer<FqName, Void, FileContent> getIndexer() {
|
||||
return INDEXER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.jetbrains.konan.analyser.index
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import com.intellij.openapi.fileTypes.FileTypeConsumer
|
||||
import com.intellij.openapi.fileTypes.FileTypeFactory
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanSerializerProtocol
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.NullFlexibleTypeDeserializer
|
||||
import org.jetbrains.kotlin.metadata.KonanLinkData
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
|
||||
class KonanMetadataDecompiler : KonanMetadataDecompilerBase<KonanMetadataVersion>(
|
||||
KonanMetaFileType, KonanPlatform, KonanSerializerProtocol, NullFlexibleTypeDeserializer,
|
||||
KonanMetadataVersion.DEFAULT_INSTANCE, KonanMetadataVersion.INVALID_VERSION, KonanMetaFileType.STUB_VERSION
|
||||
) {
|
||||
override fun doReadFile(file: VirtualFile): FileWithMetadata? {
|
||||
val proto: KonanLinkData.LinkDataPackageFragment = KonanDescriptorManager.INSTANCE.parsePackageFragment(file)
|
||||
return FileWithMetadata.Compatible(proto, KonanSerializerProtocol) //todo: check version compatibility
|
||||
}
|
||||
}
|
||||
|
||||
class KonanMetadataVersion(vararg numbers: Int) : BinaryVersion(*numbers) {
|
||||
override fun isCompatible(): Boolean = true //todo: ?
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val DEFAULT_INSTANCE = KonanMetadataVersion(1, 1, 0)
|
||||
|
||||
@JvmField
|
||||
val INVALID_VERSION = KonanMetadataVersion()
|
||||
}
|
||||
}
|
||||
|
||||
object KonanMetaFileType : FileType {
|
||||
override fun getName() = "KNM"
|
||||
override fun getDescription() = "Kotlin/Native Metadata"
|
||||
override fun getDefaultExtension() = "knm"
|
||||
override fun getIcon() = null
|
||||
override fun isBinary() = true
|
||||
override fun isReadOnly() = true
|
||||
override fun getCharset(file: VirtualFile, content: ByteArray) = null
|
||||
|
||||
const val STUB_VERSION = 2
|
||||
}
|
||||
|
||||
class KonanMetaFileTypeFactory : FileTypeFactory() {
|
||||
override fun createFileTypes(consumer: FileTypeConsumer) {
|
||||
consumer.consume(KonanMetaFileType, KonanMetaFileType.defaultExtension)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.konan.analyser.index
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.FileViewProvider
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.compiled.ClassFileDecompilers
|
||||
import org.jetbrains.konan.KotlinWorkaroundUtil.createDecompiledFileViewProvider
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.decompiler.common.createIncompatibleAbiVersionDecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions
|
||||
import org.jetbrains.kotlin.metadata.KonanLinkData
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDeserializer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.io.IOException
|
||||
|
||||
//todo: Fix in Kotlin plugin
|
||||
abstract class KonanMetadataDecompilerBase<out V : BinaryVersion>(
|
||||
private val fileType: FileType,
|
||||
private val targetPlatform: TargetPlatform,
|
||||
private val serializerProtocol: SerializerExtensionProtocol,
|
||||
private val flexibleTypeDeserializer: FlexibleTypeDeserializer,
|
||||
private val expectedBinaryVersion: V,
|
||||
private val invalidBinaryVersion: V,
|
||||
stubVersion: Int
|
||||
) : ClassFileDecompilers.Full() {
|
||||
private val stubBuilder = KonanMetadataStubBuilder(stubVersion, fileType, serializerProtocol, this::readFile)
|
||||
|
||||
private val renderer = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
||||
|
||||
protected abstract fun doReadFile(file: VirtualFile): FileWithMetadata?
|
||||
|
||||
override fun accepts(file: VirtualFile) = file.fileType == fileType
|
||||
|
||||
override fun getStubBuilder() = stubBuilder
|
||||
|
||||
override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): FileViewProvider {
|
||||
return createDecompiledFileViewProvider(manager, file, physical, this::buildDecompiledText)
|
||||
}
|
||||
|
||||
private fun readFile(file: VirtualFile): FileWithMetadata? {
|
||||
if (!file.isValid) return null
|
||||
|
||||
return try {
|
||||
doReadFile(file)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
// This is needed because sometimes we're given VirtualFile instances that point to non-existent .jar entries.
|
||||
// Such files are valid (isValid() returns true), but an attempt to read their contents results in a FileNotFoundException.
|
||||
// Note that although calling "refresh()" instead of catching an exception would seem more correct here,
|
||||
// it's not always allowed and also is likely to degrade performance
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDecompiledText(virtualFile: VirtualFile): DecompiledText {
|
||||
if (virtualFile.fileType != fileType) {
|
||||
error("Unexpected file type ${virtualFile.fileType}")
|
||||
}
|
||||
|
||||
val file = readFile(virtualFile)
|
||||
|
||||
return when (file) {
|
||||
null -> {
|
||||
createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion, invalidBinaryVersion)
|
||||
}
|
||||
is FileWithMetadata.Incompatible -> {
|
||||
createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion, file.version)
|
||||
}
|
||||
is FileWithMetadata.Compatible -> {
|
||||
decompiledText(file, targetPlatform, serializerProtocol, flexibleTypeDeserializer, renderer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class FileWithMetadata {
|
||||
class Incompatible(val version: BinaryVersion) : FileWithMetadata()
|
||||
|
||||
open class Compatible(
|
||||
val proto: KonanLinkData.LinkDataPackageFragment,
|
||||
serializerProtocol: SerializerExtensionProtocol
|
||||
) : FileWithMetadata() {
|
||||
val nameResolver = NameResolverImpl(proto.stringTable, proto.nameTable)
|
||||
val packageFqName = FqName(nameResolver.getPackageFqName(proto.`package`.getExtension(serializerProtocol.packageFqName)))
|
||||
|
||||
open val classesToDecompile: List<ProtoBuf.Class> =
|
||||
proto.classes.classesList.filter { proto ->
|
||||
val classId = nameResolver.getClassId(proto.fqName)
|
||||
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//todo: this function is extracted for KonanMetadataStubBuilder, that's the difference from Big Kotlin.
|
||||
fun decompiledText(file: FileWithMetadata.Compatible, targetPlatform: TargetPlatform,
|
||||
serializerProtocol: SerializerExtensionProtocol,
|
||||
flexibleTypeDeserializer: FlexibleTypeDeserializer,
|
||||
renderer: DescriptorRenderer): DecompiledText {
|
||||
val packageFqName = file.packageFqName
|
||||
val resolver = KonanMetadataDeserializerForDecompiler(
|
||||
packageFqName, file.proto, file.nameResolver,
|
||||
targetPlatform, serializerProtocol, flexibleTypeDeserializer
|
||||
)
|
||||
val declarations = arrayListOf<DeclarationDescriptor>()
|
||||
declarations.addAll(resolver.resolveDeclarationsInFacade(packageFqName))
|
||||
for (classProto in file.classesToDecompile) {
|
||||
val classId = file.nameResolver.getClassId(classProto.fqName)
|
||||
declarations.addIfNotNull(resolver.resolveTopLevelClass(classId))
|
||||
}
|
||||
return buildDecompiledText(packageFqName, declarations, renderer)
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.konan.analyser.index
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import org.jetbrains.konan.KotlinWorkaroundUtil.createLoggingErrorReporter
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DeserializerForDecompilerBase
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolveEverythingToKotlinAnyLocalClassifierResolver
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.metadata.KonanLinkData
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||
|
||||
//todo: Fix in Kotlin plugin
|
||||
class KonanMetadataDeserializerForDecompiler(
|
||||
packageFqName: FqName,
|
||||
private val proto: KonanLinkData.LinkDataPackageFragment,
|
||||
private val nameResolver: NameResolver,
|
||||
override val targetPlatform: TargetPlatform,
|
||||
serializerProtocol: SerializerExtensionProtocol,
|
||||
flexibleTypeDeserializer: FlexibleTypeDeserializer
|
||||
) : DeserializerForDecompilerBase(packageFqName) {
|
||||
override val builtIns: KotlinBuiltIns get() = DefaultBuiltIns.Instance
|
||||
|
||||
override val deserializationComponents: DeserializationComponents
|
||||
|
||||
init {
|
||||
val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
|
||||
|
||||
deserializationComponents = DeserializationComponents(
|
||||
storageManager, moduleDescriptor, DeserializationConfiguration.Default, KonanProtoBasedClassDataFinder(proto, nameResolver),
|
||||
AnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, serializerProtocol), packageFragmentProvider,
|
||||
ResolveEverythingToKotlinAnyLocalClassifierResolver(builtIns), createLoggingErrorReporter(LOG),
|
||||
LookupTracker.DO_NOTHING, flexibleTypeDeserializer, emptyList(), notFoundClasses, ContractDeserializer.DEFAULT,
|
||||
extensionRegistryLite = serializerProtocol.extensionRegistry
|
||||
)
|
||||
}
|
||||
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
|
||||
assert(facadeFqName == directoryPackageFqName) {
|
||||
"Was called for $facadeFqName; only members of $directoryPackageFqName package are expected."
|
||||
}
|
||||
|
||||
val membersScope = DeserializedPackageMemberScope(
|
||||
createDummyPackageFragment(facadeFqName), proto.`package`, nameResolver, containerSource = null,
|
||||
components = deserializationComponents
|
||||
) { emptyList() }
|
||||
|
||||
return membersScope.getContributedDescriptors().toList()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(KonanMetadataDeserializerForDecompiler::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.konan.analyser.index
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.compiled.ClsStubBuilder
|
||||
import com.intellij.psi.impl.compiled.ClassFileStubBuilder
|
||||
import com.intellij.psi.stubs.PsiFileStub
|
||||
import com.intellij.util.indexing.FileContent
|
||||
import org.jetbrains.konan.KotlinWorkaroundUtil.createFileStub
|
||||
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.NullFlexibleTypeDeserializer
|
||||
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.createIncompatibleAbiVersionFileStub
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
||||
|
||||
//todo: Fix in Kotlin plugin
|
||||
open class KonanMetadataStubBuilder(
|
||||
private val version: Int,
|
||||
private val fileType: FileType,
|
||||
private val serializerProtocol: SerializerExtensionProtocol,
|
||||
private val readFile: (VirtualFile) -> FileWithMetadata?
|
||||
) : ClsStubBuilder() {
|
||||
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + version
|
||||
|
||||
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
||||
val virtualFile = content.file
|
||||
assert(virtualFile.fileType == fileType) { "Unexpected file type ${virtualFile.fileType}" }
|
||||
val file = readFile(virtualFile) ?: return null
|
||||
|
||||
when (file) {
|
||||
is FileWithMetadata.Incompatible -> {
|
||||
return createIncompatibleAbiVersionFileStub()
|
||||
}
|
||||
is FileWithMetadata.Compatible -> { //todo: this part is implemented in our own way
|
||||
val renderer = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
||||
val ktFileText = decompiledText(file, KonanPlatform, serializerProtocol, NullFlexibleTypeDeserializer, renderer)
|
||||
return createFileStub(content.project, ktFileText.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.jetbrains.konan.analyser.index
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.metadata.KonanLinkData
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassData
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
|
||||
//todo: Fix in Kotlin plugin
|
||||
class KonanProtoBasedClassDataFinder(
|
||||
proto: KonanLinkData.LinkDataPackageFragment,
|
||||
private val nameResolver: NameResolver,
|
||||
private val classSource: (ClassId) -> SourceElement = { SourceElement.NO_SOURCE }
|
||||
) : ClassDataFinder {
|
||||
private val classIdToProto =
|
||||
proto.classes.classesList.associateBy { klass ->
|
||||
nameResolver.getClassId(klass.fqName)
|
||||
}
|
||||
|
||||
internal val allClassIds: Collection<ClassId> get() = classIdToProto.keys
|
||||
|
||||
override fun findClassData(classId: ClassId): ClassData? {
|
||||
val classProto = classIdToProto[classId] ?: return null
|
||||
return ClassData(nameResolver, classProto, classSource(classId))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.jetbrains.konan.settings
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind.*
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.nio.file.Path
|
||||
|
||||
data class KonanArtifact(
|
||||
val targetName: String,
|
||||
val moduleName: String,
|
||||
val type: CompilerOutputKind,
|
||||
val target: KonanTarget?,
|
||||
val libraryDependencies: List<String>,
|
||||
val sources: List<Path>,
|
||||
val output: Path
|
||||
)
|
||||
|
||||
val CompilerOutputKind.isLibrary: Boolean get() = this == LIBRARY || this == DYNAMIC || this == STATIC || this == FRAMEWORK
|
||||
val CompilerOutputKind.isExecutable: Boolean get() = this == PROGRAM
|
||||
val CompilerOutputKind.isTest: Boolean get() = false //TODO
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.jetbrains.konan.settings;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.messages.Topic;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public interface KonanModelProvider {
|
||||
Topic<Runnable> RELOAD_TOPIC = new Topic<>("Konan Project Model Updater", Runnable.class);
|
||||
|
||||
ExtensionPointName<KonanModelProvider> EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.native.konanModelProvider");
|
||||
|
||||
@NotNull
|
||||
Collection<KonanArtifact> getArtifacts(@NotNull Project project);
|
||||
|
||||
@Nullable
|
||||
Path getKonanHome(@NotNull Project project);
|
||||
|
||||
boolean reloadLibraries(@NotNull Project project, @NotNull Collection<Path> libraryPaths);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.jetbrains.konan.settings
|
||||
|
||||
import com.intellij.openapi.components.ProjectComponent
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.io.exists
|
||||
import com.intellij.util.io.isDirectory
|
||||
import org.jetbrains.konan.KotlinNativeToolchain
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.stream.Collectors
|
||||
|
||||
open class KonanPaths(protected val project: Project) : ProjectComponent {
|
||||
companion object {
|
||||
private const val STDLIB_PATH = "klib/common/stdlib" //todo: move to kotlin/native
|
||||
|
||||
fun bundledKonanDist(): Path = KotlinNativeToolchain.BUNDLED.baseDir
|
||||
|
||||
fun getInstance(project: Project): KonanPaths = project.getComponent(KonanPaths::class.java)
|
||||
}
|
||||
|
||||
override fun getComponentName() = "Konan Compiler Paths"
|
||||
|
||||
fun konanStdlib(): Path? = konanDist()?.resolve(STDLIB_PATH)
|
||||
|
||||
open fun konanDist(): Path? {
|
||||
for (provider in KonanModelProvider.EP_NAME.extensions) {
|
||||
return provider.getKonanHome(project)
|
||||
}
|
||||
return bundledKonanDist()
|
||||
}
|
||||
|
||||
open fun libraryPaths(): Set<Path> = emptySet()
|
||||
|
||||
fun konanPlatformLibraries(): List<Path> {
|
||||
val resolvedTargetName = HostManager.resolveAlias(target().name)
|
||||
val klibPath = konanDist()?.resolve("klib/platform/${resolvedTargetName}") ?: return emptyList()
|
||||
if (!klibPath.exists()) return emptyList()
|
||||
return Files.walk(klibPath, 1).filter {
|
||||
it.isDirectory() && it.fileName.toString() != "stdlib" && it != klibPath
|
||||
}.collect(Collectors.toList())
|
||||
}
|
||||
|
||||
//todo: this is wrong, we are not allowing multiple targets in project
|
||||
open fun target(): KonanTarget = HostManager.host
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package org.jetbrains.konan.settings
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.components.ProjectComponent
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.OrderRootType
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable
|
||||
import com.intellij.openapi.vfs.*
|
||||
import org.jetbrains.konan.KotlinNativeToolchain
|
||||
import org.jetbrains.konan.settings.KonanModelProvider.RELOAD_TOPIC
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.nio.file.Path
|
||||
|
||||
private const val LINK_DATA: String = "linkdata"
|
||||
|
||||
abstract class KonanProjectComponent(val project: Project) : ProjectComponent {
|
||||
companion object {
|
||||
fun getInstance(project: Project): KonanProjectComponent = project.getComponent(KonanProjectComponent::class.java)
|
||||
}
|
||||
|
||||
protected var libraryPaths: Set<String> = emptySet()
|
||||
|
||||
override fun getComponentName(): String = "Kotlin/Native Project component"
|
||||
|
||||
override fun projectOpened() {
|
||||
VirtualFileManager.getInstance().addVirtualFileListener(object : VirtualFileListener {
|
||||
override fun fileCreated(event: VirtualFileEvent) {
|
||||
val filePath = event.file.path
|
||||
if (libraryPaths.contains(filePath)) reloadLibraries()
|
||||
}
|
||||
}, project)
|
||||
|
||||
val connection = project.messageBus.connect(project)
|
||||
connection.subscribe(RELOAD_TOPIC, Runnable {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
KotlinNativeToolchain.BUNDLED.ensureExists(project)
|
||||
reloadLibraries()
|
||||
}
|
||||
})
|
||||
|
||||
if (looksLikeKotlinNativeProject()) {
|
||||
reloadLibraries()
|
||||
}
|
||||
}
|
||||
|
||||
open fun reloadLibraries(): Unit = synchronized(this) {
|
||||
val libraryPaths: Set<Path> = collectLibraryPaths()
|
||||
this.libraryPaths = libraryPaths.asSequence().map(Path::toString).toSet()
|
||||
|
||||
// for (konanModelProvider in KonanModelProvider.EP_NAME.extensions) {
|
||||
// if (konanModelProvider.reloadLibraries(project, libraryPaths)) return
|
||||
// }
|
||||
|
||||
val module = ModuleManager.getInstance(project).modules.firstOrNull() ?: return
|
||||
val modifiableModel = ModuleRootManager.getInstance(module).modifiableModel
|
||||
val libraryTable: LibraryTable = modifiableModel.moduleLibraryTable
|
||||
libraryTable.libraries.forEach { libraryTable.removeLibrary(it) }
|
||||
|
||||
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||
val jarFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JAR_PROTOCOL)
|
||||
|
||||
for (path: Path in libraryPaths) {
|
||||
|
||||
fun createLibrary(vfs: VirtualFileSystem, linkDataPath: String) {
|
||||
val linkData = vfs.refreshAndFindFileByPath(linkDataPath) ?: return
|
||||
|
||||
val library = libraryTable.createLibrary(path.fileName.toString())
|
||||
val libraryModifiableModel = library.modifiableModel
|
||||
|
||||
libraryModifiableModel.addRoot(linkData, OrderRootType.CLASSES)
|
||||
|
||||
runWriteAction {
|
||||
libraryModifiableModel.commit()
|
||||
}
|
||||
}
|
||||
|
||||
val libraryRootPath = path.toString()
|
||||
val libraryRoot: VirtualFile = localFileSystem.refreshAndFindFileByPath(libraryRootPath) ?: continue
|
||||
|
||||
if (libraryRoot.isDirectory) {
|
||||
createLibrary(localFileSystem, "$libraryRootPath/$LINK_DATA")
|
||||
}
|
||||
else { //zip
|
||||
createLibrary(jarFileSystem, "$libraryRootPath!/$LINK_DATA")
|
||||
}
|
||||
}
|
||||
|
||||
runWriteAction {
|
||||
modifiableModel.commit()
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun collectLibraryPaths(): MutableSet<Path> {
|
||||
val konanPaths = KonanPaths.getInstance(project)
|
||||
return mutableSetOf<Path>().apply {
|
||||
addIfNotNull(konanPaths.konanStdlib())
|
||||
addAll(konanPaths.konanPlatformLibraries())
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun looksLikeKotlinNativeProject(): Boolean
|
||||
}
|
||||
@@ -78,4 +78,31 @@
|
||||
|
||||
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
|
||||
</extensions>
|
||||
|
||||
<!-- NATIVE PART -->
|
||||
<application-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.konan.gradle.internal.KotlinNativeIdeInitializer</implementation-class>
|
||||
</component>
|
||||
</application-components>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<interface-class>org.jetbrains.konan.settings.KonanProjectComponent</interface-class>
|
||||
<implementation-class>org.jetbrains.konan.gradle.GradleKonanProjectComponent</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin.native">
|
||||
<konanModelProvider implementation="org.jetbrains.konan.gradle.GradleKonanModelProvider"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<projectResolve implementation="org.jetbrains.konan.gradle.KonanProjectResolver"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalProjectDataService implementation="org.jetbrains.konan.gradle.KonanProjectDataService"/>
|
||||
</extensions>
|
||||
<!-- /NATIVE PART -->
|
||||
</idea-plugin>
|
||||
|
||||
@@ -10,4 +10,31 @@
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
|
||||
</extensions>
|
||||
|
||||
<!-- NATIVE PART -->
|
||||
<application-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.konan.gradle.internal.KotlinNativeIdeInitializer</implementation-class>
|
||||
</component>
|
||||
</application-components>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<interface-class>org.jetbrains.konan.settings.KonanProjectComponent</interface-class>
|
||||
<implementation-class>org.jetbrains.konan.gradle.GradleKonanProjectComponent</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin.native">
|
||||
<konanModelProvider implementation="org.jetbrains.konan.gradle.GradleKonanModelProvider"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<projectResolve implementation="org.jetbrains.konan.gradle.KonanProjectResolver"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalProjectDataService implementation="org.jetbrains.konan.gradle.KonanProjectDataService"/>
|
||||
</extensions>
|
||||
<!-- /NATIVE PART -->
|
||||
</idea-plugin>
|
||||
|
||||
37
idea/src/META-INF/native.xml
Normal file
37
idea/src/META-INF/native.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<application-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.konan.KonanApplicationComponent</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.konan.analyser.index.KonanDescriptorManager</implementation-class>
|
||||
</component>
|
||||
</application-components>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.konan.settings.KonanPaths</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.native.konanModelProvider" interface="org.jetbrains.konan.settings.KonanModelProvider"/>
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<postStartupActivity implementation="org.jetbrains.konan.SetupKotlinNativeStartupActivity"/>
|
||||
<psi.classFileDecompiler implementation="org.jetbrains.konan.analyser.index.KonanMetadataDecompiler"/>
|
||||
|
||||
<fileType.fileViewProviderFactory filetype="KNM"
|
||||
implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
|
||||
<filetype.stubBuilder filetype="KNM" implementationClass="com.intellij.psi.impl.compiled.ClassFileStubBuilder"/>
|
||||
<filetype.decompiler filetype="KNM" implementationClass="com.intellij.psi.impl.compiled.ClassFileDecompiler"/>
|
||||
<fileTypeFactory implementation="org.jetbrains.konan.analyser.index.KonanMetaFileTypeFactory"/>
|
||||
<fileBasedIndex implementation="org.jetbrains.konan.analyser.index.KonanMetaFileIndex"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<binaryExtension implementation="org.jetbrains.konan.analyser.index.KonanMetaBinary"/>
|
||||
<idePlatformSupport implementation="org.jetbrains.konan.analyser.KonanPlatformSupport" order="first"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -2940,6 +2940,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<!-- CIDR-PLUGIN-EXCLUDE-END -->
|
||||
|
||||
<xi:include href="native.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="tipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="extensions/ide.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
@@ -2939,6 +2939,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<!-- CIDR-PLUGIN-EXCLUDE-END -->
|
||||
|
||||
<xi:include href="native.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="tipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="extensions/ide.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
@@ -2938,6 +2938,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<!-- CIDR-PLUGIN-EXCLUDE-END -->
|
||||
|
||||
<xi:include href="native.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="tipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="extensions/ide.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
@@ -16,13 +16,10 @@
|
||||
|
||||
package example
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
|
||||
class ExampleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
|
||||
@@ -31,12 +28,12 @@ class ExampleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
}
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
println("ExampleSubplugin loaded")
|
||||
return listOf(SubpluginOption("exampleKey", "exampleValue"))
|
||||
|
||||
@@ -18,14 +18,8 @@ package org.jetbrains.kotlin.allopen.gradle
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
|
||||
class AllOpenGradleSubplugin : Plugin<Project> {
|
||||
companion object {
|
||||
@@ -52,12 +46,12 @@ class AllOpenKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
override fun isApplicable(project: Project, task: AbstractCompile) = AllOpenGradleSubplugin.isEnabled(project)
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
if (!AllOpenGradleSubplugin.isEnabled(project)) return emptyList()
|
||||
|
||||
|
||||
@@ -1,12 +1,25 @@
|
||||
plugins {
|
||||
id 'com.github.jk1.tcdeps' version '0.17'
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'jps-compatible'
|
||||
|
||||
def kotlinNativeVersion = "0.9-dev-2798" // TODO: Get from root dir
|
||||
|
||||
configureJvmProject(project)
|
||||
configurePublishing(project)
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
teamcityServer {
|
||||
url = "http://buildserver.labs.intellij.net"
|
||||
credentials {
|
||||
username = "guest"
|
||||
password = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pill {
|
||||
@@ -15,7 +28,8 @@ pill {
|
||||
|
||||
dependencies {
|
||||
compile project(':kotlin-stdlib')
|
||||
|
||||
|
||||
compileOnly tc("Kotlin_KotlinNative_Master_KotlinNativeLinuxDist:$kotlinNativeVersion:shared.jar")
|
||||
compileOnly gradleApi()
|
||||
compileOnly 'com.android.tools.build:gradle:0.4.2'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import groovy.lang.Closure
|
||||
|
||||
interface KotlinDependencyHandler {
|
||||
fun api(dependencyNotation: Any)
|
||||
fun implementation(dependencyNotation: Any)
|
||||
fun compileOnly(dependencyNotation: Any)
|
||||
fun runtimeOnly(dependencyNotation: Any)
|
||||
}
|
||||
|
||||
interface HasKotlinDependencies {
|
||||
fun dependencies(configure: KotlinDependencyHandler.() -> Unit)
|
||||
fun dependencies(configureClosure: Closure<Any?>)
|
||||
|
||||
val apiConfigurationName: String
|
||||
val implementationConfigurationName: String
|
||||
val compileOnlyConfigurationName: String
|
||||
val runtimeOnlyConfigurationName: String
|
||||
|
||||
val relatedConfigurationNames: List<String>
|
||||
get() = listOf(apiConfigurationName, implementationConfigurationName, compileOnlyConfigurationName, runtimeOnlyConfigurationName)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.attributes.HasAttributes
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
|
||||
interface KotlinCompilation: Named, HasAttributes, HasKotlinDependencies {
|
||||
val target: KotlinTarget
|
||||
|
||||
val compilationName: String
|
||||
|
||||
val kotlinSourceSets: List<KotlinSourceSet>
|
||||
|
||||
val compileDependencyConfigurationName: String
|
||||
|
||||
var compileDependencyFiles: FileCollection
|
||||
|
||||
val output: SourceSetOutput
|
||||
|
||||
val platformType get() = target.platformType
|
||||
|
||||
val compileKotlinTaskName: String
|
||||
|
||||
val compileAllTaskName: String
|
||||
|
||||
companion object {
|
||||
const val MAIN_COMPILATION_NAME = "main"
|
||||
const val TEST_COMPILATION_NAME = "test"
|
||||
}
|
||||
|
||||
fun source(sourceSet: KotlinSourceSet)
|
||||
|
||||
override fun getName(): String = compilationName
|
||||
}
|
||||
|
||||
interface KotlinCompilationToRunnableFiles : KotlinCompilation {
|
||||
val runtimeDependencyConfigurationName: String
|
||||
|
||||
var runtimeDependencyFiles: FileCollection
|
||||
}
|
||||
|
||||
interface KotlinCompilationWithResources : KotlinCompilation {
|
||||
val processResourcesTaskName: String
|
||||
}
|
||||
@@ -17,8 +17,8 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import java.io.File
|
||||
|
||||
open class SubpluginOption(val key: String, val value: String)
|
||||
@@ -52,12 +52,12 @@ interface KotlinGradleSubplugin<in KotlinCompile : AbstractCompile> {
|
||||
fun isApplicable(project: Project, task: AbstractCompile): Boolean
|
||||
|
||||
fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption>
|
||||
|
||||
fun getSubpluginKotlinTasks(
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.io.Serializable
|
||||
|
||||
// TODO: Do we really need a separate platform type for each native target?
|
||||
open class KotlinPlatformType(private val name: String) : Named, Serializable {
|
||||
|
||||
override fun toString(): String = name
|
||||
override fun getName(): String = name
|
||||
|
||||
companion object {
|
||||
|
||||
val COMMON = KotlinPlatformType("common")
|
||||
val JVM = KotlinPlatformType("JVM")
|
||||
val JS = KotlinPlatformType("JS")
|
||||
|
||||
val attribute = Attribute.of(
|
||||
"org.jetbrains.kotlin.platform.type",
|
||||
KotlinPlatformType::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make KonanTarget serializable
|
||||
data class KotlinNativePlatformType(val konanTargetName: String) : KotlinPlatformType(konanTargetName) {
|
||||
val konanTarget: KonanTarget
|
||||
get() = HostManager().targetByName(konanTargetName)
|
||||
}
|
||||
|
||||
fun KonanTarget.toKotlinPlatformType(): KotlinNativePlatformType = KotlinNativePlatformType(name)
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.attributes.HasAttributes
|
||||
import org.gradle.api.internal.component.UsageContext
|
||||
|
||||
interface KotlinTarget: Named, HasAttributes {
|
||||
val targetName: String
|
||||
val disambiguationClassifier: String? get() = targetName
|
||||
|
||||
val platformType: KotlinPlatformType
|
||||
|
||||
val compilations: NamedDomainObjectContainer<out KotlinCompilation>
|
||||
|
||||
val project: Project
|
||||
|
||||
val artifactsTaskName: String
|
||||
|
||||
val defaultConfigurationName: String
|
||||
val apiElementsConfigurationName: String
|
||||
val runtimeElementsConfigurationName: String
|
||||
|
||||
fun createUsageContexts(): Set<UsageContext>
|
||||
|
||||
override fun getName(): String = targetName
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Named
|
||||
|
||||
interface KotlinTargetPreset<T: KotlinTarget> : Named {
|
||||
fun createTarget(name: String): T
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.source
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
|
||||
|
||||
interface KotlinSourceSet : Named, HasKotlinDependencies {
|
||||
val kotlin: SourceDirectorySet
|
||||
|
||||
fun kotlin(configureClosure: Closure<Any?>): SourceDirectorySet
|
||||
|
||||
companion object {
|
||||
const val COMMON_MAIN_SOURCE_SET_NAME = "commonMain"
|
||||
const val COMMON_TEST_SOURCE_SET_NAME = "commonTest"
|
||||
}
|
||||
}
|
||||
|
||||
interface KotlinSourceSetWithResources : KotlinSourceSet {
|
||||
val resources: SourceDirectorySet
|
||||
}
|
||||
@@ -1,10 +1,3 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'java-gradle-plugin'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'org.jetbrains.dokka'
|
||||
apply plugin: 'jps-compatible'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
@@ -14,6 +7,17 @@ buildscript {
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.github.jk1.tcdeps' version '0.17'
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'java-gradle-plugin'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'org.jetbrains.dokka'
|
||||
apply plugin: 'jps-compatible'
|
||||
|
||||
configureJvmProject(project)
|
||||
configurePublishing(project)
|
||||
|
||||
@@ -21,6 +25,14 @@ repositories {
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
maven { url 'https://maven.google.com' }
|
||||
|
||||
teamcityServer {
|
||||
url = "http://buildserver.labs.intellij.net"
|
||||
credentials {
|
||||
username = "guest"
|
||||
password = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
@@ -31,8 +43,12 @@ pill {
|
||||
variant = "FULL"
|
||||
}
|
||||
|
||||
def kotlinNativeVersion = "0.9-dev-2798" // TODO: Get from root dir
|
||||
|
||||
dependencies {
|
||||
compile project(':kotlin-gradle-plugin-api')
|
||||
|
||||
compileOnly tc("Kotlin_KotlinNative_Master_KotlinNativeLinuxDist:$kotlinNativeVersion:shared.jar")
|
||||
compileOnly project(':compiler')
|
||||
compileOnly project(':compiler:incremental-compilation-impl')
|
||||
compileOnly project(':compiler:daemon-common')
|
||||
|
||||
@@ -11,6 +11,8 @@ import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.internal.KaptTask
|
||||
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
|
||||
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
|
||||
import org.jetbrains.kotlin.gradle.plugin.base.usesPlatformOf
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import java.io.File
|
||||
|
||||
@@ -36,13 +38,15 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
|
||||
}
|
||||
}
|
||||
|
||||
override fun wireKotlinTasks(project: Project,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: BaseVariant,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile) {
|
||||
|
||||
override fun wireKotlinTasks(
|
||||
project: Project,
|
||||
compilation: KotlinJvmAndroidCompilation,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: BaseVariant,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile
|
||||
) {
|
||||
val preJavaKotlinOutputFiles = mutableListOf<File>().apply {
|
||||
add(kotlinTask.destinationDir)
|
||||
if (Kapt3GradleSubplugin.isEnabled(project)) {
|
||||
@@ -57,8 +61,9 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
|
||||
kotlinTask.dependsOn(variantData.getSourceFolders(SourceKind.JAVA))
|
||||
|
||||
kotlinTask.mapClasspath {
|
||||
val kotlinCompilationDependencies = compilation.compileDependencyFiles
|
||||
val kotlinClasspath = variantData.getCompileClasspath(preJavaClasspathKey)
|
||||
kotlinClasspath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt))
|
||||
kotlinClasspath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt)) + kotlinCompilationDependencies
|
||||
}
|
||||
|
||||
// Find the classpath entries that comes from the tested variant and register it as the friend path, lazily
|
||||
@@ -95,6 +100,11 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
|
||||
return variantData.mergeResources?.computeResourceSetList0() ?: emptyList()
|
||||
}
|
||||
|
||||
override fun setUpDependencyResolution(variant: BaseVariant, compilation: KotlinCompilation) {
|
||||
variant.compileConfiguration.usesPlatformOf(compilation.target)
|
||||
variant.runtimeConfiguration.usesPlatformOf(compilation.target)
|
||||
}
|
||||
|
||||
private inner class KaptVariant(variantData: BaseVariant) : KaptVariantData<BaseVariant>(variantData) {
|
||||
override val name: String = getVariantName(variantData)
|
||||
override val sourceProviders: Iterable<SourceProvider> = getSourceProviders(variantData)
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
|
||||
internal enum class KotlinNativeProjectProperty(val propertyName: String) {
|
||||
KONAN_HOME ("konan.home"),
|
||||
KONAN_JVM_ARGS ("konan.jvmArgs"),
|
||||
KONAN_USE_ENVIRONMENT_VARIABLES("konan.useEnvironmentVariables"),
|
||||
DOWNLOAD_COMPILER ("download.compiler"),
|
||||
|
||||
// Properties used instead of env vars until https://github.com/gradle/gradle/issues/3468 is fixed.
|
||||
// TODO: Remove them when an API for env vars is provided.
|
||||
KONAN_CONFIGURATION_BUILD_DIR ("konan.configuration.build.dir"),
|
||||
KONAN_DEBUGGING_SYMBOLS ("konan.debugging.symbols"),
|
||||
KONAN_OPTIMIZATIONS_ENABLE ("konan.optimizations.enable"),
|
||||
KONAN_PUBLICATION_ENABLED ("konan.publication.enabled")
|
||||
}
|
||||
|
||||
internal fun Project.hasProperty(property: KotlinNativeProjectProperty) = hasProperty(property.propertyName)
|
||||
internal fun Project.findProperty(property: KotlinNativeProjectProperty): Any? = findProperty(property.propertyName)
|
||||
|
||||
internal fun Project.getProperty(property: KotlinNativeProjectProperty) = findProperty(property)
|
||||
?: throw IllegalArgumentException("No such property in the project: ${property.propertyName}")
|
||||
|
||||
internal val Project.jvmArgs
|
||||
get() = (findProperty(KotlinNativeProjectProperty.KONAN_JVM_ARGS) as String?)?.split("\\s+".toRegex()).orEmpty()
|
||||
|
||||
// konanHome extension is set by downloadKonanCompiler task.
|
||||
internal val Project.konanHome: String
|
||||
get() {
|
||||
assert(hasProperty(KotlinNativeProjectProperty.KONAN_HOME))
|
||||
return project.file(getProperty(KotlinNativeProjectProperty.KONAN_HOME)).canonicalPath
|
||||
}
|
||||
|
||||
internal interface KonanToolRunner: Named {
|
||||
val mainClass: String
|
||||
val classpath: FileCollection
|
||||
val jvmArgs: List<String>
|
||||
val environment: Map<String, Any>
|
||||
val additionalSystemProperties: Map<String, String>
|
||||
|
||||
fun run(args: List<String>)
|
||||
fun run(vararg args: String) = run(args.toList())
|
||||
}
|
||||
|
||||
internal abstract class KonanCliRunner(
|
||||
val toolName: String,
|
||||
val fullName: String,
|
||||
val project: Project,
|
||||
private val additionalJvmArgs: List<String>
|
||||
): KonanToolRunner {
|
||||
override val mainClass = "org.jetbrains.kotlin.cli.utilities.MainKt"
|
||||
|
||||
override fun getName() = toolName
|
||||
|
||||
// We need to unset some environment variables which are set by XCode and may potentially affect the tool executed.
|
||||
protected val blacklistEnvironment: List<String> by lazy {
|
||||
KonanToolRunner::class.java.getResourceAsStream("/env_blacklist")?.let { stream ->
|
||||
stream.reader().use { it.readLines() }
|
||||
} ?: emptyList<String>()
|
||||
}
|
||||
|
||||
override val classpath: FileCollection =
|
||||
project.fileTree("${project.konanHome}/konan/lib/")
|
||||
.apply { include("*.jar") }
|
||||
|
||||
override val jvmArgs = mutableListOf("-ea").apply {
|
||||
if (additionalJvmArgs.none { it.startsWith("-Xmx") } &&
|
||||
project.jvmArgs.none { it.startsWith("-Xmx") }) {
|
||||
add("-Xmx3G")
|
||||
}
|
||||
addAll(additionalJvmArgs)
|
||||
addAll(project.jvmArgs)
|
||||
}
|
||||
|
||||
override val additionalSystemProperties = mutableMapOf(
|
||||
"konan.home" to project.konanHome,
|
||||
"java.library.path" to "${project.konanHome}/konan/nativelib"
|
||||
)
|
||||
|
||||
override val environment = mutableMapOf("LIBCLANG_DISABLE_CRASH_RECOVERY" to "1")
|
||||
|
||||
override fun run(args: List<String>) {
|
||||
project.logger.info("Run tool: $toolName with args: ${args.joinToString(separator = " ")}")
|
||||
if (classpath.isEmpty) {
|
||||
throw IllegalStateException("Classpath of the tool is empty: $toolName\n" +
|
||||
"Probably the 'konan.home' project property contains an incorrect path.\n" +
|
||||
"Please change it to the compiler root directory and rerun the build.")
|
||||
}
|
||||
|
||||
project.javaexec { spec ->
|
||||
spec.main = mainClass
|
||||
spec.classpath = classpath
|
||||
spec.jvmArgs(jvmArgs)
|
||||
spec.systemProperties(System.getProperties().map { (k, v) -> k.toString() to v }.toMap())
|
||||
spec.systemProperties(additionalSystemProperties)
|
||||
spec.args(listOf(toolName) + args)
|
||||
blacklistEnvironment.forEach { spec.environment.remove(it) }
|
||||
spec.environment(environment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class KonanInteropRunner(project: Project, additionalJvmArgs: List<String> = emptyList())
|
||||
: KonanCliRunner("cinterop", "Kotlin/Native cinterop tool", project, additionalJvmArgs)
|
||||
{
|
||||
init {
|
||||
if (HostManager.host == KonanTarget.MINGW_X64) {
|
||||
//TODO: Oh-ho-ho fix it in more convinient way.
|
||||
environment.put("PATH", DependencyProcessor.defaultDependenciesRoot.absolutePath +
|
||||
"\\msys2-mingw-w64-x86_64-gcc-7.2.0-clang-llvm-5.0.0-windows-x86-64" +
|
||||
"\\bin;${environment.get("PATH")}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class KonanCompilerRunner(project: Project, additionalJvmArgs: List<String> = emptyList())
|
||||
: KonanCliRunner("konanc", "Kotlin/Native compiler", project, additionalJvmArgs)
|
||||
|
||||
internal class KonanKlibRunner(project: Project, additionalJvmArgs: List<String> = emptyList())
|
||||
: KonanCliRunner("klib", "Klib management tool", project, additionalJvmArgs)
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.dsl
|
||||
|
||||
import org.gradle.api.NamedDomainObjectCollection
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset
|
||||
|
||||
open class KotlinMultiplatformExtension : KotlinProjectExtension() {
|
||||
lateinit var presets: NamedDomainObjectCollection<KotlinTargetPreset<*>>
|
||||
internal set
|
||||
|
||||
lateinit var targets: NamedDomainObjectCollection<KotlinTarget>
|
||||
internal set
|
||||
}
|
||||
@@ -16,21 +16,40 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.dsl
|
||||
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.plugins.DslObject
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
internal fun Project.createKotlinExtension(extensionClass: KClass<out KotlinProjectExtension>) {
|
||||
val kotlinExt = extensions.create("kotlin", extensionClass.java)
|
||||
private const val KOTLIN_PROJECT_EXTENSION_NAME = "kotlin"
|
||||
|
||||
internal fun Project.createKotlinExtension(extensionClass: KClass<out KotlinProjectExtension>): KotlinProjectExtension {
|
||||
val kotlinExt = extensions.create(KOTLIN_PROJECT_EXTENSION_NAME, extensionClass.java)
|
||||
DslObject(kotlinExt).extensions.create("experimental", ExperimentalExtension::class.java)
|
||||
return kotlinExtension
|
||||
}
|
||||
|
||||
internal val Project.kotlinExtension: KotlinProjectExtension
|
||||
get() = extensions.getByName(KOTLIN_PROJECT_EXTENSION_NAME) as KotlinProjectExtension
|
||||
|
||||
open class KotlinProjectExtension {
|
||||
val experimental: ExperimentalExtension
|
||||
get() = DslObject(this).extensions.getByType(ExperimentalExtension::class.java)!!
|
||||
get() = DslObject(this).extensions.getByType(ExperimentalExtension::class.java)
|
||||
|
||||
var sourceSets: NamedDomainObjectContainer<out KotlinSourceSet>
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
get() = DslObject(this).extensions.getByName("sourceSets") as NamedDomainObjectContainer<out KotlinSourceSet>
|
||||
internal set(value) { DslObject(this).extensions.add("sourceSets", value) }
|
||||
}
|
||||
|
||||
open class KotlinJvmProjectExtension : KotlinProjectExtension() {
|
||||
open class KotlinSingleTargetProjectExtension : KotlinProjectExtension() {
|
||||
internal lateinit var target: KotlinTarget
|
||||
}
|
||||
|
||||
open class KotlinJvmProjectExtension : KotlinSingleTargetProjectExtension() {
|
||||
/**
|
||||
* With Gradle 4.0+, disables the separate output directory for Kotlin, falling back to sharing the deprecated
|
||||
* single classes directory per source set. With Gradle < 4.0, has no effect.
|
||||
@@ -38,6 +57,11 @@ open class KotlinJvmProjectExtension : KotlinProjectExtension() {
|
||||
var copyClassesToJavaOutput = false
|
||||
}
|
||||
|
||||
internal val KotlinProjectExtension.sourceSetProvider
|
||||
get() = object : KotlinSourceSetProvider {
|
||||
override fun provideSourceSet(displayName: String): KotlinSourceSet = sourceSets.maybeCreate(displayName)
|
||||
}
|
||||
|
||||
open class ExperimentalExtension {
|
||||
var coroutines: Coroutines? = null
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.android.build.gradle.internal.variant.TestVariantData
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.UnknownDomainObjectException
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
@@ -81,12 +80,12 @@ class AndroidSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
}
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
val androidExtension = project.extensions.getByName("android") as? BaseExtension ?: return emptyList()
|
||||
val androidExtensionsExtension = project.extensions.getByType(AndroidExtensionsExtension::class.java)
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.gradle.internal
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.internal.file.DefaultSourceDirectorySet
|
||||
import org.gradle.api.internal.file.FileResolver
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetProvider
|
||||
import java.lang.reflect.Constructor
|
||||
|
||||
internal class KotlinSourceSetProviderImpl constructor(private val fileResolver: FileResolver) : KotlinSourceSetProvider {
|
||||
override fun create(displayName: String): KotlinSourceSet =
|
||||
KotlinSourceSetImpl(displayName, fileResolver)
|
||||
}
|
||||
|
||||
private class KotlinSourceSetImpl(displayName: String, resolver: FileResolver) : KotlinSourceSet {
|
||||
override val kotlin: SourceDirectorySet =
|
||||
createDefaultSourceDirectorySet(displayName + " Kotlin source", resolver)
|
||||
|
||||
init {
|
||||
kotlin.filter?.include("**/*.java", "**/*.kt", "**/*.kts")
|
||||
}
|
||||
|
||||
override fun kotlin(configureClosure: Closure<Any?>?): KotlinSourceSet {
|
||||
ConfigureUtil.configure(configureClosure, kotlin)
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
private val createDefaultSourceDirectorySet: (name: String?, resolver: FileResolver?) -> SourceDirectorySet = run {
|
||||
val klass = DefaultSourceDirectorySet::class.java
|
||||
val defaultConstructor = klass.constructorOrNull(String::class.java, FileResolver::class.java)
|
||||
|
||||
if (defaultConstructor != null && defaultConstructor.getAnnotation(java.lang.Deprecated::class.java) == null) {
|
||||
// TODO: drop when gradle < 2.12 are obsolete
|
||||
{ name, resolver -> defaultConstructor.newInstance(name, resolver) }
|
||||
}
|
||||
else {
|
||||
val directoryFileTreeFactoryClass = Class.forName("org.gradle.api.internal.file.collections.DirectoryFileTreeFactory")
|
||||
val alternativeConstructor = klass.getConstructor(String::class.java, FileResolver::class.java, directoryFileTreeFactoryClass)
|
||||
|
||||
val defaultFileTreeFactoryClass = Class.forName("org.gradle.api.internal.file.collections.DefaultDirectoryFileTreeFactory")
|
||||
val defaultFileTreeFactory = defaultFileTreeFactoryClass.getConstructor().newInstance()
|
||||
return@run { name, resolver -> alternativeConstructor.newInstance(name, resolver, defaultFileTreeFactory) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> Class<T>.constructorOrNull(vararg parameterTypes: Class<*>): Constructor<T>? =
|
||||
try {
|
||||
getConstructor(*parameterTypes)
|
||||
}
|
||||
catch (e: NoSuchMethodException) {
|
||||
null
|
||||
}
|
||||
@@ -139,10 +139,10 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
private inner class Kapt3SubpluginContext(
|
||||
val project: Project,
|
||||
val kotlinCompile: KotlinCompile,
|
||||
val javaCompile: AbstractCompile,
|
||||
val javaCompile: AbstractCompile?,
|
||||
val kaptVariantData: KaptVariantData<*>?,
|
||||
val sourceSetName: String,
|
||||
val javaSourceSet: SourceSet?,
|
||||
val kotlinCompilation: KotlinCompilation?,
|
||||
val kaptExtension: KaptExtension,
|
||||
val kaptClasspathConfigurations: List<Configuration>
|
||||
) {
|
||||
@@ -152,14 +152,14 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
}
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: KotlinCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
assert((variantData != null) xor (javaSourceSet != null))
|
||||
assert((variantData != null) xor (kotlinCompilation != null))
|
||||
|
||||
val buildDependencies = arrayListOf<TaskDependency>()
|
||||
val kaptConfigurations = arrayListOf<Configuration>()
|
||||
@@ -181,10 +181,10 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
kaptVariantData.name
|
||||
}
|
||||
else {
|
||||
if (javaSourceSet == null) error("Java source set should not be null")
|
||||
if (kotlinCompilation == null) error("Java source set should not be null")
|
||||
|
||||
handleSourceSet(javaSourceSet.name)
|
||||
javaSourceSet.name
|
||||
handleSourceSet(kotlinCompilation.compilationName)
|
||||
kotlinCompilation.compilationName
|
||||
}
|
||||
|
||||
val kaptExtension = project.extensions.getByType(KaptExtension::class.java)
|
||||
@@ -193,7 +193,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
|
||||
val context = Kapt3SubpluginContext(
|
||||
project, kotlinCompile, javaCompile,
|
||||
kaptVariantData, sourceSetName, javaSourceSet, kaptExtension, nonEmptyKaptConfigurations
|
||||
kaptVariantData, sourceSetName, kotlinCompilation, kaptExtension, nonEmptyKaptConfigurations
|
||||
)
|
||||
|
||||
val kaptGenerateStubsTask = context.createKaptGenerateStubsTask()
|
||||
@@ -226,7 +226,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
pluginOptions += SubpluginOption("aptMode", aptMode)
|
||||
disableAnnotationProcessingInJavaTask()
|
||||
|
||||
javaCompile.source(generatedFilesDir)
|
||||
javaCompile?.source(generatedFilesDir)
|
||||
|
||||
pluginOptions += FilesSubpluginOption("sources", listOf(generatedFilesDir))
|
||||
pluginOptions += FilesSubpluginOption("classes", listOf(getKaptGeneratedClassesDir(project, sourceSetName)))
|
||||
@@ -342,18 +342,22 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
kaptTask.kotlinSourcesDestinationDir = kotlinSourcesOutputDir
|
||||
kaptTask.classesDir = classesOutputDir
|
||||
|
||||
javaSourceSet?.output?.apply {
|
||||
if (tryAddClassesDir { project.files(classesOutputDir).builtBy(kaptTask) }) {
|
||||
kotlinCompile.attachClassesDir { classesOutputDir }
|
||||
kotlinCompilation?.run {
|
||||
output.apply {
|
||||
if (tryAddClassesDir { project.files(classesOutputDir).builtBy(kaptTask) }) {
|
||||
kotlinCompile.attachClassesDir { classesOutputDir }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kotlinCompile.source(sourcesOutputDir, kotlinSourcesOutputDir)
|
||||
|
||||
if (kaptVariantData != null) {
|
||||
kaptVariantData.registerGeneratedJavaSource(project, kaptTask, javaCompile)
|
||||
} else {
|
||||
registerGeneratedJavaSource(kaptTask, javaCompile)
|
||||
if (javaCompile != null) {
|
||||
if (kaptVariantData != null) {
|
||||
kaptVariantData.registerGeneratedJavaSource(project, kaptTask, javaCompile)
|
||||
} else {
|
||||
registerGeneratedJavaSource(kaptTask, javaCompile)
|
||||
}
|
||||
}
|
||||
|
||||
kaptTask.kaptClasspathConfigurations = kaptClasspathConfigurations
|
||||
|
||||
@@ -131,7 +131,7 @@ open class KaptJavacOptionsDelegate {
|
||||
fun execute(closure: Closure<*>) = executeClosure(closure)
|
||||
}
|
||||
|
||||
private fun Any?.executeClosure(closure: Closure<*>) {
|
||||
internal fun Any?.executeClosure(closure: Closure<*>) {
|
||||
closure.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
closure.delegate = this
|
||||
closure.call()
|
||||
|
||||
@@ -21,10 +21,10 @@ import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.matchSymmetricallyByNames
|
||||
|
||||
abstract class KotlinPlatformPluginBase(protected val platformName: String) : Plugin<Project> {
|
||||
companion object {
|
||||
@@ -110,70 +110,65 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin
|
||||
// Since the two projects may add source sets in arbitrary order, and both may do that after the plugin is applied,
|
||||
// we need to handle all source sets of the two projects and connect them once we get a match:
|
||||
// todo warn if no match found
|
||||
matchSymmetricallyByNames(commonProject.sourceSets, namedSourceSetsContainer(platformProject)) { commonSourceSet, _ ->
|
||||
matchSymmetricallyByNames(
|
||||
getKotlinSourceSetsSafe(commonProject),
|
||||
namedSourceSetsContainer(platformProject)
|
||||
) { commonSourceSet: Named, _ ->
|
||||
addCommonSourceSetToPlatformSourceSet(commonSourceSet, platformProject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies [whenMatched] to pairs of items with the same name in [containerA] and [containerB],
|
||||
* regardless of the order in which they are added to the containers.
|
||||
*/
|
||||
private fun <A, B> matchSymmetricallyByNames(
|
||||
containerA: NamedDomainObjectContainer<A>,
|
||||
containerB: NamedDomainObjectContainer<B>,
|
||||
whenMatched: (A, B) -> Unit
|
||||
) {
|
||||
val matchedNames = mutableSetOf<String>()
|
||||
|
||||
fun <T, R> NamedDomainObjectContainer<T>.matchAllWith(other: NamedDomainObjectContainer<R>, match: (T, R) -> Unit) {
|
||||
this@matchAllWith.all { item ->
|
||||
val itemName = this@matchAllWith.namer.determineName(item)
|
||||
if (itemName !in matchedNames) {
|
||||
val otherItem = other.findByName(itemName)
|
||||
if (otherItem != null) {
|
||||
matchedNames += itemName
|
||||
match(item, otherItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
containerA.matchAllWith(containerB) { a, b -> whenMatched(a, b) }
|
||||
containerB.matchAllWith(containerA) { b, a -> whenMatched(a, b) }
|
||||
}
|
||||
|
||||
protected open fun namedSourceSetsContainer(project: Project): NamedDomainObjectContainer<*> =
|
||||
project.sourceSets
|
||||
project.kotlinExtension.sourceSets
|
||||
|
||||
protected open fun addCommonSourceSetToPlatformSourceSet(commonSourceSet: SourceSet, platformProject: Project) {
|
||||
protected open fun addCommonSourceSetToPlatformSourceSet(commonSourceSet: Named, platformProject: Project) {
|
||||
val platformTask = platformProject.tasks
|
||||
.filterIsInstance<AbstractKotlinCompile<*>>()
|
||||
.firstOrNull { it.sourceSetName == commonSourceSet.name }
|
||||
|
||||
platformTask?.source(commonSourceSet.kotlin!!)
|
||||
platformTask?.source(getKotlinSourceDirectorySetSafe(commonSourceSet))
|
||||
}
|
||||
|
||||
protected val SourceSet.kotlin: SourceDirectorySet?
|
||||
get() {
|
||||
// Access through reflection, because another project's KotlinSourceSet might be loaded
|
||||
// by a different class loader:
|
||||
val convention = (getConvention("kotlin") ?: getConvention("kotlin2js")) ?: return null
|
||||
val kotlinSourceSetIface = convention.javaClass.interfaces.find { it.name == KotlinSourceSet::class.qualifiedName }
|
||||
val getKotlin = kotlinSourceSetIface?.methods?.find { it.name == "getKotlin" } ?: return null
|
||||
return getKotlin(convention) as? SourceDirectorySet
|
||||
private fun getKotlinSourceSetsSafe(project: Project): NamedDomainObjectCollection<out Named> {
|
||||
// Access through reflection, because another project's KotlinBaseSourceSet might be loaded
|
||||
// by a different class loader:
|
||||
val kotlinExt = project.extensions.getByName("kotlin")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val sourceSets = kotlinExt.javaClass.getMethod("getSourceSets").invoke(kotlinExt) as NamedDomainObjectCollection<out Named>
|
||||
return sourceSets
|
||||
}
|
||||
|
||||
protected fun getKotlinSourceDirectorySetSafe(from: Any): SourceDirectorySet? {
|
||||
// Access through reflection, because another project's KotlinBaseSourceSet might be loaded
|
||||
// by a different class loader:
|
||||
fun getImplementedKotlinSourceSetInterface(from: Any): Class<*>? {
|
||||
fun findImplementedInterface(name: String, derivedClass: Class<*>): Class<*>? {
|
||||
if (derivedClass.canonicalName == name)
|
||||
return derivedClass
|
||||
else {
|
||||
for (parentInterface in derivedClass.interfaces + derivedClass.superclass) {
|
||||
findImplementedInterface(name, parentInterface)?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return findImplementedInterface(KotlinSourceSet::class.qualifiedName!!, from.javaClass)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
protected fun <T> Project.whenEvaluated(fn: Project.() -> T) {
|
||||
if (state.executed) {
|
||||
fn()
|
||||
}
|
||||
else {
|
||||
afterEvaluate { it.fn() }
|
||||
}
|
||||
}
|
||||
val getKotlin = from.javaClass.getMethod("getKotlin")
|
||||
return getKotlin(from) as? SourceDirectorySet
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> Project.whenEvaluated(fn: Project.() -> T) {
|
||||
if (state.executed) {
|
||||
fn()
|
||||
}
|
||||
else {
|
||||
afterEvaluate { it.fn() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,11 +185,12 @@ open class KotlinPlatformAndroidPlugin : KotlinPlatformImplementationPluginBase(
|
||||
override fun namedSourceSetsContainer(project: Project): NamedDomainObjectContainer<*> =
|
||||
(project.extensions.getByName("android") as BaseExtension).sourceSets
|
||||
|
||||
override fun addCommonSourceSetToPlatformSourceSet(commonSourceSet: SourceSet, platformProject: Project) {
|
||||
override fun addCommonSourceSetToPlatformSourceSet(commonSourceSet: Named, platformProject: Project) {
|
||||
val androidExtension = platformProject.extensions.getByName("android") as BaseExtension
|
||||
val androidSourceSet = androidExtension.sourceSets.findByName(commonSourceSet.name) ?: return
|
||||
val kotlinSourceSet = androidSourceSet.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: return
|
||||
kotlinSourceSet.kotlin.source(commonSourceSet.kotlin!!)
|
||||
val kotlinSourceSet = androidSourceSet.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet
|
||||
?: return
|
||||
kotlinSourceSet.kotlin.source(getKotlinSourceDirectorySetSafe(commonSourceSet)!!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +206,4 @@ open class KotlinPlatformJsPlugin : KotlinPlatformImplementationPluginBase("js")
|
||||
project.applyPlugin<Kotlin2JsPluginWrapper>()
|
||||
super.apply(project)
|
||||
}
|
||||
}
|
||||
|
||||
private val Project.sourceSets: SourceSetContainer
|
||||
get() = convention.getPlugin(JavaPluginConvention::class.java).sourceSets
|
||||
}
|
||||
@@ -3,9 +3,9 @@ package org.jetbrains.kotlin.gradle.plugin
|
||||
import com.android.build.gradle.BaseExtension
|
||||
import com.android.build.gradle.BasePlugin
|
||||
import com.android.builder.model.SourceProvider
|
||||
import com.intellij.openapi.util.text.StringUtil.compareVersionNumbers
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ExternalDependency
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
@@ -13,7 +13,6 @@ import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.plugins.InvalidPluginException
|
||||
import org.gradle.api.plugins.JavaBasePlugin
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.CompileClasspathNormalizer
|
||||
@@ -25,10 +24,15 @@ import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.sourceSetProvider
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.getKaptGeneratedClassesDir
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
|
||||
import org.jetbrains.kotlin.gradle.internal.checkAndroidAnnotationProcessorDependencyUsage
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
@@ -45,58 +49,90 @@ val KOTLIN_JS_DSL_NAME = "kotlin2js"
|
||||
val KOTLIN_OPTIONS_DSL_NAME = "kotlinOptions"
|
||||
|
||||
internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
val project: Project,
|
||||
val javaBasePlugin: JavaBasePlugin,
|
||||
val sourceSet: SourceSet,
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
val kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
val dslExtensionName: String,
|
||||
val compileTaskNameSuffix: String,
|
||||
val taskDescription: String
|
||||
val project: Project,
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
val taskDescription: String,
|
||||
val kotlinCompilation: KotlinCompilation
|
||||
) {
|
||||
abstract protected fun doTargetSpecificProcessing()
|
||||
protected val logger = Logging.getLogger(this.javaClass)!!
|
||||
|
||||
protected val isSeparateClassesDirSupported: Boolean by lazy {
|
||||
!CopyClassesToJavaOutputStatus.isEnabled(project) &&
|
||||
sourceSet.output.javaClass.methods.any { it.name == "getClassesDirs" }
|
||||
kotlinCompilation.output.javaClass.methods.any { it.name == "getClassesDirs" }
|
||||
}
|
||||
|
||||
protected val sourceSetName: String = sourceSet.name
|
||||
protected val sourceRootDir: String = "src/$sourceSetName/kotlin"
|
||||
protected val kotlinSourceSet: KotlinSourceSet = createKotlinSourceSet()
|
||||
protected val sourceSetName: String = kotlinCompilation.compilationName
|
||||
|
||||
protected val kotlinTask: T = createKotlinCompileTask()
|
||||
|
||||
protected open val defaultKotlinDestinationDir: File
|
||||
get() = if (isSeparateClassesDirSupported)
|
||||
File(project.buildDir, "classes/kotlin/${sourceSet.name}") else
|
||||
sourceSet.output.classesDir
|
||||
get() {
|
||||
return if (isSeparateClassesDirSupported) {
|
||||
val kotlinExt = project.kotlinExtension
|
||||
val targetSubDirectory =
|
||||
if (kotlinExt is KotlinSingleTargetProjectExtension)
|
||||
"" // In single-target projects, don't add the target name part to this path
|
||||
else
|
||||
kotlinCompilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||
File(project.buildDir, "classes/kotlin/$targetSubDirectory${kotlinCompilation.compilationName}")
|
||||
} else {
|
||||
kotlinCompilation.output.classesDir
|
||||
}
|
||||
}
|
||||
|
||||
fun run() {
|
||||
addKotlinDirSetToSources()
|
||||
private fun createKotlinCompileTask(): T {
|
||||
val name = kotlinCompilation.compileKotlinTaskName
|
||||
logger.kotlinDebug("Creating kotlin compile task $name")
|
||||
val kotlinCompile = doCreateTask(project, name)
|
||||
kotlinCompile.description = taskDescription
|
||||
kotlinCompile.mapClasspath { kotlinCompilation.compileDependencyFiles }
|
||||
kotlinCompile.setDestinationDir { defaultKotlinDestinationDir }
|
||||
kotlinCompilation.output.tryAddClassesDir { project.files(kotlinTask.destinationDir).builtBy(kotlinTask) }
|
||||
return kotlinCompile
|
||||
}
|
||||
|
||||
open fun run() {
|
||||
doTargetSpecificProcessing()
|
||||
}
|
||||
|
||||
private fun createKotlinSourceSet(): KotlinSourceSet {
|
||||
logger.kotlinDebug("Creating KotlinSourceSet for $sourceSet")
|
||||
val kotlinSourceSet = kotlinSourceSetProvider.create(sourceSet.name)
|
||||
kotlinSourceSet.kotlin.srcDir(project.file(sourceRootDir))
|
||||
sourceSet.addConvention(dslExtensionName, kotlinSourceSet)
|
||||
return kotlinSourceSet
|
||||
protected abstract fun doCreateTask(project: Project, taskName: String): T
|
||||
}
|
||||
|
||||
internal abstract class KotlinJavaSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
project: Project,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
taskDescription: String,
|
||||
val javaSourceSet: SourceSet?,
|
||||
kotlinCompilation: KotlinCompilation
|
||||
): KotlinSourceSetProcessor<T>(
|
||||
project, tasksProvider, taskDescription, kotlinCompilation
|
||||
) {
|
||||
override fun run() {
|
||||
addKotlinDirSetToSources()
|
||||
super.run()
|
||||
}
|
||||
|
||||
private fun addKotlinDirSetToSources() {
|
||||
val kotlinDirSet = kotlinSourceSet.kotlin
|
||||
if (javaSourceSet == null)
|
||||
return
|
||||
|
||||
val kotlinDirSets = kotlinCompilation.kotlinSourceSets.map(KotlinSourceSet::kotlin)
|
||||
|
||||
// Try to avoid duplicate Java sources in allSource:
|
||||
val kotlinSrcDirsToAdd = filterOutJavaSrcDirsIfPossible(kotlinDirSet)
|
||||
val kotlinSrcDirsToAdd = kotlinDirSets.map { filterOutJavaSrcDirsIfPossible(it) }
|
||||
|
||||
sourceSet.allJava.srcDirs(kotlinSrcDirsToAdd)
|
||||
sourceSet.allSource.srcDirs(kotlinSrcDirsToAdd)
|
||||
sourceSet.resources.filter.exclude { it.file in kotlinDirSet }
|
||||
kotlinSrcDirsToAdd.forEach { kotlinSrcDirs ->
|
||||
javaSourceSet.allJava.srcDirs(kotlinSrcDirs)
|
||||
javaSourceSet.allSource.srcDirs(kotlinSrcDirs)
|
||||
javaSourceSet.resources.filter.exclude { it.file in kotlinSrcDirs }
|
||||
}
|
||||
}
|
||||
|
||||
private fun filterOutJavaSrcDirsIfPossible(sourceDirectorySet: SourceDirectorySet): FileCollection {
|
||||
if (javaSourceSet == null)
|
||||
return sourceDirectorySet
|
||||
|
||||
// If the API used below is not available, fall back to not filtering the Java sources.
|
||||
if (SourceDirectorySet::class.java.methods.none { it.name == "getSourceDirectories" }) {
|
||||
return sourceDirectorySet
|
||||
@@ -108,35 +144,19 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
||||
}
|
||||
|
||||
// Build a lazily-resolved file collection that filters out Java sources from sources of this sourceDirectorySet
|
||||
return getSourceDirectories(sourceDirectorySet).minus(getSourceDirectories(sourceSet.java))
|
||||
return getSourceDirectories(sourceDirectorySet).minus(getSourceDirectories(javaSourceSet.java))
|
||||
}
|
||||
|
||||
private fun createKotlinCompileTask(): T {
|
||||
val name = sourceSet.getCompileTaskName(compileTaskNameSuffix)
|
||||
logger.kotlinDebug("Creating kotlin compile task $name")
|
||||
val kotlinCompile = doCreateTask(project, name)
|
||||
kotlinCompile.description = taskDescription
|
||||
kotlinCompile.mapClasspath { sourceSet.compileClasspath }
|
||||
kotlinCompile.setDestinationDir { defaultKotlinDestinationDir }
|
||||
sourceSet.output.tryAddClassesDir { project.files(kotlinTask.destinationDir).builtBy(kotlinTask) }
|
||||
return kotlinCompile
|
||||
}
|
||||
|
||||
protected abstract fun doCreateTask(project: Project, taskName: String): T
|
||||
}
|
||||
|
||||
internal class Kotlin2JvmSourceSetProcessor(
|
||||
project: Project,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
sourceSet: SourceSet,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
) : KotlinSourceSetProcessor<KotlinCompile>(
|
||||
project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider,
|
||||
dslExtensionName = KOTLIN_DSL_NAME,
|
||||
compileTaskNameSuffix = "kotlin",
|
||||
taskDescription = "Compiles the $sourceSet.kotlin."
|
||||
project: Project,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinCompilation: KotlinCompilation,
|
||||
private val kotlinPluginVersion: String
|
||||
) : KotlinJavaSourceSetProcessor<KotlinCompile>(
|
||||
project, tasksProvider, taskDescription = "Compiles the $kotlinCompilation.",
|
||||
javaSourceSet = if (kotlinCompilation is KotlinWithJavaCompilation) kotlinCompilation.javaSourceSet else null,
|
||||
kotlinCompilation = kotlinCompilation
|
||||
) {
|
||||
override val defaultKotlinDestinationDir: File
|
||||
get() = if (!isSeparateClassesDirSupported)
|
||||
@@ -144,44 +164,44 @@ internal class Kotlin2JvmSourceSetProcessor(
|
||||
super.defaultKotlinDestinationDir
|
||||
|
||||
override fun doCreateTask(project: Project, taskName: String): KotlinCompile =
|
||||
tasksProvider.createKotlinJVMTask(project, taskName, sourceSet.name)
|
||||
tasksProvider.createKotlinJVMTask(project, taskName, kotlinCompilation.compilationName)
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
kotlinSourceSet.kotlin.source(sourceSet.java)
|
||||
Kapt3KotlinGradleSubplugin.createAptConfigurationIfNeeded(project, sourceSet.name)
|
||||
Kapt3KotlinGradleSubplugin.createAptConfigurationIfNeeded(project, kotlinCompilation.compilationName)
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
if (project != null) {
|
||||
val javaTask = project.tasks.findByName(sourceSet.compileJavaTaskName)
|
||||
val javaTask = javaSourceSet?.let { project.tasks.findByName(it.compileJavaTaskName) as JavaCompile }
|
||||
|
||||
val subpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, javaTask as JavaCompile, null, null, sourceSet)
|
||||
val subpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, javaTask, null, null, kotlinCompilation
|
||||
)
|
||||
|
||||
// KotlinCompile.source(kotlinDirSet) should be called only after all java roots are added to kotlinDirSet
|
||||
// otherwise some java roots can be ignored
|
||||
kotlinTask.source(kotlinSourceSet.kotlin)
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { it.source(kotlinSourceSet.kotlin) }
|
||||
// KotlinCompile.source(kotlinDirSet) should be called only after all java roots are added to kotlinDirSet
|
||||
// otherwise some java roots can be ignored
|
||||
for (compiledSourceSet in kotlinCompilation.kotlinSourceSets) {
|
||||
kotlinTask.source(compiledSourceSet.kotlin)
|
||||
}
|
||||
|
||||
configureJavaTask(kotlinTask, javaTask, logger)
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { plugin -> kotlinCompilation.kotlinSourceSets.forEach { sourceSet -> plugin.source(sourceSet.kotlin) } }
|
||||
|
||||
var syncOutputTask: SyncOutputTask? = null
|
||||
javaTask?.let { configureJavaTask(kotlinTask, it, logger) }
|
||||
|
||||
if (!isSeparateClassesDirSupported) {
|
||||
syncOutputTask = createSyncOutputTask(project, kotlinTask, javaTask, sourceSetName)
|
||||
}
|
||||
|
||||
if (project.pluginManager.hasPlugin("java-library") && sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) {
|
||||
val (classesProviderTask, classesDirectory) = when {
|
||||
isSeparateClassesDirSupported -> kotlinTask.let { it to it.destinationDir }
|
||||
else -> syncOutputTask!!.let { it to it.javaOutputDir }
|
||||
}
|
||||
|
||||
registerKotlinOutputForJavaLibrary(classesDirectory, classesProviderTask)
|
||||
var syncOutputTask: SyncOutputTask? = null
|
||||
|
||||
if (!isSeparateClassesDirSupported && javaTask != null) {
|
||||
syncOutputTask = createSyncOutputTask(project, kotlinTask, javaTask, sourceSetName)
|
||||
}
|
||||
|
||||
if (project.pluginManager.hasPlugin("java-library") && sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) {
|
||||
val (classesProviderTask, classesDirectory) = when {
|
||||
isSeparateClassesDirSupported -> kotlinTask.let { it to it.destinationDir }
|
||||
else -> syncOutputTask!!.let { it to it.javaOutputDir }
|
||||
}
|
||||
|
||||
registerKotlinOutputForJavaLibrary(classesDirectory, classesProviderTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,37 +251,38 @@ internal fun SourceSetOutput.tryAddClassesDir(
|
||||
}
|
||||
|
||||
internal class Kotlin2JsSourceSetProcessor(
|
||||
project: Project,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
sourceSet: SourceSet,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
project: Project,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinCompilation: KotlinCompilation,
|
||||
private val kotlinPluginVersion: String
|
||||
) : KotlinSourceSetProcessor<Kotlin2JsCompile>(
|
||||
project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider,
|
||||
dslExtensionName = KOTLIN_JS_DSL_NAME,
|
||||
taskDescription = "Compiles the kotlin sources in $sourceSet to JavaScript.",
|
||||
compileTaskNameSuffix = "kotlin2Js"
|
||||
project, tasksProvider, taskDescription = "Compiles the Kotlin sources in $kotlinCompilation to JavaScript.",
|
||||
kotlinCompilation = kotlinCompilation
|
||||
) {
|
||||
override fun doCreateTask(project: Project, taskName: String): Kotlin2JsCompile =
|
||||
tasksProvider.createKotlinJSTask(project, taskName, sourceSet.name)
|
||||
tasksProvider.createKotlinJSTask(project, taskName, kotlinCompilation.compilationName)
|
||||
|
||||
override fun doTargetSpecificProcessing() {
|
||||
project.tasks.findByName(sourceSet.classesTaskName)!!.dependsOn(kotlinTask)
|
||||
kotlinTask.source(kotlinSourceSet.kotlin)
|
||||
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask)
|
||||
|
||||
createCleanSourceMapTask()
|
||||
|
||||
sourceSet.clearJavaSrcDirs()
|
||||
//TODO check for complete removal, as we don't need Java anymore
|
||||
// sourceSet.clearJavaSrcDirs()
|
||||
|
||||
// outputFile can be set later during the configuration phase, get it only after the phase:
|
||||
project.afterEvaluate { project ->
|
||||
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, kotlinTask, null, null, sourceSet)
|
||||
|
||||
kotlinTask.kotlinOptions.outputFile = kotlinTask.outputFile.absolutePath
|
||||
val outputDir = kotlinTask.outputFile.parentFile
|
||||
|
||||
for (compiledSourceSet in kotlinCompilation.kotlinSourceSets) {
|
||||
kotlinTask.source(compiledSourceSet.kotlin)
|
||||
}
|
||||
|
||||
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, null, null, null, kotlinCompilation)
|
||||
|
||||
if (outputDir.isParentOf(project.rootDir))
|
||||
throw InvalidUserDataException(
|
||||
"The output directory '$outputDir' (defined by outputFile of $kotlinTask) contains or " +
|
||||
@@ -272,17 +293,17 @@ internal class Kotlin2JsSourceSetProcessor(
|
||||
kotlinTask.destinationDir = outputDir
|
||||
|
||||
if (!isSeparateClassesDirSupported) {
|
||||
sourceSet.output.setClassesDirCompatible(kotlinTask.destinationDir)
|
||||
kotlinCompilation.output.setClassesDirCompatible(kotlinTask.destinationDir)
|
||||
}
|
||||
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { it.source(kotlinSourceSet.kotlin) }
|
||||
.forEach { task -> kotlinCompilation.kotlinSourceSets.forEach { sourceSet -> task.source(sourceSet.kotlin) } }
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCleanSourceMapTask() {
|
||||
val taskName = sourceSet.getTaskName("clean", "sourceMap")
|
||||
val taskName = kotlinCompilation.composeName("clean", "sourceMap")
|
||||
val task = project.tasks.create(taskName, Delete::class.java)
|
||||
task.onlyIf { kotlinTask.kotlinOptions.sourceMap }
|
||||
task.delete(object : Closure<String>(this) {
|
||||
@@ -293,178 +314,265 @@ internal class Kotlin2JsSourceSetProcessor(
|
||||
}
|
||||
|
||||
internal class KotlinCommonSourceSetProcessor(
|
||||
project: Project,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
sourceSet: SourceSet,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
project: Project,
|
||||
compilation: KotlinCompilation,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
) : KotlinSourceSetProcessor<KotlinCompileCommon>(
|
||||
project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider,
|
||||
dslExtensionName = KOTLIN_DSL_NAME,
|
||||
taskDescription = "Compiles the kotlin sources in $sourceSet to Metadata.",
|
||||
compileTaskNameSuffix = "kotlinCommon"
|
||||
project, tasksProvider, taskDescription = "Compiles the kotlin sources in $compilation to Metadata.",
|
||||
kotlinCompilation = compilation
|
||||
) {
|
||||
override fun doTargetSpecificProcessing() {
|
||||
sourceSet.clearJavaSrcDirs()
|
||||
project.tasks.findByName(kotlinCompilation.compileAllTaskName)!!.dependsOn(kotlinTask)
|
||||
// can be missing (e.g. in case of tests)
|
||||
if (kotlinCompilation.compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||
project.tasks.findByName(kotlinCompilation.target.artifactsTaskName)?.dependsOn(kotlinTask)
|
||||
}
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
kotlinTask.source(kotlinSourceSet.kotlin)
|
||||
kotlinCompilation.kotlinSourceSets.forEach { sourceSet ->
|
||||
kotlinTask.source(sourceSet.kotlin)
|
||||
|
||||
}
|
||||
|
||||
val subpluginEnvironment: SubpluginEnvironment = loadSubplugins(project, kotlinPluginVersion)
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, kotlinTask, null, null, sourceSet)
|
||||
|
||||
project.tasks.findByName(sourceSet.classesTaskName)!!.dependsOn(kotlinTask)
|
||||
// can be missing (e.g. in case of tests)
|
||||
project.tasks.findByName(sourceSet.jarTaskName)?.dependsOn(kotlinTask)
|
||||
|
||||
project, kotlinTask, null, null, null, kotlinCompilation
|
||||
)
|
||||
appliedPlugins
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { it.source(kotlinSourceSet.kotlin) }
|
||||
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { kotlinCompilation.kotlinSourceSets.forEach { sourceSet -> it.source(sourceSet.kotlin) } }
|
||||
}
|
||||
}
|
||||
|
||||
override fun doCreateTask(project: Project, taskName: String): KotlinCompileCommon =
|
||||
tasksProvider.createKotlinCommonTask(project, taskName, sourceSet.name)
|
||||
tasksProvider.createKotlinCommonTask(project, taskName, kotlinCompilation.compilationName)
|
||||
}
|
||||
|
||||
|
||||
internal abstract class AbstractKotlinPlugin(
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
val kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
protected val kotlinPluginVersion: String
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
protected val kotlinPluginVersion: String
|
||||
) : Plugin<Project> {
|
||||
internal abstract fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String): KotlinSourceSetProcessor<*>
|
||||
|
||||
internal abstract fun buildSourceSetProcessor(project: Project, compilation: KotlinCompilation, kotlinPluginVersion: String): KotlinSourceSetProcessor<*>
|
||||
|
||||
protected abstract val platformType: KotlinPlatformType
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val javaBasePlugin = project.plugins.apply(JavaBasePlugin::class.java)
|
||||
val javaPluginConvention = project.convention.getPlugin(JavaPluginConvention::class.java)
|
||||
|
||||
project.plugins.apply(JavaPlugin::class.java)
|
||||
|
||||
configureSourceSetDefaults(project, javaBasePlugin, javaPluginConvention)
|
||||
configureDefaultVersionsResolutionStrategy(project)
|
||||
configureClassInspectionForIC(project)
|
||||
configureTarget(
|
||||
(project.kotlinExtension as KotlinSingleTargetProjectExtension).target,
|
||||
{ compilation -> buildSourceSetProcessor(project, compilation, kotlinPluginVersion) }
|
||||
)
|
||||
|
||||
configureProjectGlobalSettings(project, kotlinPluginVersion)
|
||||
}
|
||||
|
||||
open protected fun configureSourceSetDefaults(
|
||||
project: Project,
|
||||
javaBasePlugin: JavaBasePlugin,
|
||||
javaPluginConvention: JavaPluginConvention
|
||||
) {
|
||||
javaPluginConvention.sourceSets?.all { sourceSet ->
|
||||
buildSourceSetProcessor(project, javaBasePlugin, sourceSet, kotlinPluginVersion).run()
|
||||
companion object {
|
||||
fun configureProjectGlobalSettings(project: Project, kotlinPluginVersion: String) {
|
||||
configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion)
|
||||
configureClassInspectionForIC(project)
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureDefaultVersionsResolutionStrategy(project: Project) {
|
||||
project.configurations.all { configuration ->
|
||||
if (isGradleVersionAtLeast(4, 4)) {
|
||||
// Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved:
|
||||
configuration.withDependencies { dependencySet ->
|
||||
dependencySet.filterIsInstance<ExternalDependency>()
|
||||
.filter { it.group == "org.jetbrains.kotlin" && it.version.isNullOrEmpty() }
|
||||
.forEach { it.version { constraint -> constraint.prefer(kotlinPluginVersion) } }
|
||||
}
|
||||
fun configureTarget(
|
||||
target: KotlinTarget,
|
||||
buildSourceSetProcessor: (KotlinCompilation) -> KotlinSourceSetProcessor<*>
|
||||
) {
|
||||
setUpJavaSourceSets(target)
|
||||
configureSourceSetDefaults(target, buildSourceSetProcessor)
|
||||
}
|
||||
|
||||
private fun configureClassInspectionForIC(project: Project) {
|
||||
val classesTask = project.tasks.findByName(JavaPlugin.CLASSES_TASK_NAME)
|
||||
val jarTask = project.tasks.findByName(JavaPlugin.JAR_TASK_NAME)
|
||||
|
||||
if (classesTask == null || jarTask !is Jar) {
|
||||
project.logger.info(
|
||||
"Could not configure class inspection task " +
|
||||
"(classes task = ${classesTask?.javaClass?.canonicalName}, " +
|
||||
"jar task = ${classesTask?.javaClass?.canonicalName}"
|
||||
)
|
||||
return
|
||||
}
|
||||
else {
|
||||
configuration.resolutionStrategy.eachDependency { details ->
|
||||
val requested = details.requested
|
||||
if (requested.group == "org.jetbrains.kotlin" && requested.version.isEmpty()) {
|
||||
details.useVersion(kotlinPluginVersion)
|
||||
}
|
||||
}
|
||||
val inspectTask = project.tasks.create("inspectClassesForKotlinIC", InspectClassesForMultiModuleIC::class.java)
|
||||
inspectTask.sourceSetName = SourceSet.MAIN_SOURCE_SET_NAME
|
||||
inspectTask.jarTask = jarTask
|
||||
inspectTask.dependsOn(classesTask)
|
||||
jarTask.dependsOn(inspectTask)
|
||||
}
|
||||
|
||||
private fun setUpJavaSourceSets(
|
||||
kotlinTarget: KotlinTarget
|
||||
) {
|
||||
val project = kotlinTarget.project
|
||||
val javaSourceSets = project.convention.getPlugin(JavaPluginConvention::class.java).sourceSets
|
||||
|
||||
javaSourceSets.all { javaSourceSet ->
|
||||
val kotlinCompilation = kotlinTarget.compilations.maybeCreate(javaSourceSet.name) as KotlinWithJavaCompilation
|
||||
kotlinCompilation.source(javaSourceSet)
|
||||
val kotlinSourceSet = project.kotlinExtension.sourceSets.maybeCreate(kotlinCompilation.fullName)
|
||||
javaSourceSet.addConvention(KOTLIN_DSL_NAME, kotlinSourceSet)
|
||||
kotlinCompilation.source(kotlinSourceSet)
|
||||
}
|
||||
|
||||
kotlinTarget.compilations.all { kotlinCompilation -> javaSourceSets.maybeCreate(kotlinCompilation.fullName) }
|
||||
}
|
||||
|
||||
fun configureSourceSetDefaults(
|
||||
kotlinTarget: KotlinTarget,
|
||||
buildSourceSetProcessor: (KotlinCompilation) -> KotlinSourceSetProcessor<*>
|
||||
) {
|
||||
kotlinTarget.compilations.all { compilation ->
|
||||
buildSourceSetProcessor(compilation).run()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureClassInspectionForIC(project: Project) {
|
||||
val classesTask = project.tasks.findByName(JavaPlugin.CLASSES_TASK_NAME)
|
||||
val jarTask = project.tasks.findByName(JavaPlugin.JAR_TASK_NAME)
|
||||
|
||||
if (classesTask == null || jarTask !is Jar) {
|
||||
project.logger.info(
|
||||
"Could not configure class inspection task " +
|
||||
"(classes task = ${classesTask?.javaClass?.canonicalName}, " +
|
||||
"jar task = ${classesTask?.javaClass?.canonicalName}"
|
||||
)
|
||||
return
|
||||
internal fun configureDefaultVersionsResolutionStrategy(project: Project, kotlinPluginVersion: String) {
|
||||
project.configurations.all { configuration ->
|
||||
if (isGradleVersionAtLeast(4, 4)) {
|
||||
// Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved:
|
||||
configuration.withDependencies { dependencySet ->
|
||||
dependencySet.filterIsInstance<ExternalDependency>()
|
||||
.filter { it.group == "org.jetbrains.kotlin" && it.version.isNullOrEmpty() }
|
||||
.forEach { it.version { constraint -> constraint.prefer(kotlinPluginVersion) } }
|
||||
}
|
||||
} else {
|
||||
configuration.resolutionStrategy.eachDependency { details ->
|
||||
val requested = details.requested
|
||||
if (requested.group == "org.jetbrains.kotlin" && requested.version.isEmpty()) {
|
||||
details.useVersion(kotlinPluginVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
val inspectTask = project.tasks.create("inspectClassesForKotlinIC", InspectClassesForMultiModuleIC::class.java)
|
||||
inspectTask.sourceSetName = SourceSet.MAIN_SOURCE_SET_NAME
|
||||
inspectTask.jarTask = jarTask
|
||||
inspectTask.dependsOn(classesTask)
|
||||
jarTask.dependsOn(inspectTask)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinPlugin(
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
kotlinPluginVersion: String
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion) {
|
||||
override fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String) =
|
||||
Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion)
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinPluginVersion: String
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinPluginVersion) {
|
||||
override val platformType: KotlinPlatformType
|
||||
get() = KotlinPlatformType.JVM
|
||||
|
||||
override fun buildSourceSetProcessor(project: Project, compilation: KotlinCompilation, kotlinPluginVersion: String) =
|
||||
Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val target = KotlinWithJavaTarget(project, KotlinPlatformType.JS, "kotlin").apply {
|
||||
disambiguationClassifier = null // don't add anything to the task names
|
||||
}
|
||||
(project.kotlinExtension as KotlinSingleTargetProjectExtension).target = target
|
||||
|
||||
project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
|
||||
super.apply(project)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinCommonPlugin(
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinPluginVersion: String
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinPluginVersion) {
|
||||
|
||||
override val platformType: KotlinPlatformType
|
||||
get() = KotlinPlatformType.COMMON
|
||||
|
||||
override fun buildSourceSetProcessor(
|
||||
project: Project,
|
||||
compilation: KotlinCompilation,
|
||||
kotlinPluginVersion: String
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion) {
|
||||
override fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String) =
|
||||
KotlinCommonSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion)
|
||||
): KotlinSourceSetProcessor<*> =
|
||||
KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val target = KotlinWithJavaTarget(project, KotlinPlatformType.JS, "common").apply {
|
||||
disambiguationClassifier = "common"
|
||||
}
|
||||
(project.kotlinExtension as KotlinSingleTargetProjectExtension).target = target
|
||||
|
||||
super.apply(project)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class Kotlin2JsPlugin(
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinPluginVersion: String
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinPluginVersion) {
|
||||
override val platformType: KotlinPlatformType
|
||||
get() = KotlinPlatformType.JS
|
||||
|
||||
override fun buildSourceSetProcessor(
|
||||
project: Project,
|
||||
compilation: KotlinCompilation,
|
||||
kotlinPluginVersion: String
|
||||
) : AbstractKotlinPlugin(tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion) {
|
||||
override fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String) =
|
||||
Kotlin2JsSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion)
|
||||
): KotlinSourceSetProcessor<*> =
|
||||
Kotlin2JsSourceSetProcessor(
|
||||
project, tasksProvider, compilation, kotlinPluginVersion
|
||||
)
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val target = KotlinWithJavaTarget(project, KotlinPlatformType.JS, "2Js").apply {
|
||||
disambiguationClassifier = "2Js"
|
||||
}
|
||||
|
||||
(project.kotlinExtension as KotlinSingleTargetProjectExtension).target = target
|
||||
super.apply(project)
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinAndroidPlugin(
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
private val kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
val tasksProvider: KotlinTasksProvider,
|
||||
private val kotlinPluginVersion: String
|
||||
) : Plugin<Project> {
|
||||
|
||||
override fun apply(project: Project) {
|
||||
val version = loadAndroidPluginVersion()
|
||||
if (version != null) {
|
||||
val minimalVersion = "1.1.0"
|
||||
if (compareVersionNumbers(version, minimalVersion) < 0) {
|
||||
throw IllegalStateException("Kotlin: Unsupported version of com.android.tools.build:gradle plugin: version $minimalVersion or higher should be used with kotlin-android plugin")
|
||||
}
|
||||
}
|
||||
val androidTarget = KotlinAndroidTarget(project)
|
||||
|
||||
val kotlinTools = KotlinConfigurationTools(
|
||||
applyToTarget(
|
||||
project, androidTarget, project.kotlinExtension.sourceSetProvider,
|
||||
tasksProvider, kotlinPluginVersion
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun applyToTarget(
|
||||
project: Project,
|
||||
kotlinTarget: KotlinAndroidTarget,
|
||||
kotlinSourceSetProvider: KotlinSourceSetProvider,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
kotlinPluginVersion: String
|
||||
) {
|
||||
|
||||
val version = loadAndroidPluginVersion()
|
||||
if (version != null) {
|
||||
val minimalVersion = "1.1.0"
|
||||
if (compareVersionNumbers(version, minimalVersion) < 0) {
|
||||
throw IllegalStateException("Kotlin: Unsupported version of com.android.tools.build:gradle plugin: version $minimalVersion or higher should be used with kotlin-android plugin")
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinTools = KotlinConfigurationTools(
|
||||
kotlinSourceSetProvider,
|
||||
tasksProvider,
|
||||
kotlinPluginVersion)
|
||||
kotlinPluginVersion
|
||||
)
|
||||
|
||||
val legacyVersionThreshold = "2.5.0"
|
||||
val legacyVersionThreshold = "2.5.0"
|
||||
|
||||
val variantProcessor = if (compareVersionNumbers(version, legacyVersionThreshold) < 0) {
|
||||
LegacyAndroidAndroidProjectHandler(kotlinTools)
|
||||
}
|
||||
else {
|
||||
val android25ProjectHandlerClass = Class.forName("org.jetbrains.kotlin.gradle.plugin.Android25ProjectHandler")
|
||||
val ctor = android25ProjectHandlerClass.constructors.single {
|
||||
it.parameterTypes.contentEquals(arrayOf(kotlinTools.javaClass))
|
||||
val variantProcessor = if (compareVersionNumbers(version, legacyVersionThreshold) < 0) {
|
||||
LegacyAndroidAndroidProjectHandler(kotlinTools)
|
||||
} else {
|
||||
val android25ProjectHandlerClass = Class.forName("org.jetbrains.kotlin.gradle.plugin.Android25ProjectHandler")
|
||||
val ctor = android25ProjectHandlerClass.constructors.single {
|
||||
it.parameterTypes.contentEquals(arrayOf(kotlinTools.javaClass))
|
||||
}
|
||||
ctor.newInstance(kotlinTools) as AbstractAndroidProjectHandler<*>
|
||||
}
|
||||
ctor.newInstance(kotlinTools) as AbstractAndroidProjectHandler<*>
|
||||
}
|
||||
|
||||
variantProcessor.handleProject(project)
|
||||
variantProcessor.handleProject(project, kotlinTarget)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,23 +598,31 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
|
||||
protected open fun checkVariantIsValid(variant: V) = Unit
|
||||
|
||||
protected abstract fun wireKotlinTasks(project: Project,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: V,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile)
|
||||
protected open fun setUpDependencyResolution(variant: V, compilation: KotlinCompilation) = Unit
|
||||
|
||||
protected abstract fun wireKotlinTasks(
|
||||
project: Project,
|
||||
compilation: KotlinJvmAndroidCompilation,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: V,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile
|
||||
)
|
||||
|
||||
protected abstract fun wrapVariantDataForKapt(variantData: V): KaptVariantData<V>
|
||||
|
||||
fun handleProject(project: Project) {
|
||||
fun handleProject(project: Project, kotlinAndroidTarget: KotlinAndroidTarget) {
|
||||
val ext = project.extensions.getByName("android") as BaseExtension
|
||||
val aptConfigurations = hashMapOf<String, Configuration>()
|
||||
|
||||
ext.sourceSets.all { sourceSet ->
|
||||
logger.kotlinDebug("Creating KotlinSourceSet for source set $sourceSet")
|
||||
val kotlinSourceSet = kotlinConfigurationTools.kotlinSourceSetProvider.create(sourceSet.name)
|
||||
kotlinSourceSet.kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin")))
|
||||
logger.kotlinDebug("Creating KotlinBaseSourceSet for source set $sourceSet")
|
||||
val kotlinSourceSet = kotlinConfigurationTools.kotlinSourceSetProvider.provideSourceSet(
|
||||
lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, sourceSet.name)
|
||||
).apply {
|
||||
kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin")))
|
||||
kotlin.srcDirs(sourceSet.java.srcDirs)
|
||||
}
|
||||
sourceSet.addConvention(KOTLIN_DSL_NAME, kotlinSourceSet)
|
||||
Kapt3KotlinGradleSubplugin.createAptConfigurationIfNeeded(project, sourceSet.name)
|
||||
}
|
||||
@@ -516,42 +632,46 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
ext.addExtension(KOTLIN_OPTIONS_DSL_NAME, kotlinOptions)
|
||||
|
||||
project.afterEvaluate { project ->
|
||||
if (project != null) {
|
||||
val androidPluginIds = listOf("android", "com.android.application", "android-library", "com.android.library",
|
||||
"com.android.test", "com.android.feature", "com.android.dynamic-feature")
|
||||
val plugin = androidPluginIds.asSequence()
|
||||
.mapNotNull { project.plugins.findPlugin(it) as? BasePlugin }
|
||||
.firstOrNull()
|
||||
?: throw InvalidPluginException("'kotlin-android' expects one of the Android Gradle " +
|
||||
"plugins to be applied to the project:\n\t" +
|
||||
androidPluginIds.joinToString("\n\t") { "* $it" })
|
||||
val androidPluginIds = listOf("android", "com.android.application", "android-library", "com.android.library",
|
||||
"com.android.test", "com.android.feature", "com.android.dynamic-feature")
|
||||
val plugin = androidPluginIds.asSequence()
|
||||
.mapNotNull { project.plugins.findPlugin(it) as? BasePlugin }
|
||||
.firstOrNull()
|
||||
?: throw InvalidPluginException("'kotlin-android' expects one of the Android Gradle " +
|
||||
"plugins to be applied to the project:\n\t" +
|
||||
androidPluginIds.joinToString("\n\t") { "* $it" })
|
||||
|
||||
val subpluginEnvironment = loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion)
|
||||
val subpluginEnvironment = loadSubplugins(project, kotlinConfigurationTools.kotlinPluginVersion)
|
||||
|
||||
checkAndroidAnnotationProcessorDependencyUsage(project)
|
||||
checkAndroidAnnotationProcessorDependencyUsage(project)
|
||||
|
||||
forEachVariant(project) {
|
||||
processVariant(it, project, ext, plugin, aptConfigurations, kotlinOptions,
|
||||
kotlinConfigurationTools.kotlinTasksProvider, subpluginEnvironment)
|
||||
}
|
||||
forEachVariant(project) {
|
||||
processVariant(
|
||||
it, kotlinAndroidTarget, project, ext, plugin, kotlinOptions, kotlinConfigurationTools.kotlinTasksProvider,
|
||||
subpluginEnvironment
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processVariant(variantData: V,
|
||||
project: Project,
|
||||
androidExt: BaseExtension,
|
||||
androidPlugin: BasePlugin,
|
||||
aptConfigurations: Map<String, Configuration>,
|
||||
rootKotlinOptions: KotlinJvmOptionsImpl,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
subpluginEnvironment: SubpluginEnvironment) {
|
||||
private fun processVariant(
|
||||
variantData: V,
|
||||
target: KotlinAndroidTarget,
|
||||
project: Project,
|
||||
androidExt: BaseExtension,
|
||||
androidPlugin: BasePlugin,
|
||||
rootKotlinOptions: KotlinJvmOptionsImpl,
|
||||
tasksProvider: KotlinTasksProvider,
|
||||
subpluginEnvironment: SubpluginEnvironment
|
||||
) {
|
||||
|
||||
checkVariantIsValid(variantData)
|
||||
|
||||
val variantDataName = getVariantName(variantData)
|
||||
logger.kotlinDebug("Process variant [$variantDataName]")
|
||||
|
||||
val compilation = target.compilations.create(variantDataName)
|
||||
setUpDependencyResolution(variantData, compilation)
|
||||
|
||||
val javaTask = getJavaTask(variantData)
|
||||
|
||||
if (javaTask == null) {
|
||||
@@ -559,7 +679,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
return
|
||||
}
|
||||
|
||||
val kotlinTaskName = "compile${variantDataName.capitalize()}Kotlin"
|
||||
val kotlinTaskName = compilation.compileKotlinTaskName
|
||||
// todo: Investigate possibility of creating and configuring kotlinTask before evaluation
|
||||
val kotlinTask = tasksProvider.createKotlinJVMTask(project, kotlinTaskName, variantDataName)
|
||||
kotlinTask.parentKotlinOptionsImpl = rootKotlinOptions
|
||||
@@ -568,22 +688,35 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
|
||||
kotlinTask.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
|
||||
kotlinTask.description = "Compiles the $variantDataName kotlin."
|
||||
|
||||
configureSources(kotlinTask, variantData)
|
||||
wireKotlinTasks(project, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
|
||||
configureSources(kotlinTask, variantData, compilation)
|
||||
|
||||
// In MPPs, add the common main Kotlin sources to non-test variants, the common test sources to test variants
|
||||
val commonSourceSetName = if (getTestedVariantData(variantData) == null)
|
||||
KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME else
|
||||
KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME
|
||||
project.kotlinExtension.sourceSets.findByName(commonSourceSetName)?.let {
|
||||
compilation.source(it)
|
||||
}
|
||||
|
||||
wireKotlinTasks(project, compilation, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
|
||||
|
||||
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
|
||||
project, kotlinTask, javaTask, wrapVariantDataForKapt(variantData), this, null)
|
||||
|
||||
appliedPlugins.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
|
||||
.forEach { configureSources(it, variantData) }
|
||||
.forEach { configureSources(it, variantData, null) }
|
||||
}
|
||||
|
||||
private fun configureSources(compileTask: AbstractCompile, variantData: V) {
|
||||
private fun configureSources(compileTask: AbstractCompile, variantData: V, compilation: KotlinCompilation?) {
|
||||
val logger = compileTask.project.logger
|
||||
|
||||
for (provider in getSourceProviders(variantData)) {
|
||||
val kotlinSourceSet = provider.getConvention(KOTLIN_DSL_NAME) as? KotlinSourceSet ?: continue
|
||||
compileTask.source(kotlinSourceSet.kotlin)
|
||||
if (compilation != null) {
|
||||
compilation.source(kotlinSourceSet)
|
||||
} else {
|
||||
compileTask.source(kotlinSourceSet.kotlin)
|
||||
}
|
||||
}
|
||||
|
||||
for (javaSrcDir in getAllJavaSources(variantData)) {
|
||||
@@ -685,10 +818,10 @@ internal class SubpluginEnvironment(
|
||||
fun <C: CommonCompilerArguments> addSubpluginOptions(
|
||||
project: Project,
|
||||
kotlinTask: AbstractKotlinCompile<C>,
|
||||
javaTask: AbstractCompile,
|
||||
javaTask: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: AbstractAndroidProjectHandler<out Any?>?,
|
||||
javaSourceSet: SourceSet?
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<KotlinGradleSubplugin<AbstractKotlinCompile<C>>> {
|
||||
val pluginOptions = kotlinTask.pluginOptions
|
||||
|
||||
@@ -705,7 +838,7 @@ internal class SubpluginEnvironment(
|
||||
project.logger.kotlinDebug { "Adding '$mavenCoordinate' to '$PLUGIN_CLASSPATH_CONFIGURATION_NAME' configuration" }
|
||||
project.dependencies.add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, mavenCoordinate)
|
||||
|
||||
val subpluginOptions = subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, javaSourceSet)
|
||||
val subpluginOptions = subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, kotlinCompilation)
|
||||
val subpluginId = subplugin.getCompilerPluginId()
|
||||
kotlinTask.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions)
|
||||
|
||||
|
||||
@@ -21,20 +21,30 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.internal.file.FileResolver
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.createKotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.internal.KotlinSourceSetProviderImpl
|
||||
import org.gradle.internal.cleanup.BuildOutputCleanupRegistry
|
||||
import org.gradle.internal.reflect.Instantiator
|
||||
import org.jetbrains.kotlin.gradle.dsl.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinSourceSetFactory
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import java.io.FileNotFoundException
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
abstract class KotlinBasePluginWrapper(protected val fileResolver: FileResolver): Plugin<Project> {
|
||||
abstract class KotlinBasePluginWrapper(
|
||||
protected val fileResolver: FileResolver
|
||||
): Plugin<Project> {
|
||||
private val log = Logging.getLogger(this.javaClass)
|
||||
val kotlinPluginVersion = loadKotlinVersionFromResource(log)
|
||||
|
||||
open val projectExtensionClass: KClass<out KotlinProjectExtension> get() = KotlinProjectExtension::class
|
||||
|
||||
internal open fun kotlinSourceSetFactory(project: Project): KotlinSourceSetFactory<out KotlinSourceSet> =
|
||||
DefaultKotlinSourceSetFactory(project, fileResolver)
|
||||
|
||||
override fun apply(project: Project) {
|
||||
project.configurations.maybeCreate(COMPILER_CLASSPATH_CONFIGURATION_NAME).defaultDependencies {
|
||||
it.add(project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_COMPILER_EMBEDDABLE:$kotlinPluginVersion"))
|
||||
@@ -48,38 +58,82 @@ abstract class KotlinBasePluginWrapper(protected val fileResolver: FileResolver)
|
||||
System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true")
|
||||
val kotlinGradleBuildServices = KotlinGradleBuildServices.getInstance(project.gradle)
|
||||
|
||||
project.createKotlinExtension(projectExtensionClass)
|
||||
project.createKotlinExtension(projectExtensionClass).apply {
|
||||
fun <T : KotlinSourceSet> kotlinSourceSetContainer(factory: KotlinSourceSetFactory<T>) =
|
||||
project.container(factory.itemClass, factory)
|
||||
|
||||
val plugin = getPlugin(kotlinGradleBuildServices)
|
||||
project.kotlinExtension.sourceSets = kotlinSourceSetContainer(kotlinSourceSetFactory(project))
|
||||
}
|
||||
|
||||
val plugin = getPlugin(project, kotlinGradleBuildServices)
|
||||
plugin.apply(project)
|
||||
}
|
||||
|
||||
internal abstract fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project>
|
||||
|
||||
open val projectExtensionClass: KClass<out KotlinProjectExtension> get() = KotlinProjectExtension::class
|
||||
internal abstract fun getPlugin(
|
||||
project: Project,
|
||||
kotlinGradleBuildServices: KotlinGradleBuildServices
|
||||
): Plugin<Project>
|
||||
}
|
||||
|
||||
open class KotlinPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) =
|
||||
KotlinPlugin(KotlinTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion)
|
||||
open class KotlinPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
KotlinPlugin(KotlinTasksProvider(), kotlinPluginVersion)
|
||||
|
||||
override val projectExtensionClass: KClass<out KotlinJvmProjectExtension>
|
||||
get() = KotlinJvmProjectExtension::class
|
||||
}
|
||||
|
||||
open class KotlinCommonPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) =
|
||||
KotlinCommonPlugin(KotlinCommonTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion)
|
||||
open class KotlinCommonPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver,
|
||||
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
KotlinCommonPlugin(KotlinCommonTasksProvider(), kotlinPluginVersion)
|
||||
|
||||
override val projectExtensionClass: KClass<out KotlinSingleTargetProjectExtension>
|
||||
get() = KotlinSingleTargetProjectExtension::class
|
||||
}
|
||||
|
||||
open class KotlinAndroidPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) =
|
||||
KotlinAndroidPlugin(AndroidTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion)
|
||||
open class KotlinMultiplatformPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver,
|
||||
private val instantiator: Instantiator,
|
||||
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
KotlinMultiplatformPlugin(
|
||||
buildOutputCleanupRegistry, fileResolver,
|
||||
instantiator, kotlinPluginVersion
|
||||
)
|
||||
|
||||
override val projectExtensionClass: KClass<out KotlinMultiplatformExtension>
|
||||
get() = KotlinMultiplatformExtension::class
|
||||
}
|
||||
|
||||
open class Kotlin2JsPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) =
|
||||
Kotlin2JsPlugin(Kotlin2JsTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion)
|
||||
open class KotlinAndroidPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
KotlinAndroidPlugin(
|
||||
AndroidTasksProvider(),
|
||||
kotlinPluginVersion
|
||||
)
|
||||
|
||||
override fun kotlinSourceSetFactory(project: Project): KotlinSourceSetFactory<out KotlinSourceSet> {
|
||||
return super.kotlinSourceSetFactory(project)
|
||||
}
|
||||
}
|
||||
|
||||
open class Kotlin2JsPluginWrapper @Inject constructor(
|
||||
fileResolver: FileResolver,
|
||||
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry
|
||||
): KotlinBasePluginWrapper(fileResolver) {
|
||||
override fun getPlugin(project: Project, kotlinGradleBuildServices: KotlinGradleBuildServices): Plugin<Project> =
|
||||
Kotlin2JsPlugin(Kotlin2JsTasksProvider(), kotlinPluginVersion)
|
||||
|
||||
override val projectExtensionClass: KClass<out KotlinSingleTargetProjectExtension>
|
||||
get() = KotlinSingleTargetProjectExtension::class
|
||||
}
|
||||
|
||||
fun Project.getKotlinPluginVersion(): String? {
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
|
||||
interface KotlinSourceSet {
|
||||
val kotlin: SourceDirectorySet
|
||||
|
||||
fun kotlin(configureClosure: Closure<Any?>?): KotlinSourceSet
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
|
||||
internal interface KotlinSourceSetProvider {
|
||||
fun create(displayName: String): KotlinSourceSet
|
||||
fun provideSourceSet(displayName: String): KotlinSourceSet
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.gradle.internal.KaptTask
|
||||
import org.jetbrains.kotlin.gradle.internal.KaptVariantData
|
||||
import org.jetbrains.kotlin.gradle.internal.registerGeneratedJavaSource
|
||||
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.checkedReflection
|
||||
import java.io.File
|
||||
@@ -40,12 +41,14 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl
|
||||
variantManager.variantDataList.forEach(action)
|
||||
}
|
||||
|
||||
override fun wireKotlinTasks(project: Project,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: BaseVariantData<out BaseVariantOutputData>,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile
|
||||
override fun wireKotlinTasks(
|
||||
project: Project,
|
||||
compilation: KotlinJvmAndroidCompilation,
|
||||
androidPlugin: BasePlugin,
|
||||
androidExt: BaseExtension,
|
||||
variantData: BaseVariantData<out BaseVariantOutputData>,
|
||||
javaTask: AbstractCompile,
|
||||
kotlinTask: KotlinCompile
|
||||
) {
|
||||
kotlinTask.dependsOn(*javaTask.dependsOn.toTypedArray())
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.base
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
private val configurationNameFromPlatformExtension = NameFromKotlinTargetDelegate("ConfigurationName")
|
||||
private val taskNameFromPlatformExtension = NameFromKotlinTargetDelegate("TaskName")
|
||||
|
||||
//internal val KotlinTarget.defaultConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.compileConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.testCompileConfigurationName by configurationNameFromPlatformExtension
|
||||
//
|
||||
//internal val KotlinTarget.compileClasspathConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.testCompileClasspathConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.testRuntimeClasspathConfigurationName by configurationNameFromPlatformExtension
|
||||
//
|
||||
//internal val KotlinTarget.apiElementsConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.runtimeElementsConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.implementationConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.testImplementationConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.runtimeConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.runtimeOnlyConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.testRuntimeConfigurationName by configurationNameFromPlatformExtension
|
||||
//internal val KotlinTarget.testRuntimeOnlyConfigurationName by configurationNameFromPlatformExtension
|
||||
//
|
||||
//internal val KotlinTarget.classesTaskName by taskNameFromPlatformExtension
|
||||
//internal val KotlinTarget.jarTaskName by taskNameFromPlatformExtension
|
||||
//internal val KotlinTarget.processResourcesTaskName by taskNameFromPlatformExtension
|
||||
|
||||
private class NameFromKotlinTargetDelegate(val propertySuffix: String) {
|
||||
operator fun getValue(thisRef: KotlinTarget, property: KProperty<*>): String {
|
||||
require(property.name.endsWith(propertySuffix))
|
||||
val nameToDisambiguate = property.name.substringBeforeLast(propertySuffix)
|
||||
.also { require(it.isNotEmpty()) }
|
||||
return thisRef.disambiguateName(nameToDisambiguate)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.base
|
||||
|
||||
import org.gradle.api.NamedDomainObjectFactory
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.JavaPluginConvention
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
|
||||
interface KotlinCompilationFactory<T: KotlinCompilation> : NamedDomainObjectFactory<T> {
|
||||
val itemClass: Class<T>
|
||||
}
|
||||
|
||||
private fun Project.createSourceSetOutput(name: String) =
|
||||
KotlinSourceSetOutput(this, buildDir.resolve("processedResources/$name"))
|
||||
|
||||
class KotlinCommonCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||
) : KotlinCompilationFactory<KotlinCommonCompilation> {
|
||||
override val itemClass: Class<KotlinCommonCompilation>
|
||||
get() = KotlinCommonCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinCommonCompilation =
|
||||
KotlinCommonCompilation(target, name, project.createSourceSetOutput(name))
|
||||
}
|
||||
|
||||
class KotlinJvmCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinOnlyTarget<KotlinJvmCompilation>
|
||||
) : KotlinCompilationFactory<KotlinJvmCompilation> {
|
||||
override val itemClass: Class<KotlinJvmCompilation>
|
||||
get() = KotlinJvmCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinJvmCompilation = KotlinJvmCompilation(
|
||||
target,
|
||||
name,
|
||||
KotlinSourceSetOutput(project, project.buildDir.resolve("resources/$name"))
|
||||
)
|
||||
}
|
||||
|
||||
class KotlinWithJavaCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinWithJavaTarget
|
||||
) : KotlinCompilationFactory<KotlinWithJavaCompilation> {
|
||||
private val javaSourceSets: SourceSetContainer
|
||||
get() = project.convention.getPlugin(JavaPluginConvention::class.java).sourceSets
|
||||
|
||||
override val itemClass: Class<KotlinWithJavaCompilation>
|
||||
get() = KotlinWithJavaCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinWithJavaCompilation {
|
||||
val javaSourceSet = javaSourceSets.maybeCreate(name)
|
||||
val result = KotlinWithJavaCompilation(target, name, javaSourceSet)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinJvmAndroidCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinAndroidTarget
|
||||
) : KotlinCompilationFactory<KotlinJvmAndroidCompilation> {
|
||||
|
||||
override val itemClass: Class<KotlinJvmAndroidCompilation>
|
||||
get() = KotlinJvmAndroidCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinJvmAndroidCompilation {
|
||||
val output = project.createSourceSetOutput(name)
|
||||
val result = KotlinJvmAndroidCompilation(target, name, output)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinJsCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinOnlyTarget<KotlinJsCompilation>
|
||||
) : KotlinCompilationFactory<KotlinJsCompilation> {
|
||||
override val itemClass: Class<KotlinJsCompilation>
|
||||
get() = KotlinJsCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinJsCompilation =
|
||||
KotlinJsCompilation(target, name, project.createSourceSetOutput(name))
|
||||
}
|
||||
|
||||
class KotlinNativeCompilationFactory(
|
||||
val project: Project,
|
||||
val target: KotlinNativeTarget
|
||||
) : KotlinCompilationFactory<KotlinNativeCompilation> {
|
||||
|
||||
override val itemClass: Class<KotlinNativeCompilation>
|
||||
get() = KotlinNativeCompilation::class.java
|
||||
|
||||
override fun create(name: String): KotlinNativeCompilation =
|
||||
KotlinNativeCompilation(target, name, project.createSourceSetOutput(name)).apply {
|
||||
if (name == KotlinCompilation.TEST_COMPILATION_NAME) {
|
||||
outputKinds = mutableListOf(NativeOutputKind.EXECUTABLE)
|
||||
buildTypes = mutableListOf(NativeBuildType.DEBUG)
|
||||
isTestCompilation = true
|
||||
} else {
|
||||
buildTypes = mutableListOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.base
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ConfigurationContainer
|
||||
import org.gradle.api.artifacts.type.ArtifactTypeDefinition
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.internal.artifacts.ArtifactAttributes
|
||||
import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact
|
||||
import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
|
||||
import org.gradle.api.internal.plugins.DslObject
|
||||
import org.gradle.api.plugins.BasePlugin
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.internal.cleanup.BuildOutputCleanupRegistry
|
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||
import org.gradle.language.jvm.tasks.ProcessResources
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.fullName
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||
import java.io.File
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
open class KotlinOnlyTargetConfigurator(
|
||||
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry
|
||||
) {
|
||||
fun <KotlinCompilationType: KotlinCompilation> configureTarget(
|
||||
project: Project,
|
||||
target: KotlinOnlyTarget<KotlinCompilationType>
|
||||
) {
|
||||
configureCompilationDefaults(project, target)
|
||||
configureCompilations(project, target)
|
||||
defineConfigurationsForTarget(project, target)
|
||||
configureArchivesAndComponent(project, target)
|
||||
configureBuild(project, target)
|
||||
|
||||
setCompatibilityOfAbstractCompileTasks(project)
|
||||
}
|
||||
|
||||
private fun <KotlinCompilationType: KotlinCompilation> configureCompilations(
|
||||
project: Project,
|
||||
platformTarget: KotlinOnlyTarget<KotlinCompilationType>
|
||||
) {
|
||||
val main = platformTarget.compilations.create(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||
|
||||
platformTarget.compilations.create(KotlinCompilation.TEST_COMPILATION_NAME).apply {
|
||||
compileDependencyFiles = project.files(main.output, project.configurations.maybeCreate(compileDependencyConfigurationName))
|
||||
|
||||
if (this is KotlinCompilationToRunnableFiles) {
|
||||
runtimeDependencyFiles = project.files(output, main.output, project.configurations.maybeCreate(runtimeDependencyConfigurationName))
|
||||
}
|
||||
}
|
||||
|
||||
platformTarget.compilations.all {
|
||||
buildOutputCleanupRegistry.registerOutputs(it.output)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <KotlinCompilationType: KotlinCompilation> configureCompilationDefaults(project: Project, target: KotlinOnlyTarget<KotlinCompilationType>) {
|
||||
target.compilations.all { compilation ->
|
||||
defineConfigurationsForCompilation(compilation, target, project.configurations)
|
||||
|
||||
project.kotlinExtension.sourceSets.maybeCreate(compilation.fullName).also { sourceSet ->
|
||||
compilation.source(sourceSet) // also adds dependencies, requires the configurations for target and source set to exist at this point
|
||||
}
|
||||
|
||||
if (compilation is KotlinCompilationWithResources) {
|
||||
configureResourceProcessing(project, compilation, project.files())
|
||||
}
|
||||
|
||||
createLifecycleTask(compilation, project)
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureArchivesAndComponent(project: Project, target: KotlinOnlyTarget<*>) {
|
||||
val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||
|
||||
val jar = project.tasks.create(target.artifactsTaskName, Jar::class.java)
|
||||
jar.description = "Assembles a jar archive containing the main classes."
|
||||
jar.group = BasePlugin.BUILD_GROUP
|
||||
jar.from(mainCompilation.output)
|
||||
|
||||
val jarArtifact = ArchivePublishArtifact(jar)
|
||||
val apiElementsConfiguration = project.configurations.getByName(target.apiElementsConfigurationName)
|
||||
|
||||
target.disambiguationClassifier?.let { jar.classifier = it }
|
||||
|
||||
project.extensions.getByType(DefaultArtifactPublicationSet::class.java).addCandidate(jarArtifact)
|
||||
|
||||
addJar(apiElementsConfiguration, jarArtifact)
|
||||
|
||||
if (mainCompilation is KotlinCompilationToRunnableFiles) {
|
||||
val runtimeConfiguration = project.configurations.getByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||
val runtimeElementsConfiguration = project.configurations.getByName(target.runtimeElementsConfigurationName)
|
||||
addJar(runtimeConfiguration, jarArtifact)
|
||||
addJar(runtimeElementsConfiguration, jarArtifact) // TODO Check Gradle's special split into variants for classes & resources
|
||||
}
|
||||
|
||||
// note: there's no variant configuration for now
|
||||
|
||||
// FIXME ensure this dependency through configurations instead:
|
||||
project.tasks.getByName("assemble").dependsOn(jar)
|
||||
}
|
||||
|
||||
private fun addJar(configuration: Configuration, jarArtifact: ArchivePublishArtifact) {
|
||||
val publications = configuration.outgoing
|
||||
|
||||
// Configure an implicit variant
|
||||
publications.artifacts.add(jarArtifact)
|
||||
publications.attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, ArtifactTypeDefinition.JAR_TYPE)
|
||||
}
|
||||
|
||||
private fun configureResourceProcessing(
|
||||
project: Project,
|
||||
compilation: KotlinCompilationWithResources,
|
||||
resourceSet: FileCollection
|
||||
) {
|
||||
compilation.output.setResourcesDir(Callable {
|
||||
val classesDirName = "resources/" + compilation.compilationName
|
||||
File(project.buildDir, classesDirName)
|
||||
})
|
||||
|
||||
val resourcesTask = project.tasks.maybeCreate(compilation.processResourcesTaskName, ProcessResources::class.java)
|
||||
resourcesTask.description = "Processes $resourceSet."
|
||||
DslObject(resourcesTask).conventionMapping.map("destinationDir") { compilation.output.resourcesDir }
|
||||
resourcesTask.from(resourceSet)
|
||||
}
|
||||
|
||||
private fun createLifecycleTask(compilation: KotlinCompilation, project: Project) {
|
||||
(compilation.output.classesDirs as ConfigurableFileCollection).from(project.files().builtBy(compilation.compileAllTaskName))
|
||||
|
||||
project.tasks.create(compilation.compileAllTaskName).apply {
|
||||
group = LifecycleBasePlugin.BUILD_GROUP
|
||||
description = "Assembles " + compilation.output + "."
|
||||
dependsOn(
|
||||
compilation.output.dirs,
|
||||
compilation.compileKotlinTaskName
|
||||
)
|
||||
if (compilation is KotlinCompilationWithResources) {
|
||||
dependsOn(compilation.processResourcesTaskName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val KotlinCompilation.deprecatedCompileConfigurationName: String
|
||||
get() = disambiguateName("compile")
|
||||
|
||||
private val KotlinCompilationToRunnableFiles.deprecatedRuntimeConfigurationName: String
|
||||
get() = disambiguateName("runtime")
|
||||
|
||||
internal fun defineConfigurationsForCompilation(
|
||||
compilation: KotlinCompilation,
|
||||
target: KotlinTarget,
|
||||
configurations: ConfigurationContainer
|
||||
) {
|
||||
val compileConfiguration = configurations.maybeCreate(compilation.deprecatedCompileConfigurationName).apply {
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
description = "Dependencies for $compilation (deprecated, use '${compilation.implementationConfigurationName} ' instead)."
|
||||
}
|
||||
|
||||
val apiConfiguration = configurations.maybeCreate(compilation.apiConfigurationName).apply {
|
||||
extendsFrom(compileConfiguration)
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
description = "API dependencies for $compilation."
|
||||
}
|
||||
|
||||
val implementationConfiguration = configurations.maybeCreate(compilation.implementationConfigurationName).apply {
|
||||
extendsFrom(compileConfiguration, apiConfiguration)
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
description = "Implementation only dependencies for $compilation."
|
||||
}
|
||||
|
||||
val compileOnlyConfiguration = configurations.maybeCreate(compilation.compileOnlyConfigurationName).apply {
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
description = "Compile only dependencies for $compilation."
|
||||
}
|
||||
|
||||
val compileClasspathConfiguration = configurations.maybeCreate(compilation.compileDependencyConfigurationName).apply {
|
||||
extendsFrom(compileOnlyConfiguration, implementationConfiguration)
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
isCanBeConsumed = false
|
||||
attributes.attribute(USAGE_ATTRIBUTE, compilation.target.project.usageByName(Usage.JAVA_API))
|
||||
description = "Compile classpath for $compilation."
|
||||
}
|
||||
|
||||
compilation.compileDependencyFiles = compileClasspathConfiguration
|
||||
|
||||
if (compilation is KotlinCompilationToRunnableFiles) {
|
||||
val runtimeConfiguration = configurations.maybeCreate(compilation.deprecatedRuntimeConfigurationName).apply {
|
||||
extendsFrom(compileConfiguration)
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
description =
|
||||
"Runtime dependencies for $compilation (deprecated, use '${compilation.runtimeOnlyConfigurationName} ' instead)."
|
||||
}
|
||||
|
||||
val runtimeOnlyConfiguration = configurations.maybeCreate(compilation.runtimeOnlyConfigurationName).apply {
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
description = "Runtime only dependencies for $compilation."
|
||||
}
|
||||
|
||||
val runtimeClasspathConfiguration = configurations.maybeCreate(compilation.runtimeDependencyConfigurationName).apply {
|
||||
extendsFrom(runtimeOnlyConfiguration, runtimeConfiguration, implementationConfiguration)
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
attributes.attribute(USAGE_ATTRIBUTE, compilation.target.project.usageByName(Usage.JAVA_RUNTIME))
|
||||
description = "Runtime classpath of $compilation."
|
||||
}
|
||||
|
||||
compilation.runtimeDependencyFiles = compilation.output.plus(runtimeClasspathConfiguration)
|
||||
}
|
||||
}
|
||||
|
||||
private fun defineConfigurationsForTarget(project: Project, target: KotlinOnlyTarget<*>) {
|
||||
val configurations = project.configurations
|
||||
|
||||
val defaultConfiguration = configurations.maybeCreate(target.defaultConfigurationName)
|
||||
val mainCompilation = target.compilations.maybeCreate(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||
val testCompilation = target.compilations.maybeCreate(KotlinCompilation.TEST_COMPILATION_NAME)
|
||||
|
||||
val compileConfiguration = configurations.maybeCreate(mainCompilation.deprecatedCompileConfigurationName)
|
||||
val implementationConfiguration = configurations.maybeCreate(mainCompilation.implementationConfigurationName)
|
||||
|
||||
val runtimeOnlyConfiguration = configurations.maybeCreate(mainCompilation.runtimeOnlyConfigurationName)
|
||||
val compileTestsConfiguration = configurations.maybeCreate(testCompilation.deprecatedCompileConfigurationName)
|
||||
val testImplementationConfiguration = configurations.maybeCreate(testCompilation.implementationConfigurationName)
|
||||
val testRuntimeOnlyConfiguration = configurations.maybeCreate(testCompilation.runtimeOnlyConfigurationName)
|
||||
|
||||
compileTestsConfiguration.extendsFrom(compileConfiguration).usesPlatformOf(target)
|
||||
testImplementationConfiguration.extendsFrom(implementationConfiguration).usesPlatformOf(target)
|
||||
testRuntimeOnlyConfiguration.extendsFrom(runtimeOnlyConfiguration).usesPlatformOf(target)
|
||||
|
||||
configurations.maybeCreate(target.apiElementsConfigurationName).apply {
|
||||
description = "API elements for main."
|
||||
isVisible = false
|
||||
isCanBeResolved = false
|
||||
isCanBeConsumed = true
|
||||
attributes.attribute<Usage>(USAGE_ATTRIBUTE, project.usageByName(Usage.JAVA_API))
|
||||
extendsFrom(configurations.maybeCreate(mainCompilation.apiConfigurationName))
|
||||
if (mainCompilation is KotlinCompilationToRunnableFiles) {
|
||||
val runtimeConfiguration = configurations.maybeCreate(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||
extendsFrom(runtimeConfiguration)
|
||||
}
|
||||
usesPlatformOf(target)
|
||||
}
|
||||
|
||||
val runtimeElementsConfiguration = configurations.maybeCreate(target.runtimeElementsConfigurationName).apply {
|
||||
description = "Elements of runtime for main."
|
||||
isVisible = false
|
||||
isCanBeConsumed = true
|
||||
isCanBeResolved = false
|
||||
attributes.attribute<Usage>(USAGE_ATTRIBUTE, project.usageByName(Usage.JAVA_RUNTIME_JARS))
|
||||
if (mainCompilation is KotlinCompilationToRunnableFiles) {
|
||||
val runtimeConfiguration = configurations.maybeCreate(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||
extendsFrom(implementationConfiguration, runtimeOnlyConfiguration, runtimeConfiguration)
|
||||
}
|
||||
usesPlatformOf(target)
|
||||
}
|
||||
|
||||
if (mainCompilation is KotlinCompilationToRunnableFiles && testCompilation is KotlinCompilationToRunnableFiles) {
|
||||
val runtimeConfiguration = configurations.maybeCreate(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||
val testRuntimeConfiguration = configurations.maybeCreate(testCompilation.deprecatedRuntimeConfigurationName)
|
||||
testRuntimeConfiguration.extendsFrom(runtimeConfiguration).usesPlatformOf(target)
|
||||
}
|
||||
|
||||
defaultConfiguration.extendsFrom(runtimeElementsConfiguration).usesPlatformOf(target)
|
||||
}
|
||||
|
||||
|
||||
private fun configureBuild(project: Project, target: KotlinOnlyTarget<*>) {
|
||||
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME)
|
||||
project.tasks.maybeCreate(buildNeededTaskName, DefaultTask::class.java).apply {
|
||||
description = "Assembles and tests this project and all projects it depends on."
|
||||
group = "build"
|
||||
dependsOn("build")
|
||||
if (testCompilation is KotlinCompilationToRunnableFiles) {
|
||||
addDependsOnTaskInOtherProjects(this@apply, true, name, testCompilation.deprecatedRuntimeConfigurationName)
|
||||
}
|
||||
}
|
||||
|
||||
project.tasks.maybeCreate(buildDependentTaskName, DefaultTask::class.java).apply {
|
||||
setDescription("Assembles and tests this project and all projects that depend on it.")
|
||||
setGroup("build")
|
||||
dependsOn("build")
|
||||
doFirst {
|
||||
if (!project.gradle.includedBuilds.isEmpty()) {
|
||||
project.logger.warn("[composite-build] Warning: `" + path + "` task does not build included builds.")
|
||||
}
|
||||
}
|
||||
if (testCompilation is KotlinCompilationToRunnableFiles) {
|
||||
addDependsOnTaskInOtherProjects(this@apply, false, name, testCompilation.deprecatedRuntimeConfigurationName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addDependsOnTaskInOtherProjects(
|
||||
task: Task, useDependedOn: Boolean, otherProjectTaskName: String,
|
||||
configurationName: String
|
||||
) {
|
||||
val project = task.project
|
||||
val configuration = project.configurations.getByName(configurationName)
|
||||
task.dependsOn(configuration.getTaskDependencyFromProjectDependency(useDependedOn, otherProjectTaskName))
|
||||
}
|
||||
|
||||
private fun setCompatibilityOfAbstractCompileTasks(project: Project) = with (project) {
|
||||
tasks.withType(AbstractKotlinCompile::class.java).all {
|
||||
// Workaround: these are input properties and should not hold null values:
|
||||
it.targetCompatibility = ""
|
||||
it.sourceCompatibility = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal companion object {
|
||||
const val buildNeededTaskName = "buildAllNeeded"
|
||||
const val buildDependentTaskName = "buildAllDependents"
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Project.usageByName(usageName: String): Usage =
|
||||
if (isGradleVersionAtLeast(4, 0)) {
|
||||
// `project.objects` is an API introduced in Gradle 4.0
|
||||
project.objects.named(Usage::class.java, usageName)
|
||||
} else {
|
||||
val usagesClass = Class.forName("org.gradle.api.internal.attributes")
|
||||
val usagesMethod = usagesClass.getMethod("usage", String::class.java)
|
||||
usagesMethod(null, usageName) as Usage
|
||||
}
|
||||
|
||||
fun Configuration.usesPlatformOf(target: KotlinTarget): Configuration {
|
||||
attributes.attribute(KotlinPlatformType.attribute, target.platformType)
|
||||
return this
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import java.util.*
|
||||
|
||||
// TODO better implementation: attribute invariants (no attrs with same name and different types), thread safety?
|
||||
class HierarchyAttributeContainer(val parent: AttributeContainer?) : AttributeContainer {
|
||||
private val attributesMap = Collections.synchronizedMap(mutableMapOf<Attribute<*>, Any>())
|
||||
|
||||
override fun contains(key: Attribute<*>): Boolean =
|
||||
attributesMap.contains(key) || parent?.contains(key) ?: false
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Any?> getAttribute(key: Attribute<T>?): T? =
|
||||
attributesMap.get(key as Attribute<*>) as T? ?: parent?.getAttribute(key)
|
||||
|
||||
override fun isEmpty(): Boolean = attributesMap.isEmpty() && parent?.isEmpty ?: false
|
||||
|
||||
override fun keySet(): Set<Attribute<*>> = attributesMap.keys + parent?.keySet().orEmpty()
|
||||
|
||||
override fun <T : Any?> attribute(key: Attribute<T>?, value: T): AttributeContainer {
|
||||
val checkedValue = requireNotNull(value as Any?) { "null values for attributes are not supported" }
|
||||
attributesMap[key as Attribute<*>] = checkedValue
|
||||
return this
|
||||
}
|
||||
|
||||
override fun getAttributes(): AttributeContainer = this
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
|
||||
internal fun KotlinCompilation.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||
val compilationNamePart = compilationName.takeIf { it != "main" }
|
||||
val targetNamePart = target.disambiguationClassifier
|
||||
|
||||
return lowerCamelCaseName(prefix, targetNamePart, compilationNamePart, suffix)
|
||||
}
|
||||
|
||||
internal val KotlinCompilation.fullName: String
|
||||
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName)
|
||||
|
||||
internal class DefaultKotlinDependencyHandler(
|
||||
val parent: HasKotlinDependencies,
|
||||
val project: Project
|
||||
) : KotlinDependencyHandler {
|
||||
override fun api(dependencyNotation: Any) = addDependency(parent.apiConfigurationName, dependencyNotation)
|
||||
|
||||
override fun implementation(dependencyNotation: Any) = addDependency(parent.implementationConfigurationName, dependencyNotation)
|
||||
|
||||
override fun compileOnly(dependencyNotation: Any) = addDependency(parent.compileOnlyConfigurationName, dependencyNotation)
|
||||
|
||||
override fun runtimeOnly(dependencyNotation: Any) = addDependency(parent.runtimeOnlyConfigurationName, dependencyNotation)
|
||||
|
||||
private fun addDependency(configurationName: String, dependencyNotation: Any) {
|
||||
project.dependencies.add(configurationName, dependencyNotation)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractKotlinCompilation<T : KotlinTarget>(
|
||||
final override val target: T,
|
||||
override val compilationName: String
|
||||
) : KotlinCompilation, HasKotlinDependencies {
|
||||
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
|
||||
|
||||
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||
|
||||
override val kotlinSourceSets: MutableList<KotlinSourceSet> = mutableListOf()
|
||||
|
||||
override fun source(sourceSet: KotlinSourceSet) {
|
||||
kotlinSourceSets += sourceSet
|
||||
|
||||
with(target.project) {
|
||||
whenEvaluated {
|
||||
(target.project.tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(sourceSet.kotlin)
|
||||
}
|
||||
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName)
|
||||
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName)
|
||||
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName)
|
||||
if (this is KotlinCompilationToRunnableFiles) {
|
||||
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun Project.addExtendsFromRelation(extendingConfigurationName: String, extendsFromConfigurationName: String) {
|
||||
if (extendingConfigurationName != extendsFromConfigurationName) {
|
||||
if (project.configurations.findByName(extendingConfigurationName) != null)
|
||||
project.dependencies.add(extendingConfigurationName, project.configurations.getByName(extendsFromConfigurationName))
|
||||
}
|
||||
}
|
||||
|
||||
override val compileDependencyConfigurationName: String
|
||||
get() = lowerCamelCaseName(compilationName.takeIf { it != "main" }.orEmpty(), target.disambiguationClassifier, "compileClasspath")
|
||||
|
||||
override val compileKotlinTaskName: String
|
||||
get() = lowerCamelCaseName("compile", compilationName.takeIf { it != "main" }.orEmpty(), "Kotlin", target.disambiguationClassifier)
|
||||
|
||||
override val compileAllTaskName: String
|
||||
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName.takeIf { it != "main" }.orEmpty(), "classes")
|
||||
|
||||
override lateinit var compileDependencyFiles: FileCollection
|
||||
|
||||
override val apiConfigurationName: String
|
||||
get() = disambiguateName("api")
|
||||
|
||||
override val implementationConfigurationName: String
|
||||
get() = disambiguateName("implementation")
|
||||
|
||||
override val compileOnlyConfigurationName: String
|
||||
get() = disambiguateName("compileOnly")
|
||||
|
||||
override val runtimeOnlyConfigurationName: String
|
||||
get() = disambiguateName("runtimeOnly")
|
||||
|
||||
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||
DefaultKotlinDependencyHandler(this, target.project).run(configure)
|
||||
|
||||
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||
dependencies f@{ this@f.executeClosure(configureClosure) }
|
||||
|
||||
override fun toString(): String = "compilation '$compilationName' ($target)"
|
||||
}
|
||||
|
||||
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinTarget>(target: T, name: String)
|
||||
: AbstractKotlinCompilation<T>(target, name), KotlinCompilationToRunnableFiles {
|
||||
override val runtimeDependencyConfigurationName: String
|
||||
get() = lowerCamelCaseName(compilationName, target.disambiguationClassifier, "runtimeClasspath")
|
||||
|
||||
override lateinit var runtimeDependencyFiles: FileCollection
|
||||
}
|
||||
|
||||
internal fun KotlinCompilation.disambiguateName(simpleName: String): String {
|
||||
return lowerCamelCaseName(
|
||||
target.disambiguationClassifier,
|
||||
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||
simpleName
|
||||
)
|
||||
}
|
||||
|
||||
open class KotlinJvmCompilation(
|
||||
target: KotlinTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
) : AbstractKotlinCompilationToRunnableFiles<KotlinTarget>(target, name), KotlinCompilationWithResources {
|
||||
override val processResourcesTaskName: String
|
||||
get() = disambiguateName("processResources")
|
||||
}
|
||||
|
||||
class KotlinWithJavaCompilation(
|
||||
target: KotlinWithJavaTarget,
|
||||
name: String,
|
||||
val javaSourceSet: SourceSet
|
||||
) : AbstractKotlinCompilationToRunnableFiles<KotlinWithJavaTarget>(target, name), KotlinCompilationWithResources {
|
||||
override val output: SourceSetOutput
|
||||
get() = javaSourceSet.output
|
||||
|
||||
override val processResourcesTaskName: String
|
||||
get() = javaSourceSet.processResourcesTaskName
|
||||
|
||||
override var runtimeDependencyFiles: FileCollection
|
||||
get() = javaSourceSet.runtimeClasspath
|
||||
set(value) { javaSourceSet.runtimeClasspath = value }
|
||||
|
||||
override val runtimeDependencyConfigurationName: String
|
||||
get() = javaSourceSet.runtimeClasspathConfigurationName
|
||||
|
||||
override val compileDependencyConfigurationName: String
|
||||
get() = javaSourceSet.compileClasspathConfigurationName
|
||||
|
||||
override val runtimeOnlyConfigurationName: String
|
||||
get() = javaSourceSet.runtimeOnlyConfigurationName
|
||||
|
||||
override val implementationConfigurationName: String
|
||||
get() = javaSourceSet.implementationConfigurationName
|
||||
|
||||
override val apiConfigurationName: String
|
||||
get() = javaSourceSet.apiConfigurationName
|
||||
|
||||
override val compileOnlyConfigurationName: String
|
||||
get() = javaSourceSet.compileOnlyConfigurationName
|
||||
|
||||
override val compileAllTaskName: String
|
||||
get() = javaSourceSet.classesTaskName
|
||||
|
||||
override var compileDependencyFiles: FileCollection
|
||||
get() = javaSourceSet.compileClasspath
|
||||
set(value) { javaSourceSet.compileClasspath = value }
|
||||
|
||||
fun source(javaSourceSet: SourceSet) {
|
||||
with(target.project) {
|
||||
afterEvaluate {
|
||||
(tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(javaSourceSet.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinJvmAndroidCompilation(
|
||||
target: KotlinAndroidTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
): AbstractKotlinCompilation<KotlinAndroidTarget>(target, name)
|
||||
|
||||
class KotlinJsCompilation(
|
||||
target: KotlinTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
) : AbstractKotlinCompilation<KotlinTarget>(target, name)
|
||||
|
||||
class KotlinCommonCompilation(
|
||||
target: KotlinTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
) : AbstractKotlinCompilation<KotlinTarget>(target, name)
|
||||
|
||||
class KotlinNativeCompilation(
|
||||
target: KotlinNativeTarget,
|
||||
name: String,
|
||||
override val output: SourceSetOutput
|
||||
) : AbstractKotlinCompilationToRunnableFiles<KotlinNativeTarget>(target, name) {
|
||||
|
||||
val linkAllTaskName: String
|
||||
get() = lowerCamelCaseName("link", compilationName.takeIf { it != "main" }.orEmpty(), target.disambiguationClassifier)
|
||||
|
||||
var isTestCompilation = false
|
||||
|
||||
// Native-specific DSL.
|
||||
val extraOpts = mutableListOf<String>()
|
||||
|
||||
fun extraOpts(vararg values: Any) = extraOpts(values.toList())
|
||||
fun extraOpts(values: List<Any>) {
|
||||
extraOpts.addAll(values.map { it.toString() })
|
||||
}
|
||||
|
||||
var buildTypes = mutableListOf<NativeBuildType>()
|
||||
var outputKinds = mutableListOf<NativeOutputKind>()
|
||||
|
||||
// TODO: Integrate with Big Kotlin tasks and runners and remove this method.
|
||||
override fun source(sourceSet: KotlinSourceSet) {
|
||||
kotlinSourceSets += sourceSet
|
||||
|
||||
with(target.project) {
|
||||
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName)
|
||||
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName)
|
||||
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName)
|
||||
if (this is KotlinCompilationToRunnableFiles) {
|
||||
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Can we do it better?
|
||||
companion object {
|
||||
val DEBUG = NativeBuildType.DEBUG
|
||||
val RELEASE = NativeBuildType.RELEASE
|
||||
|
||||
val EXECUTABLE = NativeOutputKind.EXECUTABLE
|
||||
val FRAMEWORK = NativeOutputKind.FRAMEWORK
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.NamedDomainObjectCollection
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.internal.file.FileResolver
|
||||
import org.gradle.api.internal.plugins.DslObject
|
||||
import org.gradle.api.plugins.BasePlugin
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
|
||||
import org.gradle.internal.cleanup.BuildOutputCleanupRegistry
|
||||
import org.gradle.internal.reflect.Instantiator
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
internal val Project.multiplatformExtension get(): KotlinMultiplatformExtension? =
|
||||
project.extensions.getByName("kotlin") as KotlinMultiplatformExtension
|
||||
|
||||
internal class KotlinMultiplatformPlugin(
|
||||
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry,
|
||||
private val fileResolver: FileResolver,
|
||||
private val instantiator: Instantiator,
|
||||
private val kotlinPluginVersion: String
|
||||
) : Plugin<Project> {
|
||||
|
||||
private class TargetFromPresetExtension(val targetsContainer: NamedDomainObjectCollection<KotlinTarget>) {
|
||||
fun <T : KotlinTarget> fromPreset(preset: KotlinTargetPreset<T>, name: String, configureClosure: Closure<*>): T =
|
||||
fromPreset(preset, name, { executeClosure(configureClosure) })
|
||||
|
||||
@JvmOverloads
|
||||
fun <T : KotlinTarget> fromPreset(preset: KotlinTargetPreset<T>, name: String, configureAction: T.() -> Unit = { }): T {
|
||||
val target = preset.createTarget(name)
|
||||
targetsContainer.add(target)
|
||||
target.run(configureAction)
|
||||
return target
|
||||
}
|
||||
}
|
||||
|
||||
override fun apply(project: Project) {
|
||||
project.plugins.apply(BasePlugin::class.java)
|
||||
|
||||
val targetsContainer = project.container(KotlinTarget::class.java)
|
||||
val targetsFromPreset = TargetFromPresetExtension(targetsContainer)
|
||||
|
||||
project.extensions.getByType(KotlinMultiplatformExtension::class.java).apply {
|
||||
DslObject(targetsContainer).addConvention("fromPreset", targetsFromPreset)
|
||||
|
||||
targets = targetsContainer
|
||||
addExtension("targets", targets)
|
||||
|
||||
presets = project.container(KotlinTargetPreset::class.java)
|
||||
addExtension("presets", presets)
|
||||
}
|
||||
|
||||
setupDefaultPresets(project)
|
||||
configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion)
|
||||
configureSourceSets(project)
|
||||
|
||||
setUpConfigurationAttributes(project)
|
||||
configurePublishingWithMavenPublish(project)
|
||||
}
|
||||
|
||||
fun setupDefaultPresets(project: Project) {
|
||||
with((project.kotlinExtension as KotlinMultiplatformExtension).presets) {
|
||||
add(KotlinUniversalTargetPreset(project, instantiator, fileResolver, buildOutputCleanupRegistry, kotlinPluginVersion))
|
||||
add(KotlinJvmTargetPreset(project, instantiator, fileResolver, buildOutputCleanupRegistry, kotlinPluginVersion))
|
||||
add(KotlinJsTargetPreset(project, instantiator, fileResolver, buildOutputCleanupRegistry, kotlinPluginVersion))
|
||||
add(KotlinAndroidTargetPreset(project, kotlinPluginVersion, buildOutputCleanupRegistry))
|
||||
add(KotlinJvmWithJavaTargetPreset(project, kotlinPluginVersion))
|
||||
HostManager().targets.forEach { name, target ->
|
||||
add(KotlinNativeTargetPreset(name, project, target.toKotlinPlatformType(), buildOutputCleanupRegistry))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") {
|
||||
val targets = project.multiplatformExtension!!.targets
|
||||
val kotlinSoftwareComponent = KotlinSoftwareComponent(project, "kotlin", targets)
|
||||
|
||||
project.afterEvaluate { project -> // Use afterEvaluate because publications configuration is no more lazy since Gradle 4.9
|
||||
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
||||
publishing.publications.create("kotlinCompositeLibrary", MavenPublication::class.java) { publication ->
|
||||
publication.from(kotlinSoftwareComponent)
|
||||
(publication as MavenPublicationInternal).publishWithOriginalFileName()
|
||||
publication.artifactId = project.name
|
||||
publication.groupId = project.group.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureSourceSets(project: Project) = with (project.kotlinExtension as KotlinMultiplatformExtension) {
|
||||
sourceSets.all { defineSourceSetConfigurations(project, it) }
|
||||
val production = sourceSets.create(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||
val test = sourceSets.create(KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME)
|
||||
|
||||
targets.all {
|
||||
it.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME)?.source(production)
|
||||
it.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME)?.source(test)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpConfigurationAttributes(project: Project) {
|
||||
val targets = (project.kotlinExtension as KotlinMultiplatformExtension).targets
|
||||
|
||||
project.afterEvaluate {
|
||||
targets.all { target ->
|
||||
val compilationAttributes = target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME)?.attributes
|
||||
?: return@all
|
||||
|
||||
fun <T> copyAttribute(key: Attribute<T>, from: AttributeContainer, to: AttributeContainer) {
|
||||
to.attribute(key, from.getAttribute(key)!!)
|
||||
}
|
||||
|
||||
listOf(
|
||||
target.apiElementsConfigurationName,
|
||||
target.runtimeElementsConfigurationName,
|
||||
target.defaultConfigurationName
|
||||
)
|
||||
.mapNotNull { configurationName -> target.project.configurations.findByName(configurationName) }
|
||||
.forEach { configuration ->
|
||||
compilationAttributes.keySet().forEach { key ->
|
||||
copyAttribute(key, compilationAttributes, configuration.attributes)
|
||||
}
|
||||
}
|
||||
|
||||
target.compilations.all { compilation ->
|
||||
compilation.relatedConfigurationNames
|
||||
.mapNotNull { configurationName -> target.project.configurations.findByName(configurationName) }
|
||||
.forEach { configuration ->
|
||||
compilationAttributes.keySet().forEach { key ->
|
||||
copyAttribute(key, compilationAttributes, configuration.attributes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun defineSourceSetConfigurations(project: Project, sourceSet: KotlinSourceSet) = with (project.configurations) {
|
||||
sourceSet.relatedConfigurationNames.forEach { configurationName ->
|
||||
maybeCreate(configurationName)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact
|
||||
import org.gradle.api.internal.file.FileResolver
|
||||
import org.gradle.api.plugins.BasePlugin
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.internal.cleanup.BuildOutputCleanupRegistry
|
||||
import org.gradle.internal.reflect.Instantiator
|
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||
import org.gradle.nativeplatform.test.tasks.RunTestExecutable
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.sourceSetProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.base.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
import org.jetbrains.kotlin.gradle.utils.setClassesDirCompatible
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation>(
|
||||
protected val project: Project,
|
||||
private val instantiator: Instantiator,
|
||||
private val fileResolver: FileResolver,
|
||||
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry,
|
||||
protected val kotlinPluginVersion: String
|
||||
) : KotlinTargetPreset<KotlinOnlyTarget<T>> {
|
||||
|
||||
override fun createTarget(name: String): KotlinOnlyTarget<T> {
|
||||
val result = KotlinOnlyTarget<T>(project, platformType).apply {
|
||||
targetName = name
|
||||
disambiguationClassifier = name
|
||||
|
||||
val compilationFactory = createCompilationFactory(this)
|
||||
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||
}
|
||||
|
||||
KotlinOnlyTargetConfigurator(buildOutputCleanupRegistry).configureTarget(project, result)
|
||||
|
||||
result.compilations.all { compilation ->
|
||||
buildCompilationProcessor(compilation).run()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
protected abstract fun createCompilationFactory(forTarget: KotlinOnlyTarget<T>): KotlinCompilationFactory<T>
|
||||
protected abstract val platformType: KotlinPlatformType
|
||||
internal abstract fun buildCompilationProcessor(compilation: T): KotlinSourceSetProcessor<*>
|
||||
}
|
||||
|
||||
class KotlinUniversalTargetPreset(
|
||||
project: Project,
|
||||
instantiator: Instantiator,
|
||||
fileResolver: FileResolver,
|
||||
buildOutputCleanupRegistry: BuildOutputCleanupRegistry,
|
||||
kotlinPluginVersion: String
|
||||
) : KotlinOnlyTargetPreset<KotlinCommonCompilation>(
|
||||
project,
|
||||
instantiator,
|
||||
fileResolver,
|
||||
buildOutputCleanupRegistry,
|
||||
kotlinPluginVersion
|
||||
) {
|
||||
override fun getName(): String = PRESET_NAME
|
||||
|
||||
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinCommonCompilation>)
|
||||
: KotlinCompilationFactory<KotlinCommonCompilation> =
|
||||
KotlinCommonCompilationFactory(project, forTarget)
|
||||
|
||||
override val platformType: KotlinPlatformType
|
||||
get() = KotlinPlatformType.COMMON
|
||||
|
||||
override fun buildCompilationProcessor(compilation: KotlinCommonCompilation): KotlinSourceSetProcessor<*> =
|
||||
KotlinCommonSourceSetProcessor(
|
||||
project,
|
||||
compilation,
|
||||
KotlinCommonTasksProvider(),
|
||||
kotlinPluginVersion
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val PRESET_NAME = "universal"
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinJvmTargetPreset(
|
||||
project: Project,
|
||||
instantiator: Instantiator,
|
||||
fileResolver: FileResolver,
|
||||
buildOutputCleanupRegistry: BuildOutputCleanupRegistry,
|
||||
kotlinPluginVersion: String
|
||||
) : KotlinOnlyTargetPreset<KotlinJvmCompilation>(
|
||||
project,
|
||||
instantiator,
|
||||
fileResolver,
|
||||
buildOutputCleanupRegistry,
|
||||
kotlinPluginVersion
|
||||
) {
|
||||
override fun getName(): String = PRESET_NAME
|
||||
|
||||
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJvmCompilation>): KotlinCompilationFactory<KotlinJvmCompilation> =
|
||||
KotlinJvmCompilationFactory(project, forTarget)
|
||||
|
||||
override val platformType: KotlinPlatformType
|
||||
get() = KotlinPlatformType.JVM
|
||||
|
||||
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> =
|
||||
Kotlin2JvmSourceSetProcessor(project, KotlinTasksProvider(), compilation, kotlinPluginVersion)
|
||||
|
||||
companion object {
|
||||
const val PRESET_NAME = "jvm"
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinJsTargetPreset(
|
||||
project: Project,
|
||||
instantiator: Instantiator,
|
||||
fileResolver: FileResolver,
|
||||
buildOutputCleanupRegistry: BuildOutputCleanupRegistry,
|
||||
kotlinPluginVersion: String
|
||||
) : KotlinOnlyTargetPreset<KotlinJsCompilation>(
|
||||
project,
|
||||
instantiator,
|
||||
fileResolver,
|
||||
buildOutputCleanupRegistry,
|
||||
kotlinPluginVersion
|
||||
) {
|
||||
override fun getName(): String = PRESET_NAME
|
||||
|
||||
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJsCompilation>) =
|
||||
KotlinJsCompilationFactory(project, forTarget)
|
||||
|
||||
override val platformType: KotlinPlatformType
|
||||
get() = KotlinPlatformType.JS
|
||||
|
||||
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> =
|
||||
Kotlin2JsSourceSetProcessor(project, Kotlin2JsTasksProvider(), compilation, kotlinPluginVersion)
|
||||
|
||||
companion object {
|
||||
const val PRESET_NAME = "js"
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinAndroidTargetPreset(
|
||||
private val project: Project,
|
||||
private val kotlinPluginVersion: String,
|
||||
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry
|
||||
) : KotlinTargetPreset<KotlinAndroidTarget> {
|
||||
|
||||
override fun getName(): String = PRESET_NAME
|
||||
|
||||
override fun createTarget(name: String): KotlinAndroidTarget {
|
||||
val result = KotlinAndroidTarget(project).apply {
|
||||
disambiguationClassifier = name
|
||||
|
||||
val targetConfigurator = KotlinOnlyTargetConfigurator(buildOutputCleanupRegistry)
|
||||
compilations.all { compilation ->
|
||||
targetConfigurator.defineConfigurationsForCompilation(compilation, this@apply, project.configurations)
|
||||
}
|
||||
}
|
||||
|
||||
KotlinAndroidPlugin.applyToTarget(
|
||||
project, result, project.kotlinExtension.sourceSetProvider,
|
||||
AndroidTasksProvider(), kotlinPluginVersion
|
||||
)
|
||||
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PRESET_NAME = "android"
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinJvmWithJavaTargetPreset(
|
||||
private val project: Project,
|
||||
private val kotlinPluginVersion: String
|
||||
): KotlinTargetPreset<KotlinWithJavaTarget> {
|
||||
|
||||
override fun getName(): String = PRESET_NAME
|
||||
|
||||
override fun createTarget(name: String): KotlinWithJavaTarget {
|
||||
project.plugins.apply(JavaPlugin::class.java)
|
||||
|
||||
val target = KotlinWithJavaTarget(project, KotlinPlatformType.JVM, name)
|
||||
|
||||
AbstractKotlinPlugin.configureTarget(target) { compilation ->
|
||||
Kotlin2JvmSourceSetProcessor(
|
||||
project,
|
||||
KotlinTasksProvider(),
|
||||
compilation as KotlinJvmCompilation,
|
||||
kotlinPluginVersion
|
||||
)
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PRESET_NAME = "jvmWithJava"
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinNativeTargetPreset(
|
||||
private val name: String,
|
||||
val project: Project,
|
||||
val platformType: KotlinNativePlatformType,
|
||||
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry
|
||||
) : KotlinTargetPreset<KotlinNativeTarget> {
|
||||
|
||||
override fun getName(): String = name
|
||||
|
||||
private val Collection<*>.isDimensionVisible: Boolean
|
||||
get() = size > 1
|
||||
|
||||
private fun createDimensionSuffix(dimensionName: String, multivalueProperty: Collection<*>): String =
|
||||
if (multivalueProperty.isDimensionVisible) {
|
||||
dimensionName.toLowerCase().capitalize()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
private fun Task.dependsOnCompilerDownloading() {
|
||||
val checkCompilerTask = project.tasks.maybeCreate(
|
||||
KonanCompilerDownloadTask.KONAN_DOWNLOAD_TASK_NAME,
|
||||
KonanCompilerDownloadTask::class.java
|
||||
)
|
||||
dependsOn(checkCompilerTask)
|
||||
}
|
||||
|
||||
private fun createKlibCompilationTask(compilation: KotlinNativeCompilation) {
|
||||
val compileTask = project.tasks.create(
|
||||
compilation.compileKotlinTaskName,
|
||||
KotlinNativeCompile::class.java
|
||||
).apply {
|
||||
this.compilation = compilation
|
||||
outputKind = CompilerOutputKind.LIBRARY
|
||||
group = BasePlugin.BUILD_GROUP
|
||||
description = "Compiles a klibrary from the '${compilation.name}' " +
|
||||
"compilation for target '${compilation.platformType.name}'"
|
||||
|
||||
outputFile.set {
|
||||
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||
val compilationName = compilation.compilationName
|
||||
val klibName = if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||
project.name
|
||||
else
|
||||
compilationName
|
||||
File(project.buildDir, "classes/kotlin/$targetSubDirectory$compilationName/$klibName.klib")
|
||||
}
|
||||
|
||||
dependsOnCompilerDownloading()
|
||||
}
|
||||
|
||||
compilation.output.tryAddClassesDir { project.files(compileTask.outputFile.asFile.get()) }
|
||||
|
||||
project.tasks.getByName(compilation.compileAllTaskName).dependsOn(compileTask)
|
||||
if (compilation.compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||
project.tasks.findByName(compilation.target.artifactsTaskName)?.dependsOn(compileTask)
|
||||
val apiElements = project.configurations.getByName(compilation.target.apiElementsConfigurationName)
|
||||
apiElements.artifacts.add(
|
||||
DefaultPublishArtifact(
|
||||
compilation.name,
|
||||
"klib",
|
||||
"klib",
|
||||
"klib",
|
||||
Date(),
|
||||
compileTask.outputFile.asFile.get(),
|
||||
compileTask
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTestTask(compilation: KotlinNativeCompilation, testExecutableLinkTask: KotlinNativeCompile) {
|
||||
val taskName = lowerCamelCaseName("run", compilation.name, compilation.platformType.name)
|
||||
val testTask = project.tasks.create(taskName, RunTestExecutable::class.java).apply {
|
||||
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||
description = "Executes Kotlin/Native unit tests from the '${compilation.name}' compilation " +
|
||||
"for target '${compilation.platformType.name}'"
|
||||
|
||||
val testExecutableProperty = testExecutableLinkTask.outputFile
|
||||
executable = testExecutableProperty.asFile.get().absolutePath
|
||||
// TODO: Provide a normal test path!
|
||||
outputDir = project.layout.buildDirectory.dir("test-results").get().asFile
|
||||
|
||||
onlyIf { testExecutableProperty.asFile.get().exists() }
|
||||
inputs.file(testExecutableProperty)
|
||||
dependsOn(testExecutableLinkTask)
|
||||
dependsOnCompilerDownloading()
|
||||
}
|
||||
}
|
||||
|
||||
// Called in whenEvaluated block.
|
||||
private fun createBinaryLinkTasks(compilation: KotlinNativeCompilation) {
|
||||
val konanTarget = compilation.target.konanTarget
|
||||
val buildTypes = compilation.buildTypes
|
||||
val availableOutputKinds = compilation.outputKinds.filter { it.availableFor(konanTarget) }
|
||||
|
||||
// TODO: Consider using lockable set property.
|
||||
// TODO: Provide outgoing configurations somehow.
|
||||
for (buildType in compilation.buildTypes) {
|
||||
for (kind in availableOutputKinds) {
|
||||
val compilerOutputKind = kind.compilerOutputKind
|
||||
|
||||
val compilationSuffix = compilation.name.takeIf { it != "main" }.orEmpty()
|
||||
val buildTypeSuffix = createDimensionSuffix(buildType.name, buildTypes)
|
||||
val targetSuffix = compilation.target.name
|
||||
val taskName = lowerCamelCaseName("link", compilationSuffix, buildTypeSuffix, kind.taskNameClassifier, targetSuffix)
|
||||
|
||||
val linkTask = project.tasks.create(
|
||||
taskName,
|
||||
KotlinNativeCompile::class.java
|
||||
).apply {
|
||||
this.compilation = compilation
|
||||
outputKind = compilerOutputKind
|
||||
group = BasePlugin.BUILD_GROUP
|
||||
description = "Links ${kind.description} from the '${compilation.name}' " +
|
||||
"compilation for target '${compilation.platformType.name}'"
|
||||
|
||||
optimized = buildType.optimized
|
||||
debuggable = buildType.debuggable
|
||||
|
||||
outputFile.set {
|
||||
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||
val compilationName = compilation.compilationName
|
||||
val prefix = compilerOutputKind.prefix(konanTarget)
|
||||
val suffix = compilerOutputKind.suffix(konanTarget)
|
||||
File(project.buildDir, "bin/$targetSubDirectory$compilationName/$prefix$compilationName$suffix")
|
||||
}
|
||||
|
||||
dependsOnCompilerDownloading()
|
||||
}
|
||||
|
||||
project.tasks.maybeCreate(compilation.linkAllTaskName).dependsOn(linkTask)
|
||||
|
||||
if (compilation.isTestCompilation &&
|
||||
buildType == NativeBuildType.DEBUG &&
|
||||
konanTarget == HostManager.host
|
||||
) {
|
||||
createTestTask(compilation, linkTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createTarget(name: String): KotlinNativeTarget {
|
||||
val result = KotlinNativeTarget(project, platformType).apply {
|
||||
targetName = name
|
||||
disambiguationClassifier = name
|
||||
|
||||
val compilationFactory = KotlinNativeCompilationFactory(project, this)
|
||||
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||
}
|
||||
|
||||
KotlinOnlyTargetConfigurator(buildOutputCleanupRegistry).configureTarget(project, result)
|
||||
|
||||
// TODO: Move into KotlinNativeTargetConfigurator
|
||||
result.compilations.all { compilation ->
|
||||
createKlibCompilationTask(compilation)
|
||||
project.whenEvaluated {
|
||||
createBinaryLinkTasks(compilation)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.DependencyConstraint
|
||||
import org.gradle.api.artifacts.ModuleDependency
|
||||
import org.gradle.api.artifacts.PublishArtifact
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.capabilities.Capability
|
||||
import org.gradle.api.internal.component.SoftwareComponentInternal
|
||||
import org.gradle.api.internal.component.UsageContext
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.base.usageByName
|
||||
|
||||
class KotlinSoftwareComponent(
|
||||
private val project: Project,
|
||||
private val name: String,
|
||||
private val kotlinTargets: Iterable<KotlinTarget>
|
||||
) : SoftwareComponentInternal {
|
||||
override fun getUsages(): Set<UsageContext> = kotlinTargets.flatMap { it.createUsageContexts() }.toSet()
|
||||
|
||||
override fun getName(): String = name
|
||||
|
||||
companion object {
|
||||
fun kotlinApiUsage(project: Project) = project.usageByName(Usage.JAVA_API)
|
||||
fun kotlinRuntimeUsage(project: Project) = project.usageByName(Usage.JAVA_RUNTIME)
|
||||
}
|
||||
}
|
||||
|
||||
internal class KotlinPlatformUsageContext(
|
||||
val project: Project,
|
||||
val kotlinTarget: KotlinTarget,
|
||||
private val usage: Usage,
|
||||
val dependencyConfigurationName: String
|
||||
) : UsageContext {
|
||||
override fun getUsage(): Usage = usage
|
||||
|
||||
override fun getName(): String = kotlinTarget.targetName + when (usage.name) {
|
||||
Usage.JAVA_API -> "-api"
|
||||
Usage.JAVA_RUNTIME -> "-runtime"
|
||||
else -> error("unexpected usage")
|
||||
}
|
||||
|
||||
private val configuration: Configuration
|
||||
get() = project.configurations.getByName(dependencyConfigurationName)
|
||||
|
||||
override fun getDependencies(): MutableSet<out ModuleDependency> =
|
||||
configuration.incoming.dependencies.withType(ModuleDependency::class.java)
|
||||
|
||||
override fun getDependencyConstraints(): MutableSet<out DependencyConstraint> =
|
||||
configuration.incoming.dependencyConstraints
|
||||
|
||||
override fun getArtifacts(): MutableSet<out PublishArtifact> =
|
||||
// TODO Gradle Java plugin does that in a different way; check whether we can improve this
|
||||
configuration.artifacts
|
||||
|
||||
override fun getAttributes(): AttributeContainer =
|
||||
configuration.outgoing.attributes
|
||||
|
||||
override fun getCapabilities(): Set<Capability> = emptySet()
|
||||
|
||||
// FIXME this is a stub for a function that is not present in the Gradle API that we compile against
|
||||
fun getGlobalExcludes(): Set<Any> = emptySet()
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.internal.file.FileCollectionInternal
|
||||
import org.gradle.api.internal.file.FileCollectionVisitor
|
||||
import org.gradle.api.internal.file.FileSystemSubset
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import java.io.File
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
private class MutableReference<T>(var item: T)
|
||||
|
||||
class KotlinSourceSetOutput constructor(
|
||||
private val project: Project,
|
||||
private var resourcesDir: Any,
|
||||
private var backingFileCollection: ConfigurableFileCollection = project.files() // must be a parameter since it is used in delegation
|
||||
) : SourceSetOutput, ConfigurableFileCollection by backingFileCollection, FileCollectionInternal {
|
||||
|
||||
/* TODO report Gradle bug: cannot implement SourceSetOutput without also implementing FileCollectionInternal, there's a cast to the latter
|
||||
inside the Gradle logic for resolving file collections */
|
||||
override fun registerWatchPoints(p0: FileSystemSubset.Builder) = (backingFileCollection as FileCollectionInternal).registerWatchPoints(p0)
|
||||
override fun visitRootElements(p0: FileCollectionVisitor) = (backingFileCollection as FileCollectionInternal).visitRootElements(p0)
|
||||
|
||||
private val classesDirs: FileCollection = project.files()
|
||||
private val otherDirs: ConfigurableFileCollection = project.files()
|
||||
|
||||
init {
|
||||
this.from(classesDirs)
|
||||
this.from(Callable { resourcesDir })
|
||||
}
|
||||
|
||||
override fun setResourcesDir(dirNotation: Any) {
|
||||
resourcesDir = dirNotation
|
||||
}
|
||||
|
||||
override fun setResourcesDir(dir: File): Unit = setResourcesDir(dir as Any)
|
||||
|
||||
override fun getDirs(): FileCollection = otherDirs
|
||||
|
||||
override fun isLegacyLayout(): Boolean = false
|
||||
|
||||
override fun getResourcesDir(): File = project.file(resourcesDir)
|
||||
|
||||
override fun setClassesDir(file: File?) = @Suppress("DEPRECATION") setClassesDir(file as Any)
|
||||
|
||||
override fun setClassesDir(fileNotation: Any?) = throw UnsupportedOperationException("Setting classesDir is not supported, use classesDirs.")
|
||||
|
||||
override fun getClassesDir(): File = classesDirs.singleFile
|
||||
|
||||
override fun getClassesDirs(): FileCollection = classesDirs
|
||||
|
||||
override fun dir(args: Map<String, Any>, dir: Any?) {
|
||||
val dirFileCollection = project.files(dir)
|
||||
args["builtBy"]?.let { dirFileCollection.builtBy(it) }
|
||||
otherDirs.from(dirFileCollection)
|
||||
}
|
||||
|
||||
override fun dir(dirNotation: Any?): Unit = dir(emptyMap(), dirNotation)
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.internal.component.UsageContext
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinNativePlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.base.KotlinJvmAndroidCompilationFactory
|
||||
import org.jetbrains.kotlin.gradle.plugin.base.KotlinWithJavaCompilationFactory
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
abstract class AbstractKotlinTarget (
|
||||
override val project: Project
|
||||
) : KotlinTarget {
|
||||
private val attributeContainer = HierarchyAttributeContainer(parent = null)
|
||||
|
||||
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||
|
||||
override val defaultConfigurationName: String
|
||||
get() = disambiguateName("default")
|
||||
|
||||
override val apiElementsConfigurationName: String
|
||||
get() = disambiguateName("apiElements")
|
||||
|
||||
override val runtimeElementsConfigurationName: String
|
||||
get() = disambiguateName("runtimeElements")
|
||||
|
||||
override val artifactsTaskName: String
|
||||
get() = disambiguateName("jar")
|
||||
|
||||
override fun toString(): String = "target $name ($platformType)"
|
||||
|
||||
override fun createUsageContexts(): Set<UsageContext> = setOf(
|
||||
KotlinPlatformUsageContext(project, this, KotlinSoftwareComponent.kotlinApiUsage(project), apiElementsConfigurationName),
|
||||
KotlinPlatformUsageContext(project, this, KotlinSoftwareComponent.kotlinRuntimeUsage(project), runtimeElementsConfigurationName)
|
||||
)
|
||||
}
|
||||
|
||||
internal fun KotlinTarget.disambiguateName(simpleName: String) =
|
||||
lowerCamelCaseName(targetName, simpleName)
|
||||
|
||||
open class KotlinAndroidTarget(project: Project) : AbstractKotlinTarget(project) {
|
||||
override val targetName: String
|
||||
get() = "android"
|
||||
|
||||
override var disambiguationClassifier: String? = null
|
||||
internal set
|
||||
|
||||
override val platformType: KotlinPlatformType
|
||||
get() = KotlinPlatformType.JVM
|
||||
|
||||
private val compilationFactory = KotlinJvmAndroidCompilationFactory(project, this)
|
||||
|
||||
override val compilations: NamedDomainObjectContainer<out KotlinJvmAndroidCompilation> =
|
||||
project.container(compilationFactory.itemClass, compilationFactory)
|
||||
|
||||
override fun createUsageContexts(): Set<UsageContext> {
|
||||
//TODO setup Android libraries publishing. This will likely require new API in the Android Gradle plugin
|
||||
return emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
open class KotlinWithJavaTarget(
|
||||
project: Project,
|
||||
override val platformType: KotlinPlatformType,
|
||||
override val targetName: String
|
||||
) : AbstractKotlinTarget(project) {
|
||||
override var disambiguationClassifier: String? = null
|
||||
internal set
|
||||
|
||||
override val defaultConfigurationName: String
|
||||
get() = Dependency.DEFAULT_CONFIGURATION
|
||||
|
||||
override val apiElementsConfigurationName: String
|
||||
get() = JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME
|
||||
|
||||
override val runtimeElementsConfigurationName: String
|
||||
get() = JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME
|
||||
|
||||
override val artifactsTaskName: String
|
||||
get() = JavaPlugin.JAR_TASK_NAME
|
||||
|
||||
override val compilations: NamedDomainObjectContainer<KotlinWithJavaCompilation> =
|
||||
project.container(KotlinWithJavaCompilation::class.java, KotlinWithJavaCompilationFactory(project, this))
|
||||
}
|
||||
|
||||
open class KotlinOnlyTarget<T : KotlinCompilation>(
|
||||
project: Project,
|
||||
override val platformType: KotlinPlatformType
|
||||
) : AbstractKotlinTarget(project) {
|
||||
|
||||
override lateinit var compilations: NamedDomainObjectContainer<T>
|
||||
internal set
|
||||
|
||||
override lateinit var targetName: String
|
||||
internal set
|
||||
|
||||
override var disambiguationClassifier: String? = null
|
||||
internal set
|
||||
}
|
||||
|
||||
class KotlinNativeTarget(
|
||||
project: Project,
|
||||
override val platformType: KotlinNativePlatformType
|
||||
) : KotlinOnlyTarget<KotlinNativeCompilation>(project, platformType) {
|
||||
|
||||
val konanTarget: KonanTarget
|
||||
get() = platformType.konanTarget
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.Family
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
object KotlinNativeUsage {
|
||||
const val KLIB = "kotlin-native-klib"
|
||||
const val FRAMEWORK = "kotlin-native-framework"
|
||||
}
|
||||
|
||||
enum class NativeBuildType(val optimized: Boolean, val debuggable: Boolean): Named {
|
||||
RELEASE(true, false),
|
||||
DEBUG(false, true);
|
||||
|
||||
override fun getName(): String = name.toLowerCase()
|
||||
}
|
||||
|
||||
enum class NativeOutputKind(
|
||||
val compilerOutputKind: CompilerOutputKind,
|
||||
val taskNameClassifier: String,
|
||||
val description: String = taskNameClassifier,
|
||||
val additionalCompilerFlags: List<String> = emptyList(),
|
||||
val runtimeUsageName: String? = null,
|
||||
val linkUsageName: String? = null,
|
||||
val publishable: Boolean = true
|
||||
) {
|
||||
EXECUTABLE(
|
||||
CompilerOutputKind.PROGRAM,
|
||||
"executable",
|
||||
description = "an executable",
|
||||
runtimeUsageName = Usage.NATIVE_RUNTIME
|
||||
),
|
||||
FRAMEWORK(
|
||||
CompilerOutputKind.FRAMEWORK,
|
||||
"framework",
|
||||
description = "an Objective C framework",
|
||||
linkUsageName = KotlinNativeUsage.FRAMEWORK,
|
||||
publishable = false
|
||||
) {
|
||||
override fun availableFor(target: KonanTarget) =
|
||||
target.family == Family.OSX || target.family == Family.IOS
|
||||
};
|
||||
|
||||
open fun availableFor(target: KonanTarget) = true
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.sources
|
||||
|
||||
import org.gradle.api.NamedDomainObjectFactory
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.file.FileResolver
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import java.io.File
|
||||
|
||||
internal abstract class KotlinSourceSetFactory<T : KotlinSourceSet> internal constructor(
|
||||
protected val fileResolver: FileResolver,
|
||||
protected val project: Project
|
||||
) : NamedDomainObjectFactory<T> {
|
||||
|
||||
abstract val itemClass: Class<T>
|
||||
|
||||
override fun create(name: String): T {
|
||||
val result = doCreateSourceSet(name)
|
||||
setUpSourceSetDefaults(result)
|
||||
return result
|
||||
}
|
||||
|
||||
protected open fun defaultSourceLocation(sourceSetName: String): File =
|
||||
project.file("src/$sourceSetName")
|
||||
|
||||
protected open fun setUpSourceSetDefaults(sourceSet: T) {
|
||||
with(sourceSet) {
|
||||
sourceSet.kotlin.srcDir(File(defaultSourceLocation(sourceSet.name), "kotlin"))
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun doCreateSourceSet(name: String): T
|
||||
}
|
||||
|
||||
internal class DefaultKotlinSourceSetFactory(
|
||||
project: Project,
|
||||
fileResolver: FileResolver
|
||||
) : KotlinSourceSetFactory<DefaultKotlinSourceSet>(fileResolver, project) {
|
||||
|
||||
override val itemClass: Class<DefaultKotlinSourceSet>
|
||||
get() = DefaultKotlinSourceSet::class.java
|
||||
|
||||
override fun setUpSourceSetDefaults(sourceSet: DefaultKotlinSourceSet) {
|
||||
super.setUpSourceSetDefaults(sourceSet)
|
||||
sourceSet.resources.srcDir(File(defaultSourceLocation(sourceSet.name), "resources"))
|
||||
}
|
||||
|
||||
override fun doCreateSourceSet(name: String): DefaultKotlinSourceSet {
|
||||
return DefaultKotlinSourceSet(project, name, fileResolver)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.sources
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.internal.file.DefaultSourceDirectorySet
|
||||
import org.gradle.api.internal.file.FileResolver
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
||||
import org.jetbrains.kotlin.gradle.plugin.executeClosure
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSetWithResources
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
import java.lang.reflect.Constructor
|
||||
|
||||
abstract class AbstractKotlinSourceSet(
|
||||
val displayName: String,
|
||||
fileResolver: FileResolver
|
||||
) : KotlinSourceSet {
|
||||
override fun getName(): String = displayName
|
||||
|
||||
final override val kotlin: SourceDirectorySet =
|
||||
createDefaultSourceDirectorySet(name + " Kotlin source", fileResolver).apply {
|
||||
filter.include("**/*.java", "**/*.kt", "**/*.kts")
|
||||
}
|
||||
|
||||
final override fun kotlin(configureClosure: Closure<Any?>): SourceDirectorySet {
|
||||
ConfigureUtil.configure(configureClosure, kotlin)
|
||||
return kotlin
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KotlinSourceSet.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||
val sourceSetName = (if (name == "main") "" else name).let {
|
||||
if (prefix.isNullOrEmpty()) it else it.capitalize()
|
||||
}
|
||||
val resultPrefix = (prefix ?: "") + sourceSetName
|
||||
val resultSuffix = (if (resultPrefix.isEmpty()) suffix else suffix?.capitalize()) ?: ""
|
||||
return resultPrefix + resultSuffix
|
||||
}
|
||||
|
||||
class DefaultKotlinSourceSet(
|
||||
private val project: Project,
|
||||
val displayName: String,
|
||||
fileResolver: FileResolver
|
||||
) : KotlinSourceSetWithResources {
|
||||
|
||||
override val apiConfigurationName: String
|
||||
get() = disambiguateName("api")
|
||||
|
||||
override val implementationConfigurationName: String
|
||||
get() = disambiguateName("implementation")
|
||||
|
||||
override val compileOnlyConfigurationName: String
|
||||
get() = disambiguateName("compileOnly")
|
||||
|
||||
override val runtimeOnlyConfigurationName: String
|
||||
get() = disambiguateName("runtimeOnly")
|
||||
|
||||
override val kotlin: SourceDirectorySet = createDefaultSourceDirectorySet(displayName + ".kotlin", fileResolver)
|
||||
|
||||
override val resources: SourceDirectorySet = createDefaultSourceDirectorySet(displayName + ".resources", fileResolver)
|
||||
|
||||
override fun kotlin(configureClosure: Closure<Any?>): SourceDirectorySet = kotlin.apply { executeClosure(configureClosure) }
|
||||
|
||||
override fun getName(): String = displayName
|
||||
|
||||
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||
DefaultKotlinDependencyHandler(this, project).run(configure)
|
||||
|
||||
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||
dependencies f@{ this@f.executeClosure(configureClosure) }
|
||||
|
||||
override fun toString(): String = "source set $name"
|
||||
}
|
||||
|
||||
class AndroidSourceSet
|
||||
|
||||
internal fun KotlinSourceSet.disambiguateName(simpleName: String): String {
|
||||
val nameParts = listOfNotNull(this.name.takeIf { it != "main" }, simpleName)
|
||||
return lowerCamelCaseName(*nameParts.toTypedArray())
|
||||
}
|
||||
|
||||
private val createDefaultSourceDirectorySet: (name: String?, resolver: FileResolver?) -> SourceDirectorySet = run {
|
||||
val klass = DefaultSourceDirectorySet::class.java
|
||||
val defaultConstructor = klass.constructorOrNull(String::class.java, FileResolver::class.java)
|
||||
|
||||
if (defaultConstructor != null && defaultConstructor.getAnnotation(java.lang.Deprecated::class.java) == null) {
|
||||
// TODO: drop when gradle < 2.12 are obsolete
|
||||
{ name, resolver -> defaultConstructor.newInstance(name, resolver) }
|
||||
} else {
|
||||
val directoryFileTreeFactoryClass = Class.forName("org.gradle.api.internal.file.collections.DirectoryFileTreeFactory")
|
||||
val alternativeConstructor = klass.getConstructor(String::class.java, FileResolver::class.java, directoryFileTreeFactoryClass)
|
||||
|
||||
val defaultFileTreeFactoryClass = Class.forName("org.gradle.api.internal.file.collections.DefaultDirectoryFileTreeFactory")
|
||||
val defaultFileTreeFactory = defaultFileTreeFactoryClass.getConstructor().newInstance()
|
||||
return@run { name, resolver -> alternativeConstructor.newInstance(name, resolver, defaultFileTreeFactory) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> Class<T>.constructorOrNull(vararg parameterTypes: Class<*>): Constructor<T>? =
|
||||
try {
|
||||
getConstructor(*parameterTypes)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
null
|
||||
}
|
||||
@@ -7,12 +7,9 @@ package org.jetbrains.kotlin.gradle.scripting.internal
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.scripting.ScriptingExtension
|
||||
|
||||
class ScriptingGradleSubplugin : Plugin<Project> {
|
||||
@@ -39,10 +36,10 @@ class ScriptingKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
if (!ScriptingGradleSubplugin.isEnabled(project)) return emptyList()
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
package org.jetbrains.kotlin.gradle.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleScriptException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.*
|
||||
import org.jetbrains.kotlin.compilerRunner.KonanCompilerRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinNativeProjectProperty
|
||||
import org.jetbrains.kotlin.compilerRunner.getProperty
|
||||
import org.jetbrains.kotlin.compilerRunner.hasProperty
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.MetaVersion
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
import org.jetbrains.kotlin.konan.util.DependencySource
|
||||
import java.io.IOException
|
||||
|
||||
// TODO: It's just a temporary task used while KN isn't integrated with Big Kotlin compilation infrastructure.
|
||||
|
||||
open class KotlinNativeCompile: DefaultTask() {
|
||||
|
||||
init {
|
||||
super.dependsOn(KonanCompilerDownloadTask.KONAN_DOWNLOAD_TASK_NAME)
|
||||
}
|
||||
|
||||
@Internal
|
||||
lateinit var compilation: KotlinNativeCompilation
|
||||
|
||||
// region inputs/outputs
|
||||
@Input
|
||||
lateinit var outputKind: CompilerOutputKind
|
||||
|
||||
// Inputs and outputs
|
||||
|
||||
val sources: Collection<FileCollection>
|
||||
@InputFiles get() = compilation.kotlinSourceSets.map { it.kotlin }
|
||||
|
||||
val libraries: FileCollection
|
||||
@InputFiles get() = compilation.compileDependencyFiles.filter {
|
||||
it.extension == "klib"
|
||||
}
|
||||
|
||||
@Input var optimized = false
|
||||
@Input var debuggable = true
|
||||
|
||||
val processTests
|
||||
@Input get() = compilation.isTestCompilation
|
||||
|
||||
val target: String
|
||||
@Input get() = compilation.target.konanTarget.name
|
||||
|
||||
val additionalCompilerOptions: Collection<String>
|
||||
@Input get() = compilation.extraOpts
|
||||
|
||||
|
||||
@OutputFile val outputFile: RegularFileProperty = newOutputFile()
|
||||
// endregion
|
||||
|
||||
// region Useful extensions
|
||||
internal fun MutableList<String>.addArg(parameter: String, value: String) {
|
||||
add(parameter)
|
||||
add(value)
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addArgs(parameter: String, values: Iterable<String>) {
|
||||
values.forEach {
|
||||
addArg(parameter, it)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addArgIfNotNull(parameter: String, value: String?) {
|
||||
if (value != null) {
|
||||
addArg(parameter, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addKey(key: String, enabled: Boolean) {
|
||||
if (enabled) {
|
||||
add(key)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addFileArgs(parameter: String, values: FileCollection) {
|
||||
values.files.forEach {
|
||||
addArg(parameter, it.canonicalPath)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addFileArgs(parameter: String, values: Collection<FileCollection>) {
|
||||
values.forEach {
|
||||
addFileArgs(parameter, it)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun MutableList<String>.addListArg(parameter: String, values: List<String>) {
|
||||
if (values.isNotEmpty()) {
|
||||
addArg(parameter, values.joinToString(separator = " "))
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
@TaskAction
|
||||
fun compile() {
|
||||
val output = outputFile.asFile.get()
|
||||
output.parentFile.mkdirs()
|
||||
|
||||
val args = mutableListOf<String>().apply {
|
||||
addArg("-o", outputFile.get().asFile.absolutePath)
|
||||
addKey("-opt", optimized)
|
||||
addKey("-g", debuggable)
|
||||
addKey("-ea", debuggable)
|
||||
addKey("-tr", processTests)
|
||||
|
||||
addArg("-target", target)
|
||||
addArg("-p", outputKind.name.toLowerCase())
|
||||
|
||||
add("-Xmulti-platform")
|
||||
|
||||
addAll(additionalCompilerOptions)
|
||||
|
||||
libraries.files.forEach {library ->
|
||||
library.parent?.let { addArg("-r", it) }
|
||||
addArg("-l", library.nameWithoutExtension)
|
||||
}
|
||||
|
||||
// TODO: Filter only kt files?
|
||||
addAll(sources.flatMap { it.files }.map { it.absolutePath })
|
||||
}
|
||||
|
||||
KonanCompilerRunner(project).run(args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open class KonanCompilerDownloadTask : DefaultTask() {
|
||||
|
||||
internal companion object {
|
||||
internal const val BASE_DOWNLOAD_URL = "https://download.jetbrains.com/kotlin/native/builds"
|
||||
const val KONAN_DOWNLOAD_TASK_NAME = "checkKonanCompiler"
|
||||
}
|
||||
|
||||
private val simpleOsName: String = HostManager.simpleOsName()
|
||||
|
||||
private val konanCompilerName: String =
|
||||
"kotlin-native-$simpleOsName-${KonanVersion.CURRENT}"
|
||||
|
||||
@TaskAction
|
||||
fun downloadAndExtract() {
|
||||
if (!project.hasProperty(KotlinNativeProjectProperty.DOWNLOAD_COMPILER)) {
|
||||
val konanHome = project.getProperty(KotlinNativeProjectProperty.KONAN_HOME)
|
||||
logger.info("Use a user-defined compiler path: $konanHome")
|
||||
} else {
|
||||
try {
|
||||
val downloadUrlDirectory = buildString {
|
||||
append("$BASE_DOWNLOAD_URL/")
|
||||
val version = KonanVersion.CURRENT
|
||||
when (version.meta) {
|
||||
MetaVersion.DEV -> append("dev/")
|
||||
else -> append("releases/")
|
||||
}
|
||||
append("$version/")
|
||||
append(simpleOsName)
|
||||
}
|
||||
val konanCompiler = konanCompilerName
|
||||
val parentDir = DependencyProcessor.localKonanDir
|
||||
logger.info("Downloading Kotlin/Native compiler from $downloadUrlDirectory/$konanCompiler into $parentDir")
|
||||
DependencyProcessor(
|
||||
parentDir,
|
||||
downloadUrlDirectory,
|
||||
mapOf(konanCompiler to listOf(DependencySource.Remote.Public))
|
||||
).run()
|
||||
} catch (e: IOException) {
|
||||
throw GradleScriptException("Cannot download Kotlin/Native compiler", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,7 +272,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
args.verbose = true
|
||||
}
|
||||
|
||||
args.multiPlatform = project.plugins.any { it is KotlinPlatformPluginBase }
|
||||
args.multiPlatform = project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper }
|
||||
|
||||
setupPlugins(args)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.utils
|
||||
|
||||
import org.gradle.api.NamedDomainObjectCollection
|
||||
|
||||
/**
|
||||
* Applies [whenMatched] to pairs of items with the same name in [containerA] and [containerB],
|
||||
* regardless of the order in which they are added to the containers.
|
||||
*/
|
||||
internal fun <A, B> matchSymmetricallyByNames(
|
||||
containerA: NamedDomainObjectCollection<out A>,
|
||||
containerB: NamedDomainObjectCollection<out B>,
|
||||
whenMatched: (A, B) -> Unit
|
||||
) {
|
||||
val matchedNames = mutableSetOf<String>()
|
||||
|
||||
fun <T, R> NamedDomainObjectCollection<T>.matchAllWith(other: NamedDomainObjectCollection<R>, match: (T, R) -> Unit) {
|
||||
this@matchAllWith.all { item ->
|
||||
val itemName = this@matchAllWith.namer.determineName(item)
|
||||
if (itemName !in matchedNames) {
|
||||
val otherItem = other.findByName(itemName)
|
||||
if (otherItem != null) {
|
||||
matchedNames += itemName
|
||||
match(item, otherItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
containerA.matchAllWith(containerB) { a, b -> whenMatched(a, b) }
|
||||
containerB.matchAllWith(containerA) { b, a -> whenMatched(a, b) }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.utils
|
||||
|
||||
internal fun lowerCamelCaseName(vararg nameParts: String?): String {
|
||||
val nonEmptyParts = nameParts.mapNotNull { it?.takeIf(String::isNotEmpty) }
|
||||
return nonEmptyParts.drop(1).joinToString(
|
||||
separator = "",
|
||||
prefix = nonEmptyParts.firstOrNull().orEmpty(),
|
||||
transform = String::capitalize
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
implementation-class=org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
|
||||
@@ -18,15 +18,11 @@ package org.jetbrains.kotlin.noarg.gradle
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
|
||||
class NoArgGradleSubplugin : Plugin<Project> {
|
||||
companion object {
|
||||
@@ -54,12 +50,12 @@ class NoArgKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
|
||||
override fun isApplicable(project: Project, task: AbstractCompile) = NoArgGradleSubplugin.isEnabled(project)
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
if (!NoArgGradleSubplugin.isEnabled(project)) return emptyList()
|
||||
|
||||
|
||||
@@ -18,15 +18,11 @@ package org.jetbrains.kotlin.samWithReceiver.gradle
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.internal.ConventionTask
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.internal.AbstractTask
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.JetBrainsSubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.source.KotlinSourceSet
|
||||
|
||||
class SamWithReceiverGradleSubplugin : Plugin<Project> {
|
||||
companion object {
|
||||
@@ -49,12 +45,12 @@ class SamWithReceiverKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompi
|
||||
override fun isApplicable(project: Project, task: AbstractCompile) = SamWithReceiverGradleSubplugin.isEnabled(project)
|
||||
|
||||
override fun apply(
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
javaSourceSet: SourceSet?
|
||||
project: Project,
|
||||
kotlinCompile: AbstractCompile,
|
||||
javaCompile: AbstractCompile?,
|
||||
variantData: Any?,
|
||||
androidProjectHandler: Any?,
|
||||
kotlinCompilation: KotlinCompilation?
|
||||
): List<SubpluginOption> {
|
||||
if (!SamWithReceiverGradleSubplugin.isEnabled(project)) return emptyList()
|
||||
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.teamcityServer
|
||||
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.tc
|
||||
|
||||
description = "Kotlin IDEA plugin"
|
||||
|
||||
plugins {
|
||||
`java-base`
|
||||
id("com.github.jk1.tcdeps") version "0.17"
|
||||
}
|
||||
|
||||
repositories {
|
||||
teamcityServer {
|
||||
setUrl("http://buildserver.labs.intellij.net")
|
||||
credentials {
|
||||
username = "guest"
|
||||
password = "guest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinNativeVersion = "0.9-dev-2798"
|
||||
|
||||
// Do not rename, used in JPS importer
|
||||
val projectsToShadow by extra(listOf(
|
||||
":plugins:annotation-based-compiler-plugins-ide-support",
|
||||
@@ -29,8 +44,10 @@ val projectsToShadow by extra(listOf(
|
||||
":compiler:frontend.script",
|
||||
":idea:ide-common",
|
||||
":idea",
|
||||
":idea:idea-native",
|
||||
":idea:idea-core",
|
||||
":idea:idea-gradle",
|
||||
":idea:idea-gradle:native",
|
||||
//":idea-ultimate",
|
||||
":compiler:ir.psi2ir",
|
||||
":compiler:ir.tree",
|
||||
@@ -54,6 +71,9 @@ val sideJars by configurations.creating
|
||||
dependencies {
|
||||
packedJars(protobufFull())
|
||||
packedJars(project(":core:builtins", configuration = "builtins"))
|
||||
sideJars(tc("Kotlin_KotlinNative_Master_KotlinNativeLinuxDist:$kotlinNativeVersion:shared.jar"))
|
||||
sideJars(tc("Kotlin_KotlinNative_Master_KotlinNativeLinuxDist:$kotlinNativeVersion:backend.native.jar"))
|
||||
sideJars("org.jetbrains.kotlin:kotlin-native-gradle-plugin:0.9-dev-2809") { isTransitive = false }
|
||||
sideJars(projectDist(":kotlin-script-runtime"))
|
||||
sideJars(projectDist(":kotlin-stdlib"))
|
||||
sideJars(projectDist(":kotlin-reflect"))
|
||||
|
||||
@@ -178,6 +178,12 @@ include ":kotlin-build-common",
|
||||
':kotlin-noarg:plugin-marker',
|
||||
":test-instrumenter"
|
||||
|
||||
def isIncludeNative = true //todo: add property
|
||||
if (isIncludeNative) {
|
||||
include ":idea:idea-native",
|
||||
":idea:idea-gradle:native"
|
||||
}
|
||||
|
||||
def isTeamcityBuild = hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
|
||||
def includeUltimate = hasProperty("intellijUltimateEnabled") && intellijUltimateEnabled != 'false'
|
||||
if (isTeamcityBuild || includeUltimate) {
|
||||
|
||||
Reference in New Issue
Block a user